feat(core): toggle additional prompts in CNW with a flag (#9546)
* feat(core): toggle additional prompts in CNW with a flag * feat(repo): handle cli params with yargs * feat(core): add docs generation * chore(repo): add colors * fix(core): migrate to yargs 17.x * fix(core): update markup generation
This commit is contained in:
parent
66e2c37582
commit
9e06020575
80
docs/generated/cli/create-nx-workspace.md
Normal file
80
docs/generated/cli/create-nx-workspace.md
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
---
|
||||||
|
title: 'create-nx-workspace - CLI command'
|
||||||
|
description: 'Create a new Nx workspace'
|
||||||
|
---
|
||||||
|
|
||||||
|
# create-nx-workspace
|
||||||
|
|
||||||
|
Create a new Nx workspace
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
create-nx-workspace [name] [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
Install `create-nx-workspace` globally to invoke the command directly, or use `npx create-nx-workspace`, `yarn create nx-workspace`, or `pnpx create-nx-workspace`.
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
### allPrompts
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
Show all prompts
|
||||||
|
|
||||||
|
### appName
|
||||||
|
|
||||||
|
The name of the application when a preset with pregenerated app is selected
|
||||||
|
|
||||||
|
### cli
|
||||||
|
|
||||||
|
Choices: `["nx", "angular"]`
|
||||||
|
|
||||||
|
CLI to power the Nx workspace
|
||||||
|
|
||||||
|
### defaultBase
|
||||||
|
|
||||||
|
Default: `main`
|
||||||
|
|
||||||
|
Default base to use for new projects
|
||||||
|
|
||||||
|
### help
|
||||||
|
|
||||||
|
Show help
|
||||||
|
|
||||||
|
### interactive
|
||||||
|
|
||||||
|
Enable interactive mode with presets
|
||||||
|
|
||||||
|
### name
|
||||||
|
|
||||||
|
Workspace name (e.g. org name)
|
||||||
|
|
||||||
|
### nxCloud
|
||||||
|
|
||||||
|
Default: `true`
|
||||||
|
|
||||||
|
Use Nx Cloud
|
||||||
|
|
||||||
|
### packageManager
|
||||||
|
|
||||||
|
Default: `npm`
|
||||||
|
|
||||||
|
Choices: `["npm", "pnpm", "yarn"]`
|
||||||
|
|
||||||
|
Package manager to use
|
||||||
|
|
||||||
|
### preset
|
||||||
|
|
||||||
|
Choices: `["apps", "empty", "core", "npm", "ts", "web-components", "angular", "angular-nest", "react", "react-express", "react-native", "next", "nest", "express"]`
|
||||||
|
|
||||||
|
Customizes the initial content of your workspace. To build your own see https://nx.dev/nx-plugin/overview#preset
|
||||||
|
|
||||||
|
### style
|
||||||
|
|
||||||
|
Style option to be used when a preset with pregenerated app is selected
|
||||||
|
|
||||||
|
### version
|
||||||
|
|
||||||
|
Show version number
|
||||||
@ -360,6 +360,11 @@
|
|||||||
"name": "CLI",
|
"name": "CLI",
|
||||||
"id": "cli",
|
"id": "cli",
|
||||||
"itemList": [
|
"itemList": [
|
||||||
|
{
|
||||||
|
"name": "create-nx-workspace",
|
||||||
|
"id": "create-nx-workspace",
|
||||||
|
"file": "generated/cli/create-nx-workspace"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "generate",
|
"name": "generate",
|
||||||
"id": "generate",
|
"id": "generate",
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import {
|
|||||||
copySync,
|
copySync,
|
||||||
createFileSync,
|
createFileSync,
|
||||||
ensureDirSync,
|
ensureDirSync,
|
||||||
|
existsSync,
|
||||||
moveSync,
|
moveSync,
|
||||||
readdirSync,
|
readdirSync,
|
||||||
readFileSync,
|
readFileSync,
|
||||||
@ -28,7 +29,15 @@ import chalk = require('chalk');
|
|||||||
import isCI = require('is-ci');
|
import isCI = require('is-ci');
|
||||||
import treeKill = require('tree-kill');
|
import treeKill = require('tree-kill');
|
||||||
import { Workspaces } from '../../packages/nx/src/shared/workspace';
|
import { Workspaces } from '../../packages/nx/src/shared/workspace';
|
||||||
import { detectPackageManager } from '../../packages/create-nx-workspace/bin/package-manager';
|
import { PackageManager } from 'nx/src/utils/package-manager';
|
||||||
|
|
||||||
|
export function detectPackageManager(dir: string = ''): PackageManager {
|
||||||
|
return existsSync(join(dir, 'yarn.lock'))
|
||||||
|
? 'yarn'
|
||||||
|
: existsSync(join(dir, 'pnpm-lock.yaml'))
|
||||||
|
? 'pnpm'
|
||||||
|
: 'npm';
|
||||||
|
}
|
||||||
|
|
||||||
const kill = require('kill-port');
|
const kill = require('kill-port');
|
||||||
export const isWindows = require('is-windows');
|
export const isWindows = require('is-windows');
|
||||||
|
|||||||
@ -1,24 +1,37 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
import { exec } from 'child_process';
|
import { exec } from 'child_process';
|
||||||
import { writeFileSync } from 'fs';
|
import { writeFileSync } from 'fs';
|
||||||
import * as enquirer from 'enquirer';
|
import * as enquirer from 'enquirer';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { dirSync } from 'tmp';
|
import { dirSync } from 'tmp';
|
||||||
import * as yargsParser from 'yargs-parser';
|
import * as yargs from 'yargs';
|
||||||
import { showNxWarning, unparse } from './shared';
|
import { showNxWarning, unparse } from './shared';
|
||||||
import { output } from './output';
|
import { output } from './output';
|
||||||
import * as ora from 'ora';
|
import * as ora from 'ora';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
detectInvokedPackageManager,
|
detectInvokedPackageManager,
|
||||||
getPackageManagerCommand,
|
getPackageManagerCommand,
|
||||||
getPackageManagerVersion,
|
getPackageManagerVersion,
|
||||||
PackageManager,
|
PackageManager,
|
||||||
|
packageManagerList,
|
||||||
} from './package-manager';
|
} from './package-manager';
|
||||||
import { validateNpmPackage } from './validate-npm-package';
|
import { validateNpmPackage } from './validate-npm-package';
|
||||||
|
import { deduceDefaultBase } from './default-base';
|
||||||
|
import { stringifyCollection } from './utils';
|
||||||
|
import { yargsDecorator } from './decorator';
|
||||||
|
|
||||||
export enum Preset {
|
type Arguments = {
|
||||||
|
name: string;
|
||||||
|
preset: string;
|
||||||
|
appName: string;
|
||||||
|
cli: string;
|
||||||
|
style: string;
|
||||||
|
nxCloud: boolean;
|
||||||
|
allPrompts: boolean;
|
||||||
|
packageManager: string;
|
||||||
|
defaultBase: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Preset {
|
||||||
Apps = 'apps',
|
Apps = 'apps',
|
||||||
Empty = 'empty', // same as apps, deprecated
|
Empty = 'empty', // same as apps, deprecated
|
||||||
Core = 'core',
|
Core = 'core',
|
||||||
@ -101,41 +114,93 @@ const cliVersion = 'NX_VERSION';
|
|||||||
const nxVersion = 'NX_VERSION';
|
const nxVersion = 'NX_VERSION';
|
||||||
const prettierVersion = 'PRETTIER_VERSION';
|
const prettierVersion = 'PRETTIER_VERSION';
|
||||||
|
|
||||||
const parsedArgs: any = yargsParser(process.argv.slice(2), {
|
export const commandsObject: yargs.Argv<Arguments> = yargs
|
||||||
string: [
|
.wrap(yargs.terminalWidth())
|
||||||
'name',
|
.parserConfiguration({
|
||||||
'cli',
|
|
||||||
'preset',
|
|
||||||
'appName',
|
|
||||||
'style',
|
|
||||||
'defaultBase',
|
|
||||||
'packageManager',
|
|
||||||
],
|
|
||||||
alias: {
|
|
||||||
packageManager: 'pm',
|
|
||||||
},
|
|
||||||
boolean: ['help', 'interactive', 'nxCloud'],
|
|
||||||
default: {
|
|
||||||
interactive: false,
|
|
||||||
},
|
|
||||||
configuration: {
|
|
||||||
'strip-dashed': true,
|
'strip-dashed': true,
|
||||||
'strip-aliased': true,
|
'dot-notation': false,
|
||||||
},
|
})
|
||||||
}) as any;
|
.command(
|
||||||
|
// this is the default and only command
|
||||||
|
'$0 [name] [options]',
|
||||||
|
'Create a new Nx workspace',
|
||||||
|
(yargs) =>
|
||||||
|
yargs
|
||||||
|
.option('name', {
|
||||||
|
describe: `Workspace name (e.g. org name)`,
|
||||||
|
type: 'string',
|
||||||
|
})
|
||||||
|
.option('preset', {
|
||||||
|
describe: `Customizes the initial content of your workspace. To build your own see https://nx.dev/nx-plugin/overview#preset`,
|
||||||
|
choices: Object.values(Preset),
|
||||||
|
type: 'string',
|
||||||
|
})
|
||||||
|
.option('appName', {
|
||||||
|
describe: `The name of the application when a preset with pregenerated app is selected`,
|
||||||
|
type: 'string',
|
||||||
|
})
|
||||||
|
.option('interactive', {
|
||||||
|
describe: `Enable interactive mode with presets`,
|
||||||
|
type: 'boolean',
|
||||||
|
})
|
||||||
|
.option('cli', {
|
||||||
|
describe: `CLI to power the Nx workspace`,
|
||||||
|
choices: ['nx', 'angular'],
|
||||||
|
type: 'string',
|
||||||
|
})
|
||||||
|
.option('style', {
|
||||||
|
describe: `Style option to be used when a preset with pregenerated app is selected`,
|
||||||
|
type: 'string',
|
||||||
|
})
|
||||||
|
.option('nxCloud', {
|
||||||
|
describe: `Use Nx Cloud`,
|
||||||
|
defaultDescription: 'true',
|
||||||
|
type: 'boolean',
|
||||||
|
})
|
||||||
|
.option('allPrompts', {
|
||||||
|
alias: 'a',
|
||||||
|
describe: `Show all prompts`,
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
})
|
||||||
|
.option('packageManager', {
|
||||||
|
alias: 'pm',
|
||||||
|
describe: `Package manager to use`,
|
||||||
|
choices: [...packageManagerList].sort(),
|
||||||
|
defaultDescription: 'npm',
|
||||||
|
type: 'string',
|
||||||
|
})
|
||||||
|
.option('defaultBase', {
|
||||||
|
defaultDescription: 'main',
|
||||||
|
describe: `Default base to use for new projects`,
|
||||||
|
type: 'string',
|
||||||
|
}),
|
||||||
|
async (argv: yargs.ArgumentsCamelCase<Arguments>) => {
|
||||||
|
await main(argv).catch((error) => {
|
||||||
|
const { version } = require('../package.json');
|
||||||
|
output.error({
|
||||||
|
title: `Something went wrong! v${version}`,
|
||||||
|
});
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[getConfiguration]
|
||||||
|
)
|
||||||
|
.help('help')
|
||||||
|
.updateLocale(yargsDecorator)
|
||||||
|
.version(nxVersion) as yargs.Argv<Arguments>;
|
||||||
|
|
||||||
if (parsedArgs.help) {
|
async function main(parsedArgs: yargs.Arguments<Arguments>) {
|
||||||
showHelp();
|
const {
|
||||||
process.exit(0);
|
name,
|
||||||
}
|
cli,
|
||||||
|
preset,
|
||||||
(async function main() {
|
appName,
|
||||||
const packageManager: PackageManager =
|
style,
|
||||||
parsedArgs.packageManager || detectInvokedPackageManager();
|
nxCloud,
|
||||||
|
packageManager,
|
||||||
const { name, cli, preset, appName, style, nxCloud } = await getConfiguration(
|
defaultBase,
|
||||||
parsedArgs
|
} = parsedArgs;
|
||||||
);
|
|
||||||
|
|
||||||
output.log({
|
output.log({
|
||||||
title: `Nx is creating your v${cliVersion} workspace.`,
|
title: `Nx is creating your v${cliVersion} workspace.`,
|
||||||
@ -147,101 +212,73 @@ if (parsedArgs.help) {
|
|||||||
|
|
||||||
const tmpDir = await createSandbox(packageManager);
|
const tmpDir = await createSandbox(packageManager);
|
||||||
|
|
||||||
await createApp(tmpDir, name, packageManager, {
|
await createApp(tmpDir, name, packageManager as PackageManager, {
|
||||||
...parsedArgs,
|
...parsedArgs,
|
||||||
cli,
|
cli,
|
||||||
preset,
|
preset,
|
||||||
appName,
|
appName,
|
||||||
style,
|
style,
|
||||||
nxCloud,
|
nxCloud,
|
||||||
|
defaultBase,
|
||||||
});
|
});
|
||||||
|
|
||||||
let nxCloudInstallRes;
|
let nxCloudInstallRes;
|
||||||
if (nxCloud) {
|
if (nxCloud) {
|
||||||
nxCloudInstallRes = await setupNxCloud(name, packageManager);
|
nxCloudInstallRes = await setupNxCloud(
|
||||||
|
name,
|
||||||
|
packageManager as PackageManager
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
showNxWarning(name);
|
showNxWarning(name);
|
||||||
pointToTutorialAndCourse(preset);
|
pointToTutorialAndCourse(preset as Preset);
|
||||||
|
|
||||||
if (nxCloud && nxCloudInstallRes.code === 0) {
|
if (nxCloud && nxCloudInstallRes.code === 0) {
|
||||||
printNxCloudSuccessMessage(nxCloudInstallRes.stdout);
|
printNxCloudSuccessMessage(nxCloudInstallRes.stdout);
|
||||||
}
|
}
|
||||||
})().catch((error) => {
|
|
||||||
const { version } = require('../package.json');
|
|
||||||
output.error({
|
|
||||||
title: `Something went wrong! v${version}`,
|
|
||||||
});
|
|
||||||
throw error;
|
|
||||||
});
|
|
||||||
|
|
||||||
function showHelp() {
|
|
||||||
const options = Object.values(Preset)
|
|
||||||
.map((preset) => `"${preset}"`)
|
|
||||||
.join(', ');
|
|
||||||
|
|
||||||
console.log(`
|
|
||||||
Usage: create-nx-workspace <name> [options] [new workspace options]
|
|
||||||
|
|
||||||
Create a new Nx workspace
|
|
||||||
|
|
||||||
Options:
|
|
||||||
|
|
||||||
name Workspace name (e.g., org name)
|
|
||||||
|
|
||||||
preset Customizes the initial content of your workspace (options: ${options}). To build your own see https://nx.dev/nx-plugin/overview#preset
|
|
||||||
|
|
||||||
appName The name of the application created by some presets
|
|
||||||
|
|
||||||
cli CLI to power the Nx workspace (options: "nx", "angular")
|
|
||||||
|
|
||||||
style Default style option to be used when a non-empty preset is selected
|
|
||||||
options: ("css", "scss", "less") plus ("styl") for all non-Angular and ("styled-components", "@emotion/styled", "styled-jsx") for React, Next.js
|
|
||||||
|
|
||||||
interactive Enable interactive mode when using presets (boolean)
|
|
||||||
|
|
||||||
packageManager Package manager to use (alias: "pm")
|
|
||||||
options: ("npm", "yarn", "pnpm")
|
|
||||||
|
|
||||||
defaultBase Name of the main branch (default: "main")
|
|
||||||
|
|
||||||
nx-cloud Use Nx Cloud (boolean)
|
|
||||||
`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getConfiguration(parsedArgs) {
|
async function getConfiguration(
|
||||||
|
argv: yargs.Arguments<Arguments>
|
||||||
|
): Promise<void> {
|
||||||
try {
|
try {
|
||||||
let style, appName;
|
let style, appName;
|
||||||
|
|
||||||
const name = await determineWorkspaceName(parsedArgs);
|
const name = await determineWorkspaceName(argv);
|
||||||
let preset = await determineThirdPartyPackage(parsedArgs);
|
let preset = await determineThirdPartyPackage(argv);
|
||||||
|
|
||||||
if (!preset) {
|
if (!preset) {
|
||||||
preset = await determinePreset(parsedArgs);
|
preset = await determinePreset(argv);
|
||||||
appName = await determineAppName(preset, parsedArgs);
|
appName = await determineAppName(preset, argv);
|
||||||
style = await determineStyle(preset, parsedArgs);
|
style = await determineStyle(preset, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
const cli = await determineCli(preset, parsedArgs);
|
const cli = await determineCli(preset, argv);
|
||||||
const nxCloud = await askAboutNxCloud(parsedArgs);
|
const packageManager = await determinePackageManager(argv);
|
||||||
|
const defaultBase = await determineDefaultBase(argv);
|
||||||
|
const nxCloud = await determineNxCloud(argv);
|
||||||
|
|
||||||
return {
|
Object.assign(argv, {
|
||||||
name,
|
name,
|
||||||
preset,
|
preset,
|
||||||
appName,
|
appName,
|
||||||
style,
|
style,
|
||||||
cli,
|
cli,
|
||||||
nxCloud,
|
nxCloud,
|
||||||
};
|
packageManager,
|
||||||
|
defaultBase,
|
||||||
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function determineWorkspaceName(parsedArgs: any): Promise<string> {
|
function determineWorkspaceName(
|
||||||
|
parsedArgs: yargs.Arguments<Arguments>
|
||||||
|
): Promise<string> {
|
||||||
const workspaceName: string = parsedArgs._[0]
|
const workspaceName: string = parsedArgs._[0]
|
||||||
? parsedArgs._[0]
|
? parsedArgs._[0].toString()
|
||||||
: parsedArgs.name;
|
: parsedArgs.name;
|
||||||
|
|
||||||
if (workspaceName) {
|
if (workspaceName) {
|
||||||
@ -268,8 +305,85 @@ function determineWorkspaceName(parsedArgs: any): Promise<string> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function determineThirdPartyPackage({ preset }) {
|
async function determinePackageManager(
|
||||||
if (preset && Object.values(Preset).indexOf(preset) === -1) {
|
parsedArgs: yargs.Arguments<Arguments>
|
||||||
|
): Promise<PackageManager> {
|
||||||
|
const packageManager: string = parsedArgs.packageManager;
|
||||||
|
|
||||||
|
if (packageManager) {
|
||||||
|
if (packageManagerList.includes(packageManager as PackageManager)) {
|
||||||
|
return Promise.resolve(packageManager as PackageManager);
|
||||||
|
}
|
||||||
|
output.error({
|
||||||
|
title: 'Invalid package manager',
|
||||||
|
bodyLines: [
|
||||||
|
`Package manager must be one of ${stringifyCollection([
|
||||||
|
...packageManagerList,
|
||||||
|
])}`,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parsedArgs.allPrompts) {
|
||||||
|
return enquirer
|
||||||
|
.prompt([
|
||||||
|
{
|
||||||
|
name: 'PackageManager',
|
||||||
|
message: `Which package manager to use `,
|
||||||
|
initial: 'npm' as any,
|
||||||
|
type: 'select',
|
||||||
|
choices: [
|
||||||
|
{ name: 'npm', message: 'NPM' },
|
||||||
|
{ name: 'yarn', message: 'Yarn' },
|
||||||
|
{ name: 'pnpm', message: 'PNPM' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.then((a: { PackageManager }) => a.PackageManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve(detectInvokedPackageManager());
|
||||||
|
}
|
||||||
|
|
||||||
|
async function determineDefaultBase(
|
||||||
|
parsedArgs: yargs.Arguments<Arguments>
|
||||||
|
): Promise<string> {
|
||||||
|
if (parsedArgs.defaultBase) {
|
||||||
|
return Promise.resolve(parsedArgs.defaultBase);
|
||||||
|
}
|
||||||
|
if (parsedArgs.allPrompts) {
|
||||||
|
return enquirer
|
||||||
|
.prompt([
|
||||||
|
{
|
||||||
|
name: 'DefaultBase',
|
||||||
|
message: `Main branch name `,
|
||||||
|
initial: `main`,
|
||||||
|
type: 'input',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.then((a: { DefaultBase: string }) => {
|
||||||
|
if (!a.DefaultBase) {
|
||||||
|
output.error({
|
||||||
|
title: 'Invalid branch name',
|
||||||
|
bodyLines: [`Branch name cannot be empty`],
|
||||||
|
});
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
return a.DefaultBase;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.resolve(deduceDefaultBase());
|
||||||
|
}
|
||||||
|
|
||||||
|
function isKnownPreset(preset: string): preset is Preset {
|
||||||
|
return Object.values(Preset).includes(preset as Preset);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function determineThirdPartyPackage({
|
||||||
|
preset,
|
||||||
|
}: yargs.Arguments<Arguments>) {
|
||||||
|
if (preset && !isKnownPreset(preset)) {
|
||||||
const packageName = preset.match(/.+@/)
|
const packageName = preset.match(/.+@/)
|
||||||
? preset[0] + preset.substring(1).split('@')[0]
|
? preset[0] + preset.substring(1).split('@')[0]
|
||||||
: preset;
|
: preset;
|
||||||
@ -293,7 +407,7 @@ async function determineThirdPartyPackage({ preset }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function determinePreset(parsedArgs: any): Promise<Preset> {
|
async function determinePreset(parsedArgs: any): Promise<Preset> {
|
||||||
if (parsedArgs.preset) {
|
if (parsedArgs.preset) {
|
||||||
if (Object.values(Preset).indexOf(parsedArgs.preset) === -1) {
|
if (Object.values(Preset).indexOf(parsedArgs.preset) === -1) {
|
||||||
output.error({
|
output.error({
|
||||||
@ -323,7 +437,10 @@ function determinePreset(parsedArgs: any): Promise<Preset> {
|
|||||||
.then((a: { Preset: Preset }) => a.Preset);
|
.then((a: { Preset: Preset }) => a.Preset);
|
||||||
}
|
}
|
||||||
|
|
||||||
function determineAppName(preset: Preset, parsedArgs: any): Promise<string> {
|
async function determineAppName(
|
||||||
|
preset: Preset,
|
||||||
|
parsedArgs: yargs.Arguments<Arguments>
|
||||||
|
): Promise<string> {
|
||||||
if (
|
if (
|
||||||
preset === Preset.Apps ||
|
preset === Preset.Apps ||
|
||||||
preset === Preset.Core ||
|
preset === Preset.Core ||
|
||||||
@ -358,12 +475,16 @@ function determineAppName(preset: Preset, parsedArgs: any): Promise<string> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function determineCli(
|
function isValidCli(cli: string): cli is 'angular' | 'nx' {
|
||||||
|
return ['nx', 'angular'].indexOf(cli) !== -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function determineCli(
|
||||||
preset: Preset,
|
preset: Preset,
|
||||||
parsedArgs: any
|
parsedArgs: yargs.Arguments<Arguments>
|
||||||
): Promise<'nx' | 'angular'> {
|
): Promise<'nx' | 'angular'> {
|
||||||
if (parsedArgs.cli) {
|
if (parsedArgs.cli) {
|
||||||
if (['nx', 'angular'].indexOf(parsedArgs.cli) === -1) {
|
if (!isValidCli(parsedArgs.cli)) {
|
||||||
output.error({
|
output.error({
|
||||||
title: 'Invalid cli',
|
title: 'Invalid cli',
|
||||||
bodyLines: [`It must be one of the following:`, '', 'nx', 'angular'],
|
bodyLines: [`It must be one of the following:`, '', 'nx', 'angular'],
|
||||||
@ -384,7 +505,10 @@ function determineCli(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function determineStyle(preset: Preset, parsedArgs: any) {
|
async function determineStyle(
|
||||||
|
preset: Preset,
|
||||||
|
parsedArgs: yargs.Arguments<Arguments>
|
||||||
|
) {
|
||||||
if (
|
if (
|
||||||
preset === Preset.Apps ||
|
preset === Preset.Apps ||
|
||||||
preset === Preset.Core ||
|
preset === Preset.Core ||
|
||||||
@ -625,7 +749,7 @@ function execAndWait(command: string, cwd: string) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function askAboutNxCloud(parsedArgs: any) {
|
async function determineNxCloud(parsedArgs: yargs.Arguments<Arguments>) {
|
||||||
if (parsedArgs.nxCloud === undefined) {
|
if (parsedArgs.nxCloud === undefined) {
|
||||||
return enquirer
|
return enquirer
|
||||||
.prompt([
|
.prompt([
|
||||||
|
|||||||
6
packages/create-nx-workspace/bin/decorator.ts
Normal file
6
packages/create-nx-workspace/bin/decorator.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import * as chalk from 'chalk';
|
||||||
|
|
||||||
|
export const yargsDecorator = {
|
||||||
|
'Options:': `${chalk.bold('Options')}:`,
|
||||||
|
'Positionals:': `${chalk.bold('Positionals')}:`,
|
||||||
|
};
|
||||||
17
packages/create-nx-workspace/bin/default-base.ts
Normal file
17
packages/create-nx-workspace/bin/default-base.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { execSync } from 'child_process';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Because we don't want to depend on @nrwl/workspace (to speed up the workspace creation)
|
||||||
|
* we duplicate the helper functions from @nrwl/workspace in this file.
|
||||||
|
*/
|
||||||
|
export function deduceDefaultBase(): string {
|
||||||
|
const nxDefaultBase = 'main';
|
||||||
|
try {
|
||||||
|
return (
|
||||||
|
execSync('git config --get init.defaultBranch').toString().trim() ||
|
||||||
|
nxDefaultBase
|
||||||
|
);
|
||||||
|
} catch {
|
||||||
|
return nxDefaultBase;
|
||||||
|
}
|
||||||
|
}
|
||||||
5
packages/create-nx-workspace/bin/index.ts
Normal file
5
packages/create-nx-workspace/bin/index.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
import { commandsObject } from './create-nx-workspace';
|
||||||
|
|
||||||
|
commandsObject.argv;
|
||||||
@ -7,7 +7,7 @@ import { join } from 'path';
|
|||||||
* we duplicate the helper functions from @nrwl/workspace in this file.
|
* we duplicate the helper functions from @nrwl/workspace in this file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const packageManagerList = ['pnpm', 'yarn', 'npm'] as const;
|
export const packageManagerList = ['pnpm', 'yarn', 'npm'] as const;
|
||||||
|
|
||||||
export type PackageManager = typeof packageManagerList[number];
|
export type PackageManager = typeof packageManagerList[number];
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ export function detectInvokedPackageManager(): PackageManager {
|
|||||||
if (!invoker) {
|
if (!invoker) {
|
||||||
return detectedPackageManager;
|
return detectedPackageManager;
|
||||||
}
|
}
|
||||||
|
console.log(invoker.path);
|
||||||
for (const pkgManager of packageManagerList) {
|
for (const pkgManager of packageManagerList) {
|
||||||
if (invoker.path.includes(pkgManager)) {
|
if (invoker.path.includes(pkgManager)) {
|
||||||
detectedPackageManager = pkgManager;
|
detectedPackageManager = pkgManager;
|
||||||
|
|||||||
3
packages/create-nx-workspace/bin/utils.ts
Normal file
3
packages/create-nx-workspace/bin/utils.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export function stringifyCollection(items: string[]): string {
|
||||||
|
return items.map((item) => `"${item}"`).join(', ');
|
||||||
|
}
|
||||||
@ -19,7 +19,7 @@
|
|||||||
"CLI"
|
"CLI"
|
||||||
],
|
],
|
||||||
"bin": {
|
"bin": {
|
||||||
"create-nx-workspace": "./bin/create-nx-workspace.js"
|
"create-nx-workspace": "./bin/index.js"
|
||||||
},
|
},
|
||||||
"author": "Victor Savkin",
|
"author": "Victor Savkin",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -29,7 +29,7 @@
|
|||||||
"homepage": "https://nx.dev",
|
"homepage": "https://nx.dev",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tmp": "~0.2.1",
|
"tmp": "~0.2.1",
|
||||||
"yargs-parser": "21.0.1",
|
"yargs": "^17.4.0",
|
||||||
"enquirer": "~2.3.6",
|
"enquirer": "~2.3.6",
|
||||||
"flat": "^5.0.2",
|
"flat": "^5.0.2",
|
||||||
"chalk": "4.1.0",
|
"chalk": "4.1.0",
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import { execSync } from 'child_process';
|
import { execSync } from 'child_process';
|
||||||
|
|
||||||
// TODO (v13): Update to main
|
|
||||||
export function deduceDefaultBase(): string {
|
export function deduceDefaultBase(): string {
|
||||||
const nxDefaultBase = 'main';
|
const nxDefaultBase = 'main';
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
import * as chalk from 'chalk';
|
import * as chalk from 'chalk';
|
||||||
import { execSync } from 'child_process';
|
import { execSync } from 'child_process';
|
||||||
|
import { removeSync } from 'fs-extra';
|
||||||
|
import { join } from 'path';
|
||||||
import { generateCLIDocumentation } from './generate-cli-data';
|
import { generateCLIDocumentation } from './generate-cli-data';
|
||||||
|
import { generateCNWocumentation } from './generate-cnw-documentation';
|
||||||
import { generateDevkitDocumentation } from './generate-devkit-documentation';
|
import { generateDevkitDocumentation } from './generate-devkit-documentation';
|
||||||
import { generatePackageSchemas } from './package-schemas/generatePackageSchemas';
|
import { generatePackageSchemas } from './package-schemas/generatePackageSchemas';
|
||||||
|
|
||||||
@ -9,7 +12,16 @@ async function generate() {
|
|||||||
console.log(`${chalk.blue('i')} Generating Documentation`);
|
console.log(`${chalk.blue('i')} Generating Documentation`);
|
||||||
generatePackageSchemas();
|
generatePackageSchemas();
|
||||||
generateDevkitDocumentation();
|
generateDevkitDocumentation();
|
||||||
await generateCLIDocumentation();
|
|
||||||
|
const commandsOutputDirectory = join(
|
||||||
|
__dirname,
|
||||||
|
'../../docs/',
|
||||||
|
'generated',
|
||||||
|
'cli'
|
||||||
|
);
|
||||||
|
removeSync(commandsOutputDirectory);
|
||||||
|
await generateCNWocumentation(commandsOutputDirectory);
|
||||||
|
await generateCLIDocumentation(commandsOutputDirectory);
|
||||||
|
|
||||||
console.log(`\n${chalk.green('✓')} Generated Documentation\n`);
|
console.log(`\n${chalk.green('✓')} Generated Documentation\n`);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@ -1,16 +1,19 @@
|
|||||||
import * as chalk from 'chalk';
|
import * as chalk from 'chalk';
|
||||||
import { readFileSync } from 'fs';
|
import { readFileSync } from 'fs';
|
||||||
import { readJsonSync, removeSync } from 'fs-extra';
|
import { readJsonSync } from 'fs-extra';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { dedent } from 'tslint/lib/utils';
|
|
||||||
import {
|
import {
|
||||||
formatDeprecated,
|
formatDeprecated,
|
||||||
generateMarkdownFile,
|
generateMarkdownFile,
|
||||||
|
generateOptionsMarkdown,
|
||||||
|
getCommands,
|
||||||
|
parseCommand,
|
||||||
|
ParsedCommand,
|
||||||
sortAlphabeticallyFunction,
|
sortAlphabeticallyFunction,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
import { register as registerTsConfigPaths } from 'tsconfig-paths';
|
import { register as registerTsConfigPaths } from 'tsconfig-paths';
|
||||||
|
|
||||||
import { examples } from '../../packages/nx/src/command-line/examples';
|
import { examples } from '../../packages/nx/src/command-line/examples';
|
||||||
|
import { dedent } from 'tslint/lib/utils';
|
||||||
|
|
||||||
const importFresh = require('import-fresh');
|
const importFresh = require('import-fresh');
|
||||||
|
|
||||||
@ -24,21 +27,9 @@ const sharedCommands = [
|
|||||||
'test',
|
'test',
|
||||||
];
|
];
|
||||||
|
|
||||||
interface ParsedCommandOption {
|
export async function generateCLIDocumentation(
|
||||||
name: string;
|
commandsOutputDirectory: string
|
||||||
description: string;
|
) {
|
||||||
default: string;
|
|
||||||
deprecated: boolean | string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ParsedCommand {
|
|
||||||
name: string;
|
|
||||||
commandString: string;
|
|
||||||
description: string;
|
|
||||||
options?: Array<ParsedCommandOption>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function generateCLIDocumentation() {
|
|
||||||
/**
|
/**
|
||||||
* For certain commands, they will output dynamic data at runtime in a real workspace,
|
* For certain commands, they will output dynamic data at runtime in a real workspace,
|
||||||
* so we leverage an envrionment variable to inform the logic of the context that we
|
* so we leverage an envrionment variable to inform the logic of the context that we
|
||||||
@ -57,65 +48,6 @@ export async function generateCLIDocumentation() {
|
|||||||
'../../packages/nx/src/command-line/nx-commands'
|
'../../packages/nx/src/command-line/nx-commands'
|
||||||
);
|
);
|
||||||
|
|
||||||
const commandsOutputDirectory = join(
|
|
||||||
__dirname,
|
|
||||||
'../../docs/',
|
|
||||||
'generated',
|
|
||||||
'cli'
|
|
||||||
);
|
|
||||||
removeSync(commandsOutputDirectory);
|
|
||||||
|
|
||||||
function getCommands(command) {
|
|
||||||
return command
|
|
||||||
.getInternalMethods()
|
|
||||||
.getCommandInstance()
|
|
||||||
.getCommandHandlers();
|
|
||||||
}
|
|
||||||
async function parseCommandInstance(
|
|
||||||
name: string,
|
|
||||||
command: any
|
|
||||||
): Promise<ParsedCommand> {
|
|
||||||
// It is not a function return a strip down version of the command
|
|
||||||
if (
|
|
||||||
!(
|
|
||||||
command.builder &&
|
|
||||||
command.builder.constructor &&
|
|
||||||
command.builder.call &&
|
|
||||||
command.builder.apply
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return {
|
|
||||||
name,
|
|
||||||
commandString: command.original,
|
|
||||||
description: command.description,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// Show all the options we can get from yargs
|
|
||||||
const builder = await command.builder(
|
|
||||||
importFresh('yargs')().getInternalMethods().reset()
|
|
||||||
);
|
|
||||||
const builderDescriptions = builder
|
|
||||||
.getInternalMethods()
|
|
||||||
.getUsageInstance()
|
|
||||||
.getDescriptions();
|
|
||||||
const builderDefaultOptions = builder.getOptions().default;
|
|
||||||
const builderDeprecatedOptions = builder.getDeprecatedOptions();
|
|
||||||
return {
|
|
||||||
name,
|
|
||||||
description: command.description,
|
|
||||||
commandString: command.original,
|
|
||||||
options:
|
|
||||||
Object.keys(builderDescriptions).map((key) => ({
|
|
||||||
name: key,
|
|
||||||
description: builderDescriptions[key]
|
|
||||||
? builderDescriptions[key].replace('__yargsString__:', '')
|
|
||||||
: '',
|
|
||||||
default: builderDefaultOptions[key],
|
|
||||||
deprecated: builderDeprecatedOptions[key],
|
|
||||||
})) || null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateMarkdown(command: ParsedCommand) {
|
function generateMarkdown(command: ParsedCommand) {
|
||||||
let template = dedent`
|
let template = dedent`
|
||||||
---
|
---
|
||||||
@ -146,25 +78,7 @@ nx ${command.commandString}
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Array.isArray(command.options) && !!command.options.length) {
|
template += generateOptionsMarkdown(command);
|
||||||
template += '\n## Options';
|
|
||||||
|
|
||||||
command.options
|
|
||||||
.sort((a, b) => sortAlphabeticallyFunction(a.name, b.name))
|
|
||||||
.forEach((option) => {
|
|
||||||
template += dedent`
|
|
||||||
### ${option.deprecated ? `~~${option.name}~~` : option.name}
|
|
||||||
${
|
|
||||||
option.default === undefined || option.default === ''
|
|
||||||
? ''
|
|
||||||
: `Default: \`${option.default}\`\n`
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
template += dedent`
|
|
||||||
${formatDeprecated(option.description, option.deprecated)}
|
|
||||||
`;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: command.name
|
name: command.name
|
||||||
@ -181,7 +95,7 @@ nx ${command.commandString}
|
|||||||
Object.keys(nxCommands)
|
Object.keys(nxCommands)
|
||||||
.filter((name) => !sharedCommands.includes(name))
|
.filter((name) => !sharedCommands.includes(name))
|
||||||
.filter((name) => nxCommands[name].description)
|
.filter((name) => nxCommands[name].description)
|
||||||
.map((name) => parseCommandInstance(name, nxCommands[name]))
|
.map((name) => parseCommand(name, nxCommands[name]))
|
||||||
.map(async (command) => generateMarkdown(await command))
|
.map(async (command) => generateMarkdown(await command))
|
||||||
.map(async (templateObject) =>
|
.map(async (templateObject) =>
|
||||||
generateMarkdownFile(commandsOutputDirectory, await templateObject)
|
generateMarkdownFile(commandsOutputDirectory, await templateObject)
|
||||||
|
|||||||
65
scripts/documentation/generate-cnw-documentation.ts
Normal file
65
scripts/documentation/generate-cnw-documentation.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import * as chalk from 'chalk';
|
||||||
|
import { dedent } from 'tslint/lib/utils';
|
||||||
|
import {
|
||||||
|
generateMarkdownFile,
|
||||||
|
getCommands,
|
||||||
|
parseCommand,
|
||||||
|
ParsedCommand,
|
||||||
|
sortAlphabeticallyFunction,
|
||||||
|
formatDeprecated,
|
||||||
|
generateOptionsMarkdown,
|
||||||
|
} from './utils';
|
||||||
|
const importFresh = require('import-fresh');
|
||||||
|
|
||||||
|
export async function generateCNWocumentation(commandsOutputDirectory: string) {
|
||||||
|
process.env.NX_GENERATE_DOCS_PROCESS = 'true';
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`\n${chalk.blue(
|
||||||
|
'i'
|
||||||
|
)} Generating Documentation for Create Nx Workspace Command`
|
||||||
|
);
|
||||||
|
|
||||||
|
const { commandsObject } = importFresh(
|
||||||
|
'../../packages/create-nx-workspace/bin/create-nx-workspace'
|
||||||
|
);
|
||||||
|
|
||||||
|
const command = getCommands(commandsObject)['$0'];
|
||||||
|
const parsedCommand = await parseCommand('create-nx-workspace', command);
|
||||||
|
const markdown = generateMarkdown(parsedCommand);
|
||||||
|
generateMarkdownFile(commandsOutputDirectory, markdown);
|
||||||
|
|
||||||
|
delete process.env.NX_GENERATE_DOCS_PROCESS;
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`${chalk.green(
|
||||||
|
'✓'
|
||||||
|
)} Generated Documentation for Create Nx Workspace Command`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateMarkdown(command: ParsedCommand) {
|
||||||
|
let template = dedent`
|
||||||
|
---
|
||||||
|
title: "${command.name} - CLI command"
|
||||||
|
description: "${command.description}"
|
||||||
|
---
|
||||||
|
# ${command.name}
|
||||||
|
|
||||||
|
${command.description}
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
${command.commandString}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
Install \`create-nx-workspace\` globally to invoke the command directly, or use \`npx create-nx-workspace\`, \`yarn create nx-workspace\`, or \`pnpx create-nx-workspace\`.\n`;
|
||||||
|
|
||||||
|
template += generateOptionsMarkdown(command);
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: command.name,
|
||||||
|
template,
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -1,7 +1,9 @@
|
|||||||
import { outputFileSync, readJsonSync } from 'fs-extra';
|
import { outputFileSync, readJsonSync } from 'fs-extra';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { format, resolveConfig } from 'prettier';
|
import { format, resolveConfig } from 'prettier';
|
||||||
|
import { dedent } from 'tslint/lib/utils';
|
||||||
const stripAnsi = require('strip-ansi');
|
const stripAnsi = require('strip-ansi');
|
||||||
|
const importFresh = require('import-fresh');
|
||||||
|
|
||||||
export function sortAlphabeticallyFunction(a: string, b: string): number {
|
export function sortAlphabeticallyFunction(a: string, b: string): number {
|
||||||
const nameA = a.toUpperCase(); // ignore upper and lowercase
|
const nameA = a.toUpperCase(); // ignore upper and lowercase
|
||||||
@ -99,7 +101,106 @@ export function formatDeprecated(
|
|||||||
? `**Deprecated:** ${description}`
|
? `**Deprecated:** ${description}`
|
||||||
: `
|
: `
|
||||||
**Deprecated:** ${deprecated}
|
**Deprecated:** ${deprecated}
|
||||||
|
|
||||||
${description}
|
${description}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getCommands(command) {
|
||||||
|
return command.getInternalMethods().getCommandInstance().getCommandHandlers();
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ParsedCommandOption {
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
default: string;
|
||||||
|
deprecated: boolean | string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ParsedCommand {
|
||||||
|
name: string;
|
||||||
|
commandString: string;
|
||||||
|
description: string;
|
||||||
|
options?: Array<ParsedCommandOption>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function parseCommand(
|
||||||
|
name: string,
|
||||||
|
command: any
|
||||||
|
): Promise<ParsedCommand> {
|
||||||
|
// It is not a function return a strip down version of the command
|
||||||
|
if (
|
||||||
|
!(
|
||||||
|
command.builder &&
|
||||||
|
command.builder.constructor &&
|
||||||
|
command.builder.call &&
|
||||||
|
command.builder.apply
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
commandString: command.original,
|
||||||
|
description: command.description,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show all the options we can get from yargs
|
||||||
|
const builder = await command.builder(
|
||||||
|
importFresh('yargs')().getInternalMethods().reset()
|
||||||
|
);
|
||||||
|
const builderDescriptions = builder
|
||||||
|
.getInternalMethods()
|
||||||
|
.getUsageInstance()
|
||||||
|
.getDescriptions();
|
||||||
|
const builderDefaultOptions = builder.getOptions().default;
|
||||||
|
const builderAutomatedOptions = builder.getOptions().defaultDescription;
|
||||||
|
const builderDeprecatedOptions = builder.getDeprecatedOptions();
|
||||||
|
const builderOptionsChoices = builder.getOptions().choices;
|
||||||
|
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
description: command.description,
|
||||||
|
commandString: command.original.replace('$0', name),
|
||||||
|
options:
|
||||||
|
Object.keys(builderDescriptions).map((key) => ({
|
||||||
|
name: key,
|
||||||
|
description: builderDescriptions[key]
|
||||||
|
? builderDescriptions[key].replace('__yargsString__:', '')
|
||||||
|
: '',
|
||||||
|
default: builderDefaultOptions[key] ?? builderAutomatedOptions[key],
|
||||||
|
choices: builderOptionsChoices[key],
|
||||||
|
deprecated: builderDeprecatedOptions[key],
|
||||||
|
})) || null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateOptionsMarkdown(command): string {
|
||||||
|
let response = '';
|
||||||
|
if (Array.isArray(command.options) && !!command.options.length) {
|
||||||
|
response += '\n## Options';
|
||||||
|
|
||||||
|
command.options
|
||||||
|
.sort((a, b) => sortAlphabeticallyFunction(a.name, b.name))
|
||||||
|
.forEach((option) => {
|
||||||
|
response += dedent`
|
||||||
|
### ${option.deprecated ? `~~${option.name}~~` : option.name}
|
||||||
|
${
|
||||||
|
option.default === undefined || option.default === ''
|
||||||
|
? ''
|
||||||
|
: `Default: \`${option.default}\`\n`
|
||||||
|
}`;
|
||||||
|
response += dedent`
|
||||||
|
${
|
||||||
|
option.choices === undefined
|
||||||
|
? ''
|
||||||
|
: `Choices: \`[${option.choices
|
||||||
|
.map((c) => `"${c}"`)
|
||||||
|
.join(', ')}]\`\n`
|
||||||
|
}`;
|
||||||
|
response += dedent`
|
||||||
|
${formatDeprecated(option.description, option.deprecated)}
|
||||||
|
`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user