From 63654fa8b4f59bfede2c9c4fa90b726c021ddf8d Mon Sep 17 00:00:00 2001 From: Tommy Nguyen <4123478+tido64@users.noreply.github.com> Date: Mon, 9 Sep 2024 11:02:31 +0200 Subject: [PATCH] fix(third-party-notices): move Commander config from `rnx-cli` --- .changeset/eight-pots-attack.md | 6 + .changeset/hot-carrots-tease.md | 8 + packages/cli/src/index.ts | 12 +- packages/cli/src/write-third-party-notices.ts | 85 ---------- packages/third-party-notices/package.json | 1 + packages/third-party-notices/src/cli.ts | 159 ++++++++++-------- packages/third-party-notices/src/commander.ts | 58 +++++++ packages/third-party-notices/src/index.ts | 1 + yarn.lock | 1 + 9 files changed, 171 insertions(+), 160 deletions(-) create mode 100644 .changeset/eight-pots-attack.md create mode 100644 .changeset/hot-carrots-tease.md delete mode 100644 packages/cli/src/write-third-party-notices.ts create mode 100644 packages/third-party-notices/src/commander.ts diff --git a/.changeset/eight-pots-attack.md b/.changeset/eight-pots-attack.md new file mode 100644 index 000000000..43c173957 --- /dev/null +++ b/.changeset/eight-pots-attack.md @@ -0,0 +1,6 @@ +--- +"@rnx-kit/third-party-notices": patch +--- + +Moved Commander config from `@rnx-kit/cli` to `@rnx-kit/third-party-notices` and +resynced all flags diff --git a/.changeset/hot-carrots-tease.md b/.changeset/hot-carrots-tease.md new file mode 100644 index 000000000..6c3bb92e1 --- /dev/null +++ b/.changeset/hot-carrots-tease.md @@ -0,0 +1,8 @@ +--- +"@rnx-kit/cli": minor +--- + +Moved Commander config from `@rnx-kit/cli` to `@rnx-kit/third-party-notices` and +resynced all flags. Unfortunately, this means that if you were using the +`rnx-write-third-party-notices` command before, you might have to adjust your +flags when upgrading to this version. diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index fc519075b..01c14a2b8 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -1,5 +1,6 @@ import type { Command } from "@react-native-community/cli-types"; import { alignDepsCommand } from "@rnx-kit/align-deps"; +import { writeThirdPartyNoticesCommand } from "@rnx-kit/third-party-notices"; import { rnxBuildCommand } from "./build"; import { rnxBundleCommand } from "./bundle"; import { rnxCleanCommand } from "./clean"; @@ -8,7 +9,6 @@ import { rnxRamBundleCommand } from "./ram-bundle"; import { rnxRunCommand } from "./run"; import { rnxStartCommand } from "./start"; import { rnxTestCommand } from "./test"; -import { rnxWriteThirdPartyNoticesCommand } from "./write-third-party-notices"; export const reactNativeConfig = { commands: [ @@ -20,7 +20,7 @@ export const reactNativeConfig = { rnxCopyAssetsCommand, alignDepsCommand, rnxTestCommand, - rnxWriteThirdPartyNoticesCommand, + writeThirdPartyNoticesCommand, rnxCleanCommand, ] as Command[], }; @@ -29,6 +29,10 @@ export const reactNativeConfig = { export const rnxAlignDeps = alignDepsCommand.func; export const rnxAlignDepsCommand = alignDepsCommand; +// @rnx-kit/third-party-notices +export const rnxWriteThirdPartyNotices = writeThirdPartyNoticesCommand.func; +export const rnxWriteThirdPartyNoticesCommand = writeThirdPartyNoticesCommand; + export { rnxBuild, rnxBuildCommand } from "./build"; export { rnxBundle, rnxBundleCommand } from "./bundle"; export { rnxClean, rnxCleanCommand } from "./clean"; @@ -37,7 +41,3 @@ export { rnxRamBundle, rnxRamBundleCommand } from "./ram-bundle"; export { rnxRun, rnxRunCommand } from "./run"; export { rnxStart, rnxStartCommand } from "./start"; export { rnxTest, rnxTestCommand } from "./test"; -export { - rnxWriteThirdPartyNotices, - rnxWriteThirdPartyNoticesCommand, -} from "./write-third-party-notices"; diff --git a/packages/cli/src/write-third-party-notices.ts b/packages/cli/src/write-third-party-notices.ts deleted file mode 100644 index 90501460e..000000000 --- a/packages/cli/src/write-third-party-notices.ts +++ /dev/null @@ -1,85 +0,0 @@ -import type { Config as CLIConfig } from "@react-native-community/cli-types"; -import { writeThirdPartyNotices } from "@rnx-kit/third-party-notices"; - -type CliThirdPartyNoticesOptions = { - rootPath: string; - sourceMapFile: string; - json: boolean; - outputFile?: string; - ignoreScopes?: string; - ignoreModules?: string; - preambleText?: string; - additionalText?: string; -}; - -export function rnxWriteThirdPartyNotices( - _argv: string[], - _config: CLIConfig, - { - additionalText, - ignoreModules, - ignoreScopes, - json, - outputFile, - preambleText, - rootPath, - sourceMapFile, - }: CliThirdPartyNoticesOptions -): void { - // react-native-cli is not as rich as yargs, so we have to perform a mapping. - writeThirdPartyNotices({ - rootPath, - sourceMapFile, - json, - outputFile, - ignoreScopes: ignoreScopes?.split(","), - ignoreModules: ignoreModules?.split(","), - preambleText: preambleText ? [preambleText] : undefined, - additionalText: additionalText ? [additionalText] : undefined, - }); -} - -export const rnxWriteThirdPartyNoticesCommand = { - name: "rnx-write-third-party-notices", - description: "Writes third party notices based on the given bundle", - func: rnxWriteThirdPartyNotices, - options: [ - { - name: "--root-path ", - description: - "The root of the repo — the starting point for finding each module in the source map dependency graph", - }, - { - name: "--source-map-file ", - description: - "The source map file associated with the package's entry file — this source map eventually leads to all package dependencies and their licenses", - }, - { - name: "--json", - description: "Format the 3rd-party notice file as JSON instead of text", - default: false, - }, - { - name: "--output-file ", - description: "The path to use when writing the 3rd-party notice file", - }, - { - name: "--ignore-scopes ", - description: - "Comma-separated list of npm scopes to ignore when traversing the source map dependency graph", - }, - { - name: "--ignore-modules ", - description: - "Comma-separated list of modules to ignore when traversing the source map dependency graph", - }, - { - name: "--preamble-text ", - description: "A string to prepend to the start of the 3rd-party notice", - }, - { - name: "--additional-text ", - description: "A string to append to the end of the 3rd-party notice", - }, - ], -}; diff --git a/packages/third-party-notices/package.json b/packages/third-party-notices/package.json index be951158e..3ca053c95 100644 --- a/packages/third-party-notices/package.json +++ b/packages/third-party-notices/package.json @@ -36,6 +36,7 @@ "yargs": "^16.0.0" }, "devDependencies": { + "@react-native-community/cli-types": "^14.0.0", "@rnx-kit/eslint-config": "*", "@rnx-kit/jest-preset": "*", "@rnx-kit/metro-serializer": "*", diff --git a/packages/third-party-notices/src/cli.ts b/packages/third-party-notices/src/cli.ts index 92f750471..d5bc3cd2f 100644 --- a/packages/third-party-notices/src/cli.ts +++ b/packages/third-party-notices/src/cli.ts @@ -4,79 +4,100 @@ import * as yargs from "yargs"; import type { WriteThirdPartyNoticesOptions } from "./types"; import { writeThirdPartyNotices } from "./write-third-party-notices"; -function fail(message: string): never { +export const cliOptions = { + "root-path": { + type: "string", + description: "The root of the repo to start resolving modules from", + demandOption: true, + default: process.cwd(), + argsString: "", + }, + "source-map-file": { + type: "string", + description: "The source map file to generate license contents for", + demandOption: true, + argsString: "", + }, + json: { + type: "boolean", + description: "Output license information as a JSON", + default: false, + }, + "output-file": { + type: "string", + description: "The output file to write the license file to", + argsString: "", + }, + "ignore-scopes": { + string: true, + array: true, + description: "npm scopes to ignore and not emit license information for", + argsString: "", + }, + "ignore-modules": { + string: true, + array: true, + description: "Modules (JS packages) to not emit license information for", + argsString: "", + }, + "preamble-text": { + string: true, + array: true, + description: + "A list of lines to prepend at the start of the generated license file", + argsString: "", + }, + "additional-text": { + string: true, + array: true, + description: + "A list of lines to append at the end of the generated license file", + argsString: "", + }, + "full-license-text": { + type: "boolean", + description: "Include full license text in the JSON output", + default: false, + implies: "json", + }, +} as const; + +function fail(message: string): void { error(message); - process.exit(1); + process.exitCode = 1; } -function getArgs(): WriteThirdPartyNoticesOptions { - const argv = yargs.options({ - rootPath: { - type: "string", - describe: "The root of the repo where to start resolving modules from.", - require: true, - }, - sourceMapFile: { - type: "string", - describe: "The sourceMap file to generate license contents for.", - require: true, - }, - json: { - type: "boolean", - describe: "Output license information as a JSON", - default: false, - }, - outputFile: { - type: "string", - describe: "The output file to write the license file to.", - }, - ignoreScopes: { - string: true, - array: true, - describe: "Npm scopes to ignore and not emit license information for", - }, - ignoreModules: { - string: true, - array: true, - describe: "Modules (js packages) to not emit license information for ", - }, - preambleText: { - string: true, - array: true, - describe: - "A list of lines to prepend at the start of the generated license file.", - }, - additionalText: { - string: true, - array: true, - describe: - "A list of lines to append at the end of the generated license file.", - }, - fullLicenseText: { - type: "boolean", - describe: "Include full license text in the JSON output", - default: false, - implies: "json", - }, - }).argv; - - const writeTpnArgs: WriteThirdPartyNoticesOptions = argv; - - if (!writeTpnArgs.outputFile) { - writeTpnArgs.outputFile = - writeTpnArgs.sourceMapFile?.substring( +function parseArgs(): WriteThirdPartyNoticesOptions { + const { + "root-path": rootPath, + "source-map-file": sourceMapFile, + json, + "output-file": outputFile, + "ignore-scopes": ignoreScopes, + "ignore-modules": ignoreModules, + "preamble-text": preambleText, + "additional-text": additionalText, + "full-license-text": fullLicenseText, + } = yargs.options(cliOptions).argv; + return { + rootPath, + sourceMapFile, + json, + outputFile: + outputFile || + sourceMapFile.substring( 0, - writeTpnArgs.sourceMapFile.length - - path.extname(writeTpnArgs.sourceMapFile).length - ) + ".tpn"; - } - - return writeTpnArgs; + sourceMapFile.length - path.extname(sourceMapFile).length + ) + ".tpn", + ignoreScopes, + ignoreModules, + preambleText, + additionalText, + fullLicenseText, + }; } -async function main(): Promise { - const writeTpnArgs = getArgs(); - await writeThirdPartyNotices(writeTpnArgs); +if (require.main === module) { + const writeTpnArgs = parseArgs(); + writeThirdPartyNotices(writeTpnArgs).catch(fail); } - -main().catch((err: string) => fail(err)); diff --git a/packages/third-party-notices/src/commander.ts b/packages/third-party-notices/src/commander.ts new file mode 100644 index 000000000..fbdc7fc7f --- /dev/null +++ b/packages/third-party-notices/src/commander.ts @@ -0,0 +1,58 @@ +import type { Config } from "@react-native-community/cli-types"; +import { cliOptions } from "./cli"; +import type { WriteThirdPartyNoticesOptions } from "./types"; +import { writeThirdPartyNotices } from "./write-third-party-notices"; + +type InputArgs = WriteThirdPartyNoticesOptions & { + ignoreScopes?: string; + ignoreModules?: string; + preambleText?: string; + additionalText?: string; +}; + +function rnxWriteThirdPartyNotices( + _argv: string[], + _config: Config, + { + additionalText, + fullLicenseText, + ignoreModules, + ignoreScopes, + json, + outputFile, + preambleText, + rootPath, + sourceMapFile, + }: InputArgs +): void { + // react-native-cli is not as rich as yargs, so we have to perform a mapping. + writeThirdPartyNotices({ + rootPath, + sourceMapFile, + json, + outputFile, + ignoreScopes: ignoreScopes?.split(","), + ignoreModules: ignoreModules?.split(","), + preambleText: preambleText ? [preambleText] : undefined, + additionalText: additionalText ? [additionalText] : undefined, + fullLicenseText, + }); +} + +export const writeThirdPartyNoticesCommand = { + name: "rnx-write-third-party-notices", + description: "Writes third party notices based on the given bundle", + func: rnxWriteThirdPartyNotices, + get options() { + return Object.entries(cliOptions).map(([flag, options]) => { + return { + name: + "argsString" in options + ? `--${flag} ${options.argsString}` + : `--${flag}`, + description: options.description, + default: "default" in options ? options.default : undefined, + }; + }); + }, +}; diff --git a/packages/third-party-notices/src/index.ts b/packages/third-party-notices/src/index.ts index 7ec194a4f..c9d9be9bc 100644 --- a/packages/third-party-notices/src/index.ts +++ b/packages/third-party-notices/src/index.ts @@ -5,6 +5,7 @@ import { writeThirdPartyNoticesFromMap, } from "./write-third-party-notices"; +export { writeThirdPartyNoticesCommand } from "./commander"; export { writeThirdPartyNotices } from "./write-third-party-notices"; export function ThirdPartyNotices( diff --git a/yarn.lock b/yarn.lock index d6aed5f34..854f22d19 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4516,6 +4516,7 @@ __metadata: version: 0.0.0-use.local resolution: "@rnx-kit/third-party-notices@workspace:packages/third-party-notices" dependencies: + "@react-native-community/cli-types": "npm:^14.0.0" "@rnx-kit/console": "npm:^1.0.11" "@rnx-kit/eslint-config": "npm:*" "@rnx-kit/jest-preset": "npm:*"