From 69c6d9b48b11093a9cf4a0e9b9e4197754de12d1 Mon Sep 17 00:00:00 2001 From: Miroslav Jonas Date: Tue, 29 Mar 2022 12:35:26 +0200 Subject: [PATCH] fix(core): migrate to yargs 17.x --- docs/generated/cli/affected-apps.md | 4 - docs/generated/cli/affected-graph.md | 6 -- docs/generated/cli/affected-libs.md | 4 - docs/generated/cli/affected.md | 4 - docs/generated/cli/format-check.md | 4 - docs/generated/cli/format-write.md | 4 - docs/generated/cli/graph.md | 2 - docs/generated/cli/print-affected.md | 4 - docs/generated/cli/run-many.md | 6 -- .../bin/create-nx-workspace.ts | 18 ++-- packages/create-nx-workspace/bin/decorator.ts | 4 +- .../bin/package-manager.ts | 12 ++- scripts/documentation/documentation.ts | 14 ++- scripts/documentation/generate-cli-data.ts | 87 ++------------- .../generate-cnw-documentation.ts | 102 ++++++------------ scripts/documentation/utils.ts | 70 +++++++++++- 16 files changed, 145 insertions(+), 200 deletions(-) diff --git a/docs/generated/cli/affected-apps.md b/docs/generated/cli/affected-apps.md index 2849cdc215efff..cc804a95e85ef8 100644 --- a/docs/generated/cli/affected-apps.md +++ b/docs/generated/cli/affected-apps.md @@ -69,8 +69,6 @@ Show help ### ~~only-failed~~ -Default: `false` - **Deprecated:** The command to rerun failed projects will appear if projects fail. This now does nothing and will be removed in v15. Isolate projects which previously failed @@ -85,8 +83,6 @@ This is the name of the tasks runner configured in nx.json ### skip-nx-cache -Default: `false` - Rerun the tasks even when the results are available in the cache ### uncommitted diff --git a/docs/generated/cli/affected-graph.md b/docs/generated/cli/affected-graph.md index ba409666b2fad7..2256067f932f07 100644 --- a/docs/generated/cli/affected-graph.md +++ b/docs/generated/cli/affected-graph.md @@ -103,8 +103,6 @@ Bind the project graph server to a specific ip address. ### ~~only-failed~~ -Default: `false` - **Deprecated:** The command to rerun failed projects will appear if projects fail. This now does nothing and will be removed in v15. Isolate projects which previously failed @@ -125,8 +123,6 @@ This is the name of the tasks runner configured in nx.json ### skip-nx-cache -Default: `false` - Rerun the tasks even when the results are available in the cache ### uncommitted @@ -147,6 +143,4 @@ Show version number ### watch -Default: `false` - Watch for changes to project graph and update in-browser diff --git a/docs/generated/cli/affected-libs.md b/docs/generated/cli/affected-libs.md index 27bab31a502bdd..e4a965d94d3696 100644 --- a/docs/generated/cli/affected-libs.md +++ b/docs/generated/cli/affected-libs.md @@ -69,8 +69,6 @@ Show help ### ~~only-failed~~ -Default: `false` - **Deprecated:** The command to rerun failed projects will appear if projects fail. This now does nothing and will be removed in v15. Isolate projects which previously failed @@ -85,8 +83,6 @@ This is the name of the tasks runner configured in nx.json ### skip-nx-cache -Default: `false` - Rerun the tasks even when the results are available in the cache ### uncommitted diff --git a/docs/generated/cli/affected.md b/docs/generated/cli/affected.md index 31c8b5d9515eae..b3356dca20c6d9 100644 --- a/docs/generated/cli/affected.md +++ b/docs/generated/cli/affected.md @@ -87,8 +87,6 @@ Show help ### ~~only-failed~~ -Default: `false` - **Deprecated:** The command to rerun failed projects will appear if projects fail. This now does nothing and will be removed in v15. Isolate projects which previously failed @@ -103,8 +101,6 @@ This is the name of the tasks runner configured in nx.json ### skip-nx-cache -Default: `false` - Rerun the tasks even when the results are available in the cache ### target diff --git a/docs/generated/cli/format-check.md b/docs/generated/cli/format-check.md index cf036cf7991e2a..90ab18702c8465 100644 --- a/docs/generated/cli/format-check.md +++ b/docs/generated/cli/format-check.md @@ -53,8 +53,6 @@ Format only libraries and applications files. ### ~~only-failed~~ -Default: `false` - **Deprecated:** The command to rerun failed projects will appear if projects fail. This now does nothing and will be removed in v15. Isolate projects which previously failed @@ -69,8 +67,6 @@ This is the name of the tasks runner configured in nx.json ### skip-nx-cache -Default: `false` - Rerun the tasks even when the results are available in the cache ### uncommitted diff --git a/docs/generated/cli/format-write.md b/docs/generated/cli/format-write.md index 19bad53591dcdc..181e7f90a88527 100644 --- a/docs/generated/cli/format-write.md +++ b/docs/generated/cli/format-write.md @@ -53,8 +53,6 @@ Format only libraries and applications files. ### ~~only-failed~~ -Default: `false` - **Deprecated:** The command to rerun failed projects will appear if projects fail. This now does nothing and will be removed in v15. Isolate projects which previously failed @@ -69,8 +67,6 @@ This is the name of the tasks runner configured in nx.json ### skip-nx-cache -Default: `false` - Rerun the tasks even when the results are available in the cache ### uncommitted diff --git a/docs/generated/cli/graph.md b/docs/generated/cli/graph.md index 9c77a9a4a7289f..7f1130978e2651 100644 --- a/docs/generated/cli/graph.md +++ b/docs/generated/cli/graph.md @@ -107,6 +107,4 @@ Show version number ### watch -Default: `false` - Watch for changes to project graph and update in-browser diff --git a/docs/generated/cli/print-affected.md b/docs/generated/cli/print-affected.md index cfe647da584504..d643b45458cbb4 100644 --- a/docs/generated/cli/print-affected.md +++ b/docs/generated/cli/print-affected.md @@ -81,8 +81,6 @@ Show help ### ~~only-failed~~ -Default: `false` - **Deprecated:** The command to rerun failed projects will appear if projects fail. This now does nothing and will be removed in v15. Isolate projects which previously failed @@ -97,8 +95,6 @@ Select the subset of the returned json document (e.g., --selected=projects) ### skip-nx-cache -Default: `false` - Rerun the tasks even when the results are available in the cache ### uncommitted diff --git a/docs/generated/cli/run-many.md b/docs/generated/cli/run-many.md index 5c58a71ab193cb..fbf751e3280078 100644 --- a/docs/generated/cli/run-many.md +++ b/docs/generated/cli/run-many.md @@ -57,8 +57,6 @@ Show help ### ~~only-failed~~ -Default: `false` - **Deprecated:** The command to rerun failed projects will appear if projects fail. This now does nothing and will be removed in v15. Only run the target on projects which previously failed @@ -77,8 +75,6 @@ Override the tasks runner in `nx.json` ### skip-nx-cache -Default: `false` - Rerun the tasks even when the results are available in the cache ### target @@ -95,8 +91,6 @@ Show version number ### ~~with-deps~~ -Default: `false` - **Deprecated:** Configure target dependencies instead. It will be removed in v14. Include dependencies of specified projects when computing what to run diff --git a/packages/create-nx-workspace/bin/create-nx-workspace.ts b/packages/create-nx-workspace/bin/create-nx-workspace.ts index 890154b4877728..c3a9d6e03fd92c 100644 --- a/packages/create-nx-workspace/bin/create-nx-workspace.ts +++ b/packages/create-nx-workspace/bin/create-nx-workspace.ts @@ -122,17 +122,15 @@ export const commandsObject: yargs.Argv = yargs 'strip-dashed': true, 'dot-notation': false, }) - .strict() .command( // this is the default and only command '$0 [name] [options]', 'Create a new Nx workspace', (yargs) => yargs - .positional('name', { + .option('name', { describe: `Workspace name (e.g. org name)`, type: 'string', - demandOption: true, }) .option('preset', { describe: `Customizes the initial content of your workspace. To build your own see https://nx.dev/nx-plugin/overview#preset`, @@ -179,7 +177,7 @@ export const commandsObject: yargs.Argv = yargs describe: `Default base to use for new projects`, type: 'string', }), - async (argv) => { + async (argv: yargs.ArgumentsCamelCase) => { await main(argv).catch((error) => { const { version } = require('../package.json'); output.error({ @@ -192,7 +190,7 @@ export const commandsObject: yargs.Argv = yargs ) .help('help') .updateLocale(yargsDecorator) - .version(nxVersion); + .version(nxVersion) as yargs.Argv; async function main(parsedArgs: yargs.Arguments) { const { @@ -242,7 +240,9 @@ async function main(parsedArgs: yargs.Arguments) { } } -async function getConfiguration(argv: yargs.Arguments) { +async function getConfiguration( + argv: yargs.Arguments +): Promise { try { let style, appName; @@ -260,7 +260,7 @@ async function getConfiguration(argv: yargs.Arguments) { const defaultBase = await determineDefaultBase(argv); const nxCloud = await determineNxCloud(argv); - return { + Object.assign(argv, { name, preset, appName, @@ -269,7 +269,7 @@ async function getConfiguration(argv: yargs.Arguments) { nxCloud, packageManager, defaultBase, - }; + }); } catch (e) { console.error(e); process.exit(1); @@ -751,7 +751,7 @@ function execAndWait(command: string, cwd: string) { }); } -async function determineNxCloud(parsedArgs: any) { +async function determineNxCloud(parsedArgs: yargs.Arguments) { if (parsedArgs.nxCloud === undefined) { return enquirer .prompt([ diff --git a/packages/create-nx-workspace/bin/decorator.ts b/packages/create-nx-workspace/bin/decorator.ts index c9bc59f93152f0..6e1f2f8aececab 100644 --- a/packages/create-nx-workspace/bin/decorator.ts +++ b/packages/create-nx-workspace/bin/decorator.ts @@ -1,6 +1,6 @@ import * as chalk from 'chalk'; export const yargsDecorator = { - 'Options:': `${chalk.green('Options')}:`, - 'Positionals:': `${chalk.green('Positionals')}:`, + 'Options:': `${chalk.bold('Options')}:`, + 'Positionals:': `${chalk.bold('Positionals')}:`, }; diff --git a/packages/create-nx-workspace/bin/package-manager.ts b/packages/create-nx-workspace/bin/package-manager.ts index 15ec70626af734..6bd559ac2d56c6 100644 --- a/packages/create-nx-workspace/bin/package-manager.ts +++ b/packages/create-nx-workspace/bin/package-manager.ts @@ -1,4 +1,6 @@ import { execSync } from 'child_process'; +import { existsSync } from 'fs'; +import { join } from 'path'; /* * Because we don't want to depend on @nrwl/workspace (to speed up the workspace creation) @@ -9,6 +11,14 @@ export const packageManagerList = ['npm', 'yarn', 'pnpm'] as const; export type PackageManager = typeof packageManagerList[number]; +export function detectPackageManager(dir: string = ''): PackageManager { + return existsSync(join(dir, 'yarn.lock')) + ? 'yarn' + : existsSync(join(dir, 'pnpm-lock.yaml')) + ? 'pnpm' + : 'npm'; +} + /** * Returns commands for the package manager used in the workspace. * By default, the package manager is derived based on the lock file, @@ -22,7 +32,7 @@ export type PackageManager = typeof packageManagerList[number]; * */ export function getPackageManagerCommand( - packageManager: PackageManager = 'npm' + packageManager: PackageManager = detectPackageManager() ): { install: string; add: string; diff --git a/scripts/documentation/documentation.ts b/scripts/documentation/documentation.ts index 5a1a663843068c..33f17c0cb581fc 100644 --- a/scripts/documentation/documentation.ts +++ b/scripts/documentation/documentation.ts @@ -1,5 +1,7 @@ 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'; @@ -10,8 +12,16 @@ async function generate() { console.log(`${chalk.blue('i')} Generating Documentation`); generatePackageSchemas(); generateDevkitDocumentation(); - await generateCNWocumentation(); - 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) { diff --git a/scripts/documentation/generate-cli-data.ts b/scripts/documentation/generate-cli-data.ts index 1a1216e88a4d82..45765f0613ca0c 100644 --- a/scripts/documentation/generate-cli-data.ts +++ b/scripts/documentation/generate-cli-data.ts @@ -1,16 +1,18 @@ 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, + 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 +26,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; -} - -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 +47,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 { - // 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` --- @@ -181,7 +112,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) diff --git a/scripts/documentation/generate-cnw-documentation.ts b/scripts/documentation/generate-cnw-documentation.ts index 1da144cf943c71..8f0ed55ef3c8c3 100644 --- a/scripts/documentation/generate-cnw-documentation.ts +++ b/scripts/documentation/generate-cnw-documentation.ts @@ -1,14 +1,16 @@ import * as chalk from 'chalk'; -import { join } from 'path'; import { dedent } from 'tslint/lib/utils'; import { - formatDeprecated, - sortAlphabeticallyFunction, generateMarkdownFile, + getCommands, + parseCommand, + ParsedCommand, + sortAlphabeticallyFunction, + formatDeprecated, } from './utils'; const importFresh = require('import-fresh'); -export async function generateCNWocumentation() { +export async function generateCNWocumentation(commandsOutputDirectory: string) { process.env.NX_GENERATE_DOCS_PROCESS = 'true'; console.log( @@ -21,17 +23,8 @@ export async function generateCNWocumentation() { '../../packages/create-nx-workspace/bin/create-nx-workspace' ); - const commandsOutputDirectory = join( - __dirname, - '../../docs/', - 'generated', - 'cli' - ); - - const command = commandsObject.getCommandInstance().getCommandHandlers()[ - '$0' - ]; - const parsedCommand = await parseCommand(command); + const command = getCommands(commandsObject)['$0']; + const parsedCommand = await parseCommand('create-nx-workspace', command); const markdown = generateMarkdown(parsedCommand); generateMarkdownFile(commandsOutputDirectory, markdown); @@ -44,48 +37,13 @@ export async function generateCNWocumentation() { ); } -interface ParsedCommandOption { - name: string; - description: string; - default: string; - deprecated: boolean | string; -} - -interface ParsedCommand { - commandString: string; - description: string; - options?: Array; -} - -async function parseCommand(command: any): Promise { - const builder = await command.builder(importFresh('yargs')().resetOptions()); - const builderDescriptions = builder.getUsageInstance().getDescriptions(); - const builderDefaultOptions = builder.getOptions().default; - const builderAutomatedOptions = builder.getOptions().defaultDescription; - const builderDeprecatedOptions = builder.getDeprecatedOptions(); - - return { - description: command.description, - commandString: command.original.replace('$0', 'create-nx-workspace'), - options: - Object.keys(builderDescriptions).map((key) => ({ - name: key, - description: builderDescriptions[key] - ? builderDescriptions[key].replace('__yargsString__:', '') - : '', - default: builderDefaultOptions[key] || builderAutomatedOptions[key], - deprecated: builderDeprecatedOptions[key], - })) || null, - }; -} - function generateMarkdown(command: ParsedCommand) { let template = dedent` --- - title: "create-nx-workspace - CLI command" + title: "${command.name} - CLI command" description: "${command.description}" --- - # create-nx-workspace + # ${command.name} ${command.description} @@ -97,25 +55,31 @@ function generateMarkdown(command: ParsedCommand) { 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 += '\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)} - `; - }); + 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)} + `; + }); + } return { - name: 'create-nx-workspace', + name: command.name + .replace(':', '-') + .replace(' ', '-') + .replace(/[\]\[.]+/gm, ''), template, }; } diff --git a/scripts/documentation/utils.ts b/scripts/documentation/utils.ts index b7c73c26ac2a4f..dfcc0c16aeb35f 100644 --- a/scripts/documentation/utils.ts +++ b/scripts/documentation/utils.ts @@ -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,73 @@ 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; +} + +export async function parseCommand( + name: string, + command: any +): Promise { + // 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(); + + 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], + deprecated: builderDeprecatedOptions[key], + })) || null, + }; +}