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:
Miroslav Jonaš 2022-03-29 20:00:07 +02:00 committed by GitHub
parent 66e2c37582
commit 9e06020575
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 547 additions and 207 deletions

View 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

View File

@ -360,6 +360,11 @@
"name": "CLI",
"id": "cli",
"itemList": [
{
"name": "create-nx-workspace",
"id": "create-nx-workspace",
"file": "generated/cli/create-nx-workspace"
},
{
"name": "generate",
"id": "generate",

View File

@ -10,6 +10,7 @@ import {
copySync,
createFileSync,
ensureDirSync,
existsSync,
moveSync,
readdirSync,
readFileSync,
@ -28,7 +29,15 @@ import chalk = require('chalk');
import isCI = require('is-ci');
import treeKill = require('tree-kill');
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');
export const isWindows = require('is-windows');

View File

@ -1,24 +1,37 @@
#!/usr/bin/env node
import { exec } from 'child_process';
import { writeFileSync } from 'fs';
import * as enquirer from 'enquirer';
import * as path from 'path';
import { dirSync } from 'tmp';
import * as yargsParser from 'yargs-parser';
import * as yargs from 'yargs';
import { showNxWarning, unparse } from './shared';
import { output } from './output';
import * as ora from 'ora';
import {
detectInvokedPackageManager,
getPackageManagerCommand,
getPackageManagerVersion,
PackageManager,
packageManagerList,
} from './package-manager';
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',
Empty = 'empty', // same as apps, deprecated
Core = 'core',
@ -101,41 +114,93 @@ const cliVersion = 'NX_VERSION';
const nxVersion = 'NX_VERSION';
const prettierVersion = 'PRETTIER_VERSION';
const parsedArgs: any = yargsParser(process.argv.slice(2), {
string: [
'name',
'cli',
'preset',
'appName',
'style',
'defaultBase',
'packageManager',
],
alias: {
packageManager: 'pm',
},
boolean: ['help', 'interactive', 'nxCloud'],
default: {
interactive: false,
},
configuration: {
export const commandsObject: yargs.Argv<Arguments> = yargs
.wrap(yargs.terminalWidth())
.parserConfiguration({
'strip-dashed': true,
'strip-aliased': true,
},
}) as any;
'dot-notation': false,
})
.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) {
showHelp();
process.exit(0);
}
(async function main() {
const packageManager: PackageManager =
parsedArgs.packageManager || detectInvokedPackageManager();
const { name, cli, preset, appName, style, nxCloud } = await getConfiguration(
parsedArgs
);
async function main(parsedArgs: yargs.Arguments<Arguments>) {
const {
name,
cli,
preset,
appName,
style,
nxCloud,
packageManager,
defaultBase,
} = parsedArgs;
output.log({
title: `Nx is creating your v${cliVersion} workspace.`,
@ -147,101 +212,73 @@ if (parsedArgs.help) {
const tmpDir = await createSandbox(packageManager);
await createApp(tmpDir, name, packageManager, {
await createApp(tmpDir, name, packageManager as PackageManager, {
...parsedArgs,
cli,
preset,
appName,
style,
nxCloud,
defaultBase,
});
let nxCloudInstallRes;
if (nxCloud) {
nxCloudInstallRes = await setupNxCloud(name, packageManager);
nxCloudInstallRes = await setupNxCloud(
name,
packageManager as PackageManager
);
}
showNxWarning(name);
pointToTutorialAndCourse(preset);
pointToTutorialAndCourse(preset as Preset);
if (nxCloud && nxCloudInstallRes.code === 0) {
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 {
let style, appName;
const name = await determineWorkspaceName(parsedArgs);
let preset = await determineThirdPartyPackage(parsedArgs);
const name = await determineWorkspaceName(argv);
let preset = await determineThirdPartyPackage(argv);
if (!preset) {
preset = await determinePreset(parsedArgs);
appName = await determineAppName(preset, parsedArgs);
style = await determineStyle(preset, parsedArgs);
preset = await determinePreset(argv);
appName = await determineAppName(preset, argv);
style = await determineStyle(preset, argv);
}
const cli = await determineCli(preset, parsedArgs);
const nxCloud = await askAboutNxCloud(parsedArgs);
const cli = await determineCli(preset, argv);
const packageManager = await determinePackageManager(argv);
const defaultBase = await determineDefaultBase(argv);
const nxCloud = await determineNxCloud(argv);
return {
Object.assign(argv, {
name,
preset,
appName,
style,
cli,
nxCloud,
};
packageManager,
defaultBase,
});
} catch (e) {
console.error(e);
process.exit(1);
}
}
function determineWorkspaceName(parsedArgs: any): Promise<string> {
function determineWorkspaceName(
parsedArgs: yargs.Arguments<Arguments>
): Promise<string> {
const workspaceName: string = parsedArgs._[0]
? parsedArgs._[0]
? parsedArgs._[0].toString()
: parsedArgs.name;
if (workspaceName) {
@ -268,8 +305,85 @@ function determineWorkspaceName(parsedArgs: any): Promise<string> {
});
}
async function determineThirdPartyPackage({ preset }) {
if (preset && Object.values(Preset).indexOf(preset) === -1) {
async function determinePackageManager(
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(/.+@/)
? preset[0] + preset.substring(1).split('@')[0]
: 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 (Object.values(Preset).indexOf(parsedArgs.preset) === -1) {
output.error({
@ -323,7 +437,10 @@ function determinePreset(parsedArgs: any): Promise<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 (
preset === Preset.Apps ||
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,
parsedArgs: any
parsedArgs: yargs.Arguments<Arguments>
): Promise<'nx' | 'angular'> {
if (parsedArgs.cli) {
if (['nx', 'angular'].indexOf(parsedArgs.cli) === -1) {
if (!isValidCli(parsedArgs.cli)) {
output.error({
title: 'Invalid cli',
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 (
preset === Preset.Apps ||
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) {
return enquirer
.prompt([

View File

@ -0,0 +1,6 @@
import * as chalk from 'chalk';
export const yargsDecorator = {
'Options:': `${chalk.bold('Options')}:`,
'Positionals:': `${chalk.bold('Positionals')}:`,
};

View 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;
}
}

View File

@ -0,0 +1,5 @@
#!/usr/bin/env node
import { commandsObject } from './create-nx-workspace';
commandsObject.argv;

View File

@ -7,7 +7,7 @@ import { join } from 'path';
* 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];
@ -109,7 +109,7 @@ export function detectInvokedPackageManager(): PackageManager {
if (!invoker) {
return detectedPackageManager;
}
console.log(invoker.path);
for (const pkgManager of packageManagerList) {
if (invoker.path.includes(pkgManager)) {
detectedPackageManager = pkgManager;

View File

@ -0,0 +1,3 @@
export function stringifyCollection(items: string[]): string {
return items.map((item) => `"${item}"`).join(', ');
}

View File

@ -19,7 +19,7 @@
"CLI"
],
"bin": {
"create-nx-workspace": "./bin/create-nx-workspace.js"
"create-nx-workspace": "./bin/index.js"
},
"author": "Victor Savkin",
"license": "MIT",
@ -29,7 +29,7 @@
"homepage": "https://nx.dev",
"dependencies": {
"tmp": "~0.2.1",
"yargs-parser": "21.0.1",
"yargs": "^17.4.0",
"enquirer": "~2.3.6",
"flat": "^5.0.2",
"chalk": "4.1.0",

View File

@ -1,6 +1,5 @@
import { execSync } from 'child_process';
// TODO (v13): Update to main
export function deduceDefaultBase(): string {
const nxDefaultBase = 'main';
try {

View File

@ -1,6 +1,9 @@
import * as chalk from 'chalk';
import { execSync } from 'child_process';
import { removeSync } from 'fs-extra';
import { join } from 'path';
import { generateCLIDocumentation } from './generate-cli-data';
import { generateCNWocumentation } from './generate-cnw-documentation';
import { generateDevkitDocumentation } from './generate-devkit-documentation';
import { generatePackageSchemas } from './package-schemas/generatePackageSchemas';
@ -9,7 +12,16 @@ async function generate() {
console.log(`${chalk.blue('i')} Generating Documentation`);
generatePackageSchemas();
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`);
} catch (e) {

View File

@ -1,16 +1,19 @@
import * as chalk from 'chalk';
import { readFileSync } from 'fs';
import { readJsonSync, removeSync } from 'fs-extra';
import { readJsonSync } from 'fs-extra';
import { join } from 'path';
import { dedent } from 'tslint/lib/utils';
import {
formatDeprecated,
generateMarkdownFile,
generateOptionsMarkdown,
getCommands,
parseCommand,
ParsedCommand,
sortAlphabeticallyFunction,
} from './utils';
import { register as registerTsConfigPaths } from 'tsconfig-paths';
import { examples } from '../../packages/nx/src/command-line/examples';
import { dedent } from 'tslint/lib/utils';
const importFresh = require('import-fresh');
@ -24,21 +27,9 @@ const sharedCommands = [
'test',
];
interface ParsedCommandOption {
name: string;
description: string;
default: string;
deprecated: boolean | string;
}
interface ParsedCommand {
name: string;
commandString: string;
description: string;
options?: Array<ParsedCommandOption>;
}
export async function generateCLIDocumentation() {
export async function generateCLIDocumentation(
commandsOutputDirectory: string
) {
/**
* 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
@ -57,65 +48,6 @@ export async function generateCLIDocumentation() {
'../../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) {
let template = dedent`
---
@ -146,25 +78,7 @@ nx ${command.commandString}
});
}
if (Array.isArray(command.options) && !!command.options.length) {
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)}
`;
});
}
template += generateOptionsMarkdown(command);
return {
name: command.name
@ -181,7 +95,7 @@ nx ${command.commandString}
Object.keys(nxCommands)
.filter((name) => !sharedCommands.includes(name))
.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 (templateObject) =>
generateMarkdownFile(commandsOutputDirectory, await templateObject)

View 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,
};
}

View File

@ -1,7 +1,9 @@
import { outputFileSync, readJsonSync } from 'fs-extra';
import { join } from 'path';
import { format, resolveConfig } from 'prettier';
import { dedent } from 'tslint/lib/utils';
const stripAnsi = require('strip-ansi');
const importFresh = require('import-fresh');
export function sortAlphabeticallyFunction(a: string, b: string): number {
const nameA = a.toUpperCase(); // ignore upper and lowercase
@ -99,7 +101,106 @@ export function formatDeprecated(
? `**Deprecated:** ${description}`
: `
**Deprecated:** ${deprecated}
${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;
}