From 5cab2bc57ba3fdb0c1e5069d604b98d351abdce7 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Fri, 15 Dec 2023 21:54:33 +0800 Subject: [PATCH] feat(cli): support read config from the given config file (#1859) --- cli/codegen/commands.ts | 50 ++++++++- cli/docs/artifacts.md | 1 + cli/docs/build.md | 5 +- cli/docs/create-npm-dirs.md | 1 + cli/docs/new.md | 2 +- cli/docs/pre-publish.md | 1 + cli/docs/rename.md | 3 +- cli/docs/universalize.md | 1 + cli/docs/version.md | 1 + cli/src/api/build.ts | 5 +- cli/src/api/create-npm-dirs.ts | 7 +- cli/src/api/pre-publish.ts | 6 +- cli/src/api/rename.ts | 9 ++ cli/src/api/universalize.ts | 5 +- cli/src/api/version.ts | 5 +- cli/src/def/artifacts.ts | 9 ++ cli/src/def/build.ts | 17 ++- cli/src/def/create-npm-dirs.ts | 9 ++ cli/src/def/new.ts | 2 +- cli/src/def/pre-publish.ts | 9 ++ cli/src/def/rename.ts | 13 ++- cli/src/def/universalize.ts | 9 ++ cli/src/def/version.ts | 9 ++ .../__tests__/__snapshots__/config.spec.ts.md | 97 ++++++++++++++++++ .../__snapshots__/config.spec.ts.snap | Bin 0 -> 790 bytes .../__snapshots__/typegen.spec.ts.snap | Bin 4198 -> 4201 bytes .../__snapshots__/version.spec.ts.md | 15 +-- .../__snapshots__/version.spec.ts.snap | Bin 364 -> 411 bytes cli/src/utils/__tests__/config.spec.ts | 81 +++++++++++++++ cli/src/utils/config.ts | 47 ++++++++- cli/src/utils/version.ts | 18 ++-- 31 files changed, 397 insertions(+), 40 deletions(-) create mode 100644 cli/src/utils/__tests__/__snapshots__/config.spec.ts.md create mode 100644 cli/src/utils/__tests__/__snapshots__/config.spec.ts.snap create mode 100644 cli/src/utils/__tests__/config.spec.ts diff --git a/cli/codegen/commands.ts b/cli/codegen/commands.ts index d78e8444..33e7bd50 100644 --- a/cli/codegen/commands.ts +++ b/cli/codegen/commands.ts @@ -31,7 +31,7 @@ const NEW_OPTIONS: CommandSchema = { { name: 'path', type: 'string', - description: 'The path where the napi-rs project will be created.', + description: 'The path where the NAPI-RS project will be created.', required: true, }, ], @@ -108,7 +108,7 @@ const NEW_OPTIONS: CommandSchema = { const BUILD_OPTIONS: CommandSchema = { name: 'build', - description: 'Build the napi-rs project', + description: 'Build the NAPI-RS project', args: [], options: [ { @@ -129,6 +129,12 @@ const BUILD_OPTIONS: CommandSchema = { type: 'string', description: 'Path to `Cargo.toml`', }, + { + name: 'configPath', + type: 'string', + description: 'Path to `napi` config json file', + short: 'c', + }, { name: 'packageJsonPath', type: 'string', @@ -253,7 +259,7 @@ const BUILD_OPTIONS: CommandSchema = { name: 'watch', type: 'boolean', description: - 'watch the crate changes and build continiously with `cargo-watch` crates', + 'watch the crate changes and build continuously with `cargo-watch` crates', short: 'w', }, { @@ -288,6 +294,12 @@ const ARTIFACTS_OPTIONS: CommandSchema = { 'The working directory of where napi command will be executed in, all other paths options are relative to this path', default: 'process.cwd()', }, + { + name: 'configPath', + type: 'string', + description: 'Path to `napi` config json file', + short: 'c', + }, { name: 'packageJsonPath', type: 'string', @@ -323,6 +335,12 @@ const CREATE_NPM_DIRS_OPTIONS: CommandSchema = { 'The working directory of where napi command will be executed in, all other paths options are relative to this path', default: 'process.cwd()', }, + { + name: 'configPath', + type: 'string', + description: 'Path to `napi` config json file', + short: 'c', + }, { name: 'packageJsonPath', type: 'string', @@ -346,7 +364,7 @@ const CREATE_NPM_DIRS_OPTIONS: CommandSchema = { const RENAME_OPTIONS: CommandSchema = { name: 'rename', - description: 'Rename the napi-rs project', + description: 'Rename the NAPI-RS project', args: [], options: [ { @@ -356,6 +374,12 @@ const RENAME_OPTIONS: CommandSchema = { 'The working directory of where napi command will be executed in, all other paths options are relative to this path', default: 'process.cwd()', }, + { + name: 'configPath', + type: 'string', + description: 'Path to `napi` config json file', + short: 'c', + }, { name: 'packageJsonPath', type: 'string', @@ -416,6 +440,12 @@ const UNIVERSALIZE_OPTIONS: CommandSchema = { 'The working directory of where napi command will be executed in, all other paths options are relative to this path', default: 'process.cwd()', }, + { + name: 'configPath', + type: 'string', + description: 'Path to `napi` config json file', + short: 'c', + }, { name: 'packageJsonPath', type: 'string', @@ -445,6 +475,12 @@ const VERSION_OPTIONS: CommandSchema = { 'The working directory of where napi command will be executed in, all other paths options are relative to this path', default: 'process.cwd()', }, + { + name: 'configPath', + type: 'string', + description: 'Path to `napi` config json file', + short: 'c', + }, { name: 'packageJsonPath', type: 'string', @@ -472,6 +508,12 @@ const PRE_PUBLISH_OPTIONS: CommandSchema = { 'The working directory of where napi command will be executed in, all other paths options are relative to this path', default: 'process.cwd()', }, + { + name: 'configPath', + type: 'string', + description: 'Path to `napi` config json file', + short: 'c', + }, { name: 'packageJsonPath', type: 'string', diff --git a/cli/docs/artifacts.md b/cli/docs/artifacts.md index 8a218f7b..0638900b 100644 --- a/cli/docs/artifacts.md +++ b/cli/docs/artifacts.md @@ -26,6 +26,7 @@ new NapiCli().artifacts({ | --------------- | ------------------- | ------ | -------- | -------------- | ------------------------------------------------------------------------------------------------------------------ | | | --help,-h | | | | get help | | cwd | --cwd | string | false | process.cwd() | The working directory of where napi command will be executed in, all other paths options are relative to this path | +| configPath | --config-path,-c | string | false | | Path to `napi` config json file | | packageJsonPath | --package-json-path | string | false | 'package.json' | Path to `package.json` | | outputDir | --output-dir,-o | string | false | './artifacts' | Path to the folder where all built `.node` files put, same as `--output-dir` of build command | | npmDir | --npm-dir | string | false | 'npm' | Path to the folder where the npm packages put | diff --git a/cli/docs/build.md b/cli/docs/build.md index 00f4c257..4e5cd616 100644 --- a/cli/docs/build.md +++ b/cli/docs/build.md @@ -2,7 +2,7 @@ > This file is generated by cli/codegen. Do not edit this file manually. -Build the napi-rs project +Build the NAPI-RS project ## Usage @@ -28,6 +28,7 @@ new NapiCli().build({ | target | --target,-t | string | false | | Build for the target triple, bypassed to `cargo build --target` | | cwd | --cwd | string | false | | The working directory of where napi command will be executed in, all other paths options are relative to this path | | manifestPath | --manifest-path | string | false | | Path to `Cargo.toml` | +| configPath | --config-path,-c | string | false | | Path to `napi` config json file | | packageJsonPath | --package-json-path | string | false | | Path to `package.json` | | targetDir | --target-dir | string | false | | Directory for all crate generated artifacts, see `cargo build --target-dir` | | outputDir | --output-dir,-o | string | false | | Path to where all the built files would be put. Default to the crate folder | @@ -48,7 +49,7 @@ new NapiCli().build({ | crossCompile | --cross-compile,-x | boolean | false | | [experimental] cross-compile for the specified target with `cargo-xwin` on windows and `cargo-zigbuild` on other platform | | useCross | --use-cross | boolean | false | | [experimental] use [cross](https://github.com/cross-rs/cross) instead of `cargo` | | useNapiCross | --use-napi-cross | boolean | false | | [experimental] use @napi-rs/cross-toolchain to cross-compile Linux arm/arm64/x64 gnu targets. | -| watch | --watch,-w | boolean | false | | watch the crate changes and build continiously with `cargo-watch` crates | +| watch | --watch,-w | boolean | false | | watch the crate changes and build continuously with `cargo-watch` crates | | features | --features,-F | string[] | false | | Space-separated list of features to activate | | allFeatures | --all-features | boolean | false | | Activate all available features | | noDefaultFeatures | --no-default-features | boolean | false | | Do not activate the `default` feature | diff --git a/cli/docs/create-npm-dirs.md b/cli/docs/create-npm-dirs.md index 6279bad8..1ee705a7 100644 --- a/cli/docs/create-npm-dirs.md +++ b/cli/docs/create-npm-dirs.md @@ -26,6 +26,7 @@ new NapiCli().createNpmDirs({ | --------------- | ------------------- | ------- | -------- | -------------- | ------------------------------------------------------------------------------------------------------------------ | | | --help,-h | | | | get help | | cwd | --cwd | string | false | process.cwd() | The working directory of where napi command will be executed in, all other paths options are relative to this path | +| configPath | --config-path,-c | string | false | | Path to `napi` config json file | | packageJsonPath | --package-json-path | string | false | 'package.json' | Path to `package.json` | | npmDir | --npm-dir | string | false | 'npm' | Path to the folder where the npm packages put | | dryRun | --dry-run | boolean | false | false | Dry run without touching file system | diff --git a/cli/docs/new.md b/cli/docs/new.md index ad17bfdb..a58b9e3b 100644 --- a/cli/docs/new.md +++ b/cli/docs/new.md @@ -25,7 +25,7 @@ new NapiCli().new({ | Options | CLI Options | type | required | default | description | | -------------------- | ------------------------ | -------- | -------- | ------- | -------------------------------------------------------------------------------- | | | --help,-h | | | | get help | -| path | | true | string | | The path where the napi-rs project will be created. | +| path | | true | string | | The path where the NAPI-RS project will be created. | | name | --name,-n | string | false | | The name of the project, default to the name of the directory if not provided | | minNodeApiVersion | --min-node-api,-v | number | false | 4 | The minimum Node-API version to support | | license | --license,-l | string | false | 'MIT' | License for open-sourced project | diff --git a/cli/docs/pre-publish.md b/cli/docs/pre-publish.md index 3b983561..c2a9e059 100644 --- a/cli/docs/pre-publish.md +++ b/cli/docs/pre-publish.md @@ -26,6 +26,7 @@ new NapiCli().prePublish({ | --------------- | ------------------- | ---------------- | -------- | -------------- | ------------------------------------------------------------------------------------------------------------------ | | | --help,-h | | | | get help | | cwd | --cwd | string | false | process.cwd() | The working directory of where napi command will be executed in, all other paths options are relative to this path | +| configPath | --config-path,-c | string | false | | Path to `napi` config json file | | packageJsonPath | --package-json-path | string | false | 'package.json' | Path to `package.json` | | npmDir | --npm-dir | string | false | 'npm' | Path to the folder where the npm packages put | | tagStyle | --tag-style | 'npm' \| 'lerna' | false | 'lerna' | git tag style, `npm` or `lerna` | diff --git a/cli/docs/rename.md b/cli/docs/rename.md index 0ade2270..b75e52b5 100644 --- a/cli/docs/rename.md +++ b/cli/docs/rename.md @@ -2,7 +2,7 @@ > This file is generated by cli/codegen. Do not edit this file manually. -Rename the napi-rs project +Rename the NAPI-RS project ## Usage @@ -26,6 +26,7 @@ new NapiCli().rename({ | --------------- | ------------------- | ------ | -------- | -------------- | ------------------------------------------------------------------------------------------------------------------ | | | --help,-h | | | | get help | | cwd | --cwd | string | false | process.cwd() | The working directory of where napi command will be executed in, all other paths options are relative to this path | +| configPath | --config-path,-c | string | false | | Path to `napi` config json file | | packageJsonPath | --package-json-path | string | false | 'package.json' | Path to `package.json` | | npmDir | --npm-dir | string | false | 'npm' | Path to the folder where the npm packages put | | name | --name,-n | string | false | | The new name of the project | diff --git a/cli/docs/universalize.md b/cli/docs/universalize.md index a5916ea1..57adf10e 100644 --- a/cli/docs/universalize.md +++ b/cli/docs/universalize.md @@ -26,5 +26,6 @@ new NapiCli().universalize({ | --------------- | ------------------- | ------ | -------- | -------------- | ------------------------------------------------------------------------------------------------------------------ | | | --help,-h | | | | get help | | cwd | --cwd | string | false | process.cwd() | The working directory of where napi command will be executed in, all other paths options are relative to this path | +| configPath | --config-path,-c | string | false | | Path to `napi` config json file | | packageJsonPath | --package-json-path | string | false | 'package.json' | Path to `package.json` | | outputDir | --output-dir,-o | string | false | './' | Path to the folder where all built `.node` files put, same as `--output-dir` of build command | diff --git a/cli/docs/version.md b/cli/docs/version.md index 8cc02c80..5e6fa7bc 100644 --- a/cli/docs/version.md +++ b/cli/docs/version.md @@ -26,5 +26,6 @@ new NapiCli().version({ | --------------- | ------------------- | ------ | -------- | -------------- | ------------------------------------------------------------------------------------------------------------------ | | | --help,-h | | | | get help | | cwd | --cwd | string | false | process.cwd() | The working directory of where napi command will be executed in, all other paths options are relative to this path | +| configPath | --config-path,-c | string | false | | Path to `napi` config json file | | packageJsonPath | --package-json-path | string | false | 'package.json' | Path to `package.json` | | npmDir | --npm-dir | string | false | 'npm' | Path to the folder where the npm packages put | diff --git a/cli/src/api/build.ts b/cli/src/api/build.ts index 8b664ad6..97f5505c 100644 --- a/cli/src/api/build.ts +++ b/cli/src/api/build.ts @@ -90,7 +90,10 @@ export async function buildProject(options: BuildOptions) { process.env.CARGO_BUILD_TARGET_DIR ?? metadata.target_directory, await readNapiConfig( - resolvePath(options.packageJsonPath ?? 'package.json'), + resolvePath( + options.configPath ?? options.packageJsonPath ?? 'package.json', + ), + options.configPath ? resolvePath(options.configPath) : undefined, ), ) diff --git a/cli/src/api/create-npm-dirs.ts b/cli/src/api/create-npm-dirs.ts index e4cbdb08..d2065552 100644 --- a/cli/src/api/create-npm-dirs.ts +++ b/cli/src/api/create-npm-dirs.ts @@ -43,10 +43,13 @@ export async function createNpmDirs(userOptions: CreateNpmDirsOptions) { const packageJsonPath = resolve(options.cwd, options.packageJsonPath) const npmPath = resolve(options.cwd, options.npmDir) - debug(`Read content from [${packageJsonPath}]`) + debug(`Read content from [${options.configPath ?? packageJsonPath}]`) const { targets, binaryName, packageName, packageJson } = - await readNapiConfig(packageJsonPath) + await readNapiConfig( + packageJsonPath, + options.configPath ? resolve(options.cwd, options.configPath) : undefined, + ) for (const target of targets) { const targetDir = join(npmPath, `${target.platformArchABI}`) diff --git a/cli/src/api/pre-publish.ts b/cli/src/api/pre-publish.ts index b6e4f5b7..87d94f5e 100644 --- a/cli/src/api/pre-publish.ts +++ b/cli/src/api/pre-publish.ts @@ -31,10 +31,14 @@ export async function prePublish(userOptions: PrePublishOptions) { const options = applyDefaultPrePublishOptions(userOptions) + const configPath = relative( + options.cwd, + options.configPath ?? options.packageJsonPath, + ) const packageJsonPath = relative(options.cwd, options.packageJsonPath) const { packageJson, targets, packageName, binaryName, npmClient } = - await readNapiConfig(packageJsonPath) + await readNapiConfig(configPath, configPath) async function createGhRelease(packageName: string, version: string) { if (!options.ghRelease) { diff --git a/cli/src/api/rename.ts b/cli/src/api/rename.ts index c948b7e0..e4da7541 100644 --- a/cli/src/api/rename.ts +++ b/cli/src/api/rename.ts @@ -30,6 +30,15 @@ export async function renameProject(userOptions: RenameOptions) { }, ) + if (options.configPath) { + const configPath = resolve(options.cwd, options.configPath) + const configContent = await readFileAsync(configPath, 'utf8') + const configData = JSON.parse(configContent) + configData.binaryName = options.binaryName + configData.packageName = options.packageName + await writeFileAsync(configPath, JSON.stringify(configData, null, 2)) + } + await writeFileAsync( packageJsonPath, JSON.stringify(packageJsonData, null, 2), diff --git a/cli/src/api/universalize.ts b/cli/src/api/universalize.ts index 53ebd860..a0a05c70 100644 --- a/cli/src/api/universalize.ts +++ b/cli/src/api/universalize.ts @@ -27,7 +27,10 @@ export async function universalizeBinaries(userOptions: UniversalizeOptions) { const packageJsonPath = join(options.cwd, options.packageJsonPath) - const config = await readNapiConfig(packageJsonPath) + const config = await readNapiConfig( + packageJsonPath, + options.configPath ? resolve(options.cwd, options.configPath) : undefined, + ) const target = config.targets.find( (t) => t.platform === process.platform && t.arch === 'universal', diff --git a/cli/src/api/version.ts b/cli/src/api/version.ts index fa3e47cc..af0a6f41 100644 --- a/cli/src/api/version.ts +++ b/cli/src/api/version.ts @@ -13,7 +13,10 @@ export async function version(userOptions: VersionOptions) { const options = applyDefaultVersionOptions(userOptions) const packageJsonPath = resolve(options.cwd, options.packageJsonPath) - const config = await readNapiConfig(packageJsonPath) + const config = await readNapiConfig( + packageJsonPath, + options.configPath ? resolve(options.cwd, options.configPath) : undefined, + ) for (const target of config.targets) { const pkgDir = resolve(options.cwd, options.npmDir, target.platformArchABI) diff --git a/cli/src/def/artifacts.ts b/cli/src/def/artifacts.ts index 2e50439f..2e74c82b 100644 --- a/cli/src/def/artifacts.ts +++ b/cli/src/def/artifacts.ts @@ -15,6 +15,10 @@ export abstract class BaseArtifactsCommand extends Command { 'The working directory of where napi command will be executed in, all other paths options are relative to this path', }) + configPath?: string = Option.String('--config-path,-c', { + description: 'Path to `napi` config json file', + }) + packageJsonPath = Option.String('--package-json-path', 'package.json', { description: 'Path to `package.json`', }) @@ -31,6 +35,7 @@ export abstract class BaseArtifactsCommand extends Command { getOptions() { return { cwd: this.cwd, + configPath: this.configPath, packageJsonPath: this.packageJsonPath, outputDir: this.outputDir, npmDir: this.npmDir, @@ -48,6 +53,10 @@ export interface ArtifactsOptions { * @default process.cwd() */ cwd?: string + /** + * Path to `napi` config json file + */ + configPath?: string /** * Path to `package.json` * diff --git a/cli/src/def/build.ts b/cli/src/def/build.ts index cb6ca2b7..3656da94 100644 --- a/cli/src/def/build.ts +++ b/cli/src/def/build.ts @@ -6,7 +6,7 @@ export abstract class BaseBuildCommand extends Command { static paths = [['build']] static usage = Command.Usage({ - description: 'Build the napi-rs project', + description: 'Build the NAPI-RS project', }) target?: string = Option.String('--target,-t', { @@ -23,6 +23,10 @@ export abstract class BaseBuildCommand extends Command { description: 'Path to `Cargo.toml`', }) + configPath?: string = Option.String('--config-path,-c', { + description: 'Path to `napi` config json file', + }) + packageJsonPath?: string = Option.String('--package-json-path', { description: 'Path to `package.json`', }) @@ -117,7 +121,7 @@ export abstract class BaseBuildCommand extends Command { watch?: boolean = Option.Boolean('--watch,-w', { description: - 'watch the crate changes and build continiously with `cargo-watch` crates', + 'watch the crate changes and build continuously with `cargo-watch` crates', }) features?: string[] = Option.Array('--features,-F', { @@ -137,6 +141,7 @@ export abstract class BaseBuildCommand extends Command { target: this.target, cwd: this.cwd, manifestPath: this.manifestPath, + configPath: this.configPath, packageJsonPath: this.packageJsonPath, targetDir: this.targetDir, outputDir: this.outputDir, @@ -166,7 +171,7 @@ export abstract class BaseBuildCommand extends Command { } /** - * Build the napi-rs project + * Build the NAPI-RS project */ export interface BuildOptions { /** @@ -181,6 +186,10 @@ export interface BuildOptions { * Path to `Cargo.toml` */ manifestPath?: string + /** + * Path to `napi` config json file + */ + configPath?: string /** * Path to `package.json` */ @@ -262,7 +271,7 @@ export interface BuildOptions { */ useNapiCross?: boolean /** - * watch the crate changes and build continiously with `cargo-watch` crates + * watch the crate changes and build continuously with `cargo-watch` crates */ watch?: boolean /** diff --git a/cli/src/def/create-npm-dirs.ts b/cli/src/def/create-npm-dirs.ts index d44bd630..5921be97 100644 --- a/cli/src/def/create-npm-dirs.ts +++ b/cli/src/def/create-npm-dirs.ts @@ -14,6 +14,10 @@ export abstract class BaseCreateNpmDirsCommand extends Command { 'The working directory of where napi command will be executed in, all other paths options are relative to this path', }) + configPath?: string = Option.String('--config-path,-c', { + description: 'Path to `napi` config json file', + }) + packageJsonPath = Option.String('--package-json-path', 'package.json', { description: 'Path to `package.json`', }) @@ -29,6 +33,7 @@ export abstract class BaseCreateNpmDirsCommand extends Command { getOptions() { return { cwd: this.cwd, + configPath: this.configPath, packageJsonPath: this.packageJsonPath, npmDir: this.npmDir, dryRun: this.dryRun, @@ -46,6 +51,10 @@ export interface CreateNpmDirsOptions { * @default process.cwd() */ cwd?: string + /** + * Path to `napi` config json file + */ + configPath?: string /** * Path to `package.json` * diff --git a/cli/src/def/new.ts b/cli/src/def/new.ts index 387eb050..609e1f9e 100644 --- a/cli/src/def/new.ts +++ b/cli/src/def/new.ts @@ -72,7 +72,7 @@ export abstract class BaseNewCommand extends Command { */ export interface NewOptions { /** - * The path where the napi-rs project will be created. + * The path where the NAPI-RS project will be created. */ path: string /** diff --git a/cli/src/def/pre-publish.ts b/cli/src/def/pre-publish.ts index 12e7b9f3..12098cb8 100644 --- a/cli/src/def/pre-publish.ts +++ b/cli/src/def/pre-publish.ts @@ -15,6 +15,10 @@ export abstract class BasePrePublishCommand extends Command { 'The working directory of where napi command will be executed in, all other paths options are relative to this path', }) + configPath?: string = Option.String('--config-path,-c', { + description: 'Path to `napi` config json file', + }) + packageJsonPath = Option.String('--package-json-path', 'package.json', { description: 'Path to `package.json`', }) @@ -46,6 +50,7 @@ export abstract class BasePrePublishCommand extends Command { getOptions() { return { cwd: this.cwd, + configPath: this.configPath, packageJsonPath: this.packageJsonPath, npmDir: this.npmDir, tagStyle: this.tagStyle, @@ -67,6 +72,10 @@ export interface PrePublishOptions { * @default process.cwd() */ cwd?: string + /** + * Path to `napi` config json file + */ + configPath?: string /** * Path to `package.json` * diff --git a/cli/src/def/rename.ts b/cli/src/def/rename.ts index ac54454d..3431039d 100644 --- a/cli/src/def/rename.ts +++ b/cli/src/def/rename.ts @@ -6,7 +6,7 @@ export abstract class BaseRenameCommand extends Command { static paths = [['rename']] static usage = Command.Usage({ - description: 'Rename the napi-rs project', + description: 'Rename the NAPI-RS project', }) cwd = Option.String('--cwd', process.cwd(), { @@ -14,6 +14,10 @@ export abstract class BaseRenameCommand extends Command { 'The working directory of where napi command will be executed in, all other paths options are relative to this path', }) + configPath?: string = Option.String('--config-path,-c', { + description: 'Path to `napi` config json file', + }) + packageJsonPath = Option.String('--package-json-path', 'package.json', { description: 'Path to `package.json`', }) @@ -49,6 +53,7 @@ export abstract class BaseRenameCommand extends Command { getOptions() { return { cwd: this.cwd, + configPath: this.configPath, packageJsonPath: this.packageJsonPath, npmDir: this.npmDir, name: this.$$name, @@ -62,7 +67,7 @@ export abstract class BaseRenameCommand extends Command { } /** - * Rename the napi-rs project + * Rename the NAPI-RS project */ export interface RenameOptions { /** @@ -71,6 +76,10 @@ export interface RenameOptions { * @default process.cwd() */ cwd?: string + /** + * Path to `napi` config json file + */ + configPath?: string /** * Path to `package.json` * diff --git a/cli/src/def/universalize.ts b/cli/src/def/universalize.ts index 099bb851..624cbf84 100644 --- a/cli/src/def/universalize.ts +++ b/cli/src/def/universalize.ts @@ -14,6 +14,10 @@ export abstract class BaseUniversalizeCommand extends Command { 'The working directory of where napi command will be executed in, all other paths options are relative to this path', }) + configPath?: string = Option.String('--config-path,-c', { + description: 'Path to `napi` config json file', + }) + packageJsonPath = Option.String('--package-json-path', 'package.json', { description: 'Path to `package.json`', }) @@ -26,6 +30,7 @@ export abstract class BaseUniversalizeCommand extends Command { getOptions() { return { cwd: this.cwd, + configPath: this.configPath, packageJsonPath: this.packageJsonPath, outputDir: this.outputDir, } @@ -42,6 +47,10 @@ export interface UniversalizeOptions { * @default process.cwd() */ cwd?: string + /** + * Path to `napi` config json file + */ + configPath?: string /** * Path to `package.json` * diff --git a/cli/src/def/version.ts b/cli/src/def/version.ts index c1fe0c2f..b6e8d1bf 100644 --- a/cli/src/def/version.ts +++ b/cli/src/def/version.ts @@ -14,6 +14,10 @@ export abstract class BaseVersionCommand extends Command { 'The working directory of where napi command will be executed in, all other paths options are relative to this path', }) + configPath?: string = Option.String('--config-path,-c', { + description: 'Path to `napi` config json file', + }) + packageJsonPath = Option.String('--package-json-path', 'package.json', { description: 'Path to `package.json`', }) @@ -25,6 +29,7 @@ export abstract class BaseVersionCommand extends Command { getOptions() { return { cwd: this.cwd, + configPath: this.configPath, packageJsonPath: this.packageJsonPath, npmDir: this.npmDir, } @@ -41,6 +46,10 @@ export interface VersionOptions { * @default process.cwd() */ cwd?: string + /** + * Path to `napi` config json file + */ + configPath?: string /** * Path to `package.json` * diff --git a/cli/src/utils/__tests__/__snapshots__/config.spec.ts.md b/cli/src/utils/__tests__/__snapshots__/config.spec.ts.md new file mode 100644 index 00000000..e3c8cc5c --- /dev/null +++ b/cli/src/utils/__tests__/__snapshots__/config.spec.ts.md @@ -0,0 +1,97 @@ +# Snapshot report for `src/utils/__tests__/config.spec.ts` + +The actual snapshot is saved in `config.spec.ts.snap`. + +Generated by [AVA](https://avajs.dev). + +## should be able to read config from package.json + +> Snapshot 1 + + { + binaryName: 'testing', + npmClient: 'npm', + packageJson: { + name: '@napi-rs/testing', + napi: { + binaryName: 'testing', + packageName: '@napi-rs/testing', + targets: [ + 'x86_64-unknown-linux-gnu', + 'x86_64-pc-windows-msvc', + 'x86_64-apple-darwin', + ], + }, + version: '0.0.0', + }, + packageName: '@napi-rs/testing', + targets: [ + { + abi: 'gnu', + arch: 'x64', + platform: 'linux', + platformArchABI: 'linux-x64-gnu', + triple: 'x86_64-unknown-linux-gnu', + }, + { + abi: 'msvc', + arch: 'x64', + platform: 'win32', + platformArchABI: 'win32-x64-msvc', + triple: 'x86_64-pc-windows-msvc', + }, + { + abi: null, + arch: 'x64', + platform: 'darwin', + platformArchABI: 'darwin-x64', + triple: 'x86_64-apple-darwin', + }, + ], + } + +## should be able to read config from napi.json + +> Snapshot 1 + + { + binaryName: 'testing', + npmClient: 'npm', + packageJson: { + name: '@napi-rs/testing', + napi: { + binaryName: 'testing', + packageName: '@node-rs/testing', + targets: [ + 'x86_64-unknown-linux-gnu', + 'x86_64-apple-darwin', + 'aarch64-apple-darwin', + ], + }, + version: '0.0.0', + }, + packageName: '@node-rs/testing', + targets: [ + { + abi: 'gnu', + arch: 'x64', + platform: 'linux', + platformArchABI: 'linux-x64-gnu', + triple: 'x86_64-unknown-linux-gnu', + }, + { + abi: null, + arch: 'x64', + platform: 'darwin', + platformArchABI: 'darwin-x64', + triple: 'x86_64-apple-darwin', + }, + { + abi: null, + arch: 'arm64', + platform: 'darwin', + platformArchABI: 'darwin-arm64', + triple: 'aarch64-apple-darwin', + }, + ], + } diff --git a/cli/src/utils/__tests__/__snapshots__/config.spec.ts.snap b/cli/src/utils/__tests__/__snapshots__/config.spec.ts.snap new file mode 100644 index 0000000000000000000000000000000000000000..38093d0501307b08a9f0ae9d12831b289c82ff6c GIT binary patch literal 790 zcmV+x1L^!hRzVXx4s5>iE=OBrCO5ULo; z#lEC&owH>-Z7RV~5DQ}CFK9Ow)U7j9CuSxPf{Fpb06P+&oj9}?w}~i-A8Mjce!lzO zd-t8+-CL`a9oJk89;~y_4jtAQ59ZyvW9en4)3U?#(A9lLE!}i^#jffV->vB$H5X}> zjV%N&w*yW+_=Lggnq|?D&T4mMDJw-k(nqvOJf{E-JOws@ZD5#aLqxk-USMWONZTwH zixL@-h$@i+IGGV5<7J5C$~LF|$_-j$$xt?AL1^=;z&yge+BL^!JWNJpj7VgVkZ;JF z4EDD~T!#iBLNc{8S@8;F+J+yDx3ePPDESdE8&bc@!XQ$u%wl2=cmk{wL2YKYTF|#Z zc?rA%-X(Okvh>xX-rC*uP#*+5vMGqo1_w&%2U9&cQl zm;sq$?`Exz$8jQ)Yu9Vz@uwyM@o@v0%a+iaa(|)q# zfrARtEb1d)kBV|lw$T|_P&3?8Lp=-{Ne-OkZB*pP=x}H_XWH(oNZEB2H7|#Jltk*` z>&HYwx^8Eam)UQjNv|61p;twxZm&jl`~PfIuEh=;)nC!5E&{iJd%*MVjp{8Z9{>sG z?-Vc%-2VfODy4un4ja`!d87Zl6qWk5Uo9rz5|b8MkTXJ~#iVtp*C@sJKpx%c>~HK) U=^HAvr_^PB2l#>&omCA003!r*fB*mh literal 0 HcmV?d00001 diff --git a/cli/src/utils/__tests__/__snapshots__/typegen.spec.ts.snap b/cli/src/utils/__tests__/__snapshots__/typegen.spec.ts.snap index a17f23289dabfaf34a242174d60156727e384bf0..cad503c8b92712e4730c9f59ff6d5c41943034ca 100644 GIT binary patch delta 191 zcmaE+@KV9ZG0agRI4`lFI3vGAq0E?znPJZQfNiThGavaX-QIj&eA$dmj-ConXUm>( zh*h5`xOvk1jYgCC>vt}Fw~IA$*2exy$Z0z4^Z?dc$ksH@{eR+Z|lz4`;?* zSO0OZwkfuKfuU7wd%|_aA9}J)vH1ztrEh#?ll%YvD_dD?V{CZBbMLGzz1hXId)Y`nI(dg9R*YY83f7Gk*V|%oTT?!q*(zyQzSoi)r!)P2Qj% zKYmY|YQCU)qtRsk`q=FW*L5@8H-hOKrQHAQ%el*Hn_}lDTvxyGl@rc<{fp)PZvPFh z1>RV(?B+Z8{iVR0D(2ny4y-f(P`|-^!)vZLyO?&bJFrgsLef$M$Kd5ICT|m_GhTXg^c diff --git a/cli/src/utils/__tests__/__snapshots__/version.spec.ts.md b/cli/src/utils/__tests__/__snapshots__/version.spec.ts.md index e6972c74..0b092625 100644 --- a/cli/src/utils/__tests__/__snapshots__/version.spec.ts.md +++ b/cli/src/utils/__tests__/__snapshots__/version.spec.ts.md @@ -9,12 +9,13 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 [ - '>= 8.6.0', - '>= 8.10.0 < 9 || >= 9.3.0', - '>= 6.14.2 < 7 || >= 8.11.2 < 9 || >= 9.11.0', - '>= 10.16.0 < 11 || >= 11.8.0', - '>= 10.17.0 < 11 || >= 12.11.0', + '>= 8.6.0 < 9 || >= 9.0.0 < 10 || >= 10.0.0', + '>= 8.10.0 < 9 || >= 9.3.0 < 10 || >= 10.0.0', + '>= 6.14.2 < 7 || >= 8.11.2 < 9 || >= 9.11.0 < 10 || >= 10.0.0', + '>= 10.16.0 < 11 || >= 11.8.0 < 12 || >= 12.0.0', + '>= 10.17.0 < 11 || >= 12.11.0 < 13 || >= 13.0.0', '>= 10.20.0 < 11 || >= 12.17.0 < 13 || >= 14.0.0', - '>= 10.23.0 < 11 || >= 12.19.0 < 13 || >= 14.12.0', - '>= 12.22.0 < 13 || >= 14.17.0 < 15 || >= 15.12.0', + '>= 10.23.0 < 11 || >= 12.19.0 < 13 || >= 14.12.0 < 15 || >= 15.0.0', + '>= 12.22.0 < 13 || >= 14.17.0 < 15 || >= 15.12.0 < 16 || >= 16.0.0', + '>= 18.17.0 < 19 || >= 20.3.0 < 21 || >= 21.1.0', ] diff --git a/cli/src/utils/__tests__/__snapshots__/version.spec.ts.snap b/cli/src/utils/__tests__/__snapshots__/version.spec.ts.snap index 657b24b23f470e4257e1a6ca9d30952530f1e061..a9b699be44fc7a19afd3edb6e71e25e7959be730 100644 GIT binary patch literal 411 zcmV;M0c8F`RzVZlQ%lO!Vx@8^;POHe%6j zNi^X?Jo^IP@KwC|3cid}+QHH$H2Ko*H}m~6vt8fc&F16BX!WJzAfD;hPV_Ke%qD!Q zLv8$6^YPpmJ&t+kKL=cg(;(E`=$A!c^pg(bAi@G>;%K#=O#Ij%S>F{_XUPK%Xx`xa z7WIMpL7f6)Bh)AA7uB&Cdq*8Ztqs*HWBfM&`f9aW44MoM8607U#ZI8YpxTDB%OURz zSJ?c55BPG)@jMXr<}B^Zkapr^Q2@%GZ?e)Zgq?k1i^4-Jxk7e@!e%e)MVj0g|1>oA z;3|X@X-TG=NJ-sN^ixNXqw@I!%6GE7SIDdF01jDB9#Aa+lwAgR1wc0ss1e{g12|>C zpae*^NUR=Ny*#tN!&E}4GQcYVi0P8$=9!J1o9=G`^rvv~baF+LD=F~m{s6H46*CwE F006PF#-#uN literal 364 zcmV-y0h9hgRzVp1w4vp@c@FKai*bW;4$I7-+Pnw{as$hkJaj3>P+YIWmr9wi#(yJEToFG zq;aW~j5RHyr;N%X%?e4Cd|qTq&Sjyq3IpuuYPC+1NJqEu<&YlvJkL2kHR218}dDie3Tim*;r|_Hcv1J`x>r2o3>v0R77gI%5;YO#on%qdF0s zae7Wex?EB;LKZY=$D*g0OqdukAJM5nu`6n$>7ubIJGOj`5xycO^+Q4!8rfMx?^yc8 z(9?gkzcub!eE5g^yp5ZMz*-~5n}Mz!;AS9b4}`4&bT + +test.before(async (t) => { + const tmp = tmpdir() + const configPath = join(tmp, 'napi.json') + const packageJson = join(tmp, 'package.json') + const pkgJson = { + name: '@napi-rs/testing', + version: '0.0.0', + napi: { + binaryName: 'testing', + packageName: '@napi-rs/testing', + targets: [ + 'x86_64-unknown-linux-gnu', + 'x86_64-pc-windows-msvc', + 'x86_64-apple-darwin', + ], + }, + } + await writeFile(packageJson, JSON.stringify(pkgJson, null, 2)) + const config = { + binaryName: 'testing', + packageName: '@node-rs/testing', + targets: [ + 'x86_64-unknown-linux-gnu', + 'x86_64-apple-darwin', + 'aarch64-apple-darwin', + ], + } + await writeFile(configPath, JSON.stringify(config, null, 2)) + t.context = { configPath, config, packageJson, pkgJson } +}) + +test.after(async (t) => { + await unlink(t.context.configPath) + await unlink(t.context.packageJson) +}) + +test('should throw if package.json not found', async (t) => { + await t.throwsAsync(() => readNapiConfig(NON_EXISTENT_FILE), { + message: `package.json not found at ${NON_EXISTENT_FILE}`, + }) +}) + +test('should throw if napi.json not found', async (t) => { + const { packageJson } = t.context + await t.throwsAsync(() => readNapiConfig(packageJson, NON_EXISTENT_FILE), { + message: `NAPI-RS config not found at ${NON_EXISTENT_FILE}`, + }) +}) + +test('should be able to read config from package.json', async (t) => { + const { packageJson } = t.context + const config = await readNapiConfig(packageJson) + t.snapshot(config) +}) + +test('should be able to read config from napi.json', async (t) => { + const { packageJson, configPath } = t.context + const config = await readNapiConfig(packageJson, configPath) + t.snapshot(config) +}) diff --git a/cli/src/utils/config.ts b/cli/src/utils/config.ts index 7546f61a..04b00adf 100644 --- a/cli/src/utils/config.ts +++ b/cli/src/utils/config.ts @@ -1,9 +1,10 @@ +import { underline, yellow } from 'colorette' import { merge, omit } from 'lodash-es' import { fileExists, readFileAsync } from './misc.js' import { DEFAULT_TARGETS, parseTriple, Target } from './target.js' -interface UserNapiConfig { +export interface UserNapiConfig { /** * Name of the binary to be generated, default to `index` */ @@ -89,9 +90,15 @@ export type NapiConfig = Required< packageJson: CommonPackageJsonFields } -export async function readNapiConfig(path: string): Promise { +export async function readNapiConfig( + path: string, + configPath?: string, +): Promise { + if (configPath && !(await fileExists(configPath))) { + throw new Error(`NAPI-RS config not found at ${configPath}`) + } if (!(await fileExists(path))) { - throw new Error(`napi-rs config not found at ${path}`) + throw new Error(`package.json not found at ${path}`) } // May support multiple config sources later on. const content = await readFileAsync(path, 'utf8') @@ -99,12 +106,34 @@ export async function readNapiConfig(path: string): Promise { try { pkgJson = JSON.parse(content) as CommonPackageJsonFields } catch (e) { - throw new Error('Failed to parse napi-rs config', { + throw new Error(`Failed to parse package.json at ${path}`, { cause: e, }) } + let separatedConfig: UserNapiConfig | undefined + if (configPath) { + const configContent = await readFileAsync(configPath, 'utf8') + try { + separatedConfig = JSON.parse(configContent) as UserNapiConfig + } catch (e) { + throw new Error(`Failed to parse NAPI-RS config at ${configPath}`, { + cause: e, + }) + } + } + const userNapiConfig = pkgJson.napi ?? {} + if (pkgJson.napi && separatedConfig) { + const pkgJsonPath = underline(path) + const configPathUnderline = underline(configPath!) + console.warn( + yellow( + `Both napi field in ${pkgJsonPath} and [NAPI-RS config](${configPathUnderline}) file are found, the NAPI-RS config file will be used.`, + ), + ) + Object.assign(userNapiConfig, separatedConfig) + } const napiConfig: NapiConfig = merge( { binaryName: 'index', @@ -120,16 +149,26 @@ export async function readNapiConfig(path: string): Promise { // compatible with old config if (userNapiConfig?.name) { + console.warn( + `[DEPRECATED] napi.name is deprecated, use napi.binaryName instead.`, + ) napiConfig.binaryName = userNapiConfig.name } if (!targets.length) { + let deprecatedWarned = false + const warning = `[DEPRECATED] napi.triples is deprecated, use napi.targets instead.` if (userNapiConfig.triples?.defaults) { + deprecatedWarned = true + console.warn(warning) targets = targets.concat(DEFAULT_TARGETS) } if (userNapiConfig.triples?.additional?.length) { targets = targets.concat(userNapiConfig.triples.additional) + if (!deprecatedWarned) { + console.warn(warning) + } } } diff --git a/cli/src/utils/version.ts b/cli/src/utils/version.ts index 5470a257..01d0cb21 100644 --- a/cli/src/utils/version.ts +++ b/cli/src/utils/version.ts @@ -7,20 +7,22 @@ export enum NapiVersion { Napi6, Napi7, Napi8, + Napi9, } /// because node support new napi version in some minor version updates, so we might meet such situation: /// `node v10.20.0` supports `napi5` and `napi6`, but `node v12.0.0` only support `napi4`, -/// by which, we can not tell directly napi version supportness from node version directly. +/// by which, we can not tell directly napi version supportless from node version directly. const NAPI_VERSION_MATRIX = new Map([ - [NapiVersion.Napi1, '8.6.0'], - [NapiVersion.Napi2, '8.10.0 | 9.3.0'], - [NapiVersion.Napi3, '6.14.2 | 8.11.2 | 9.11.0'], - [NapiVersion.Napi4, '10.16.0 | 11.8.0'], - [NapiVersion.Napi5, '10.17.0 | 12.11.0'], + [NapiVersion.Napi1, '8.6.0 | 9.0.0 | 10.0.0'], + [NapiVersion.Napi2, '8.10.0 | 9.3.0 | 10.0.0'], + [NapiVersion.Napi3, '6.14.2 | 8.11.2 | 9.11.0 | 10.0.0'], + [NapiVersion.Napi4, '10.16.0 | 11.8.0 | 12.0.0'], + [NapiVersion.Napi5, '10.17.0 | 12.11.0 | 13.0.0'], [NapiVersion.Napi6, '10.20.0 | 12.17.0 | 14.0.0'], - [NapiVersion.Napi7, '10.23.0 | 12.19.0 | 14.12.0'], - [NapiVersion.Napi8, '12.22.0 | 14.17.0 | 15.12.0'], + [NapiVersion.Napi7, '10.23.0 | 12.19.0 | 14.12.0 | 15.0.0'], + [NapiVersion.Napi8, '12.22.0 | 14.17.0 | 15.12.0 | 16.0.0'], + [NapiVersion.Napi9, '18.17.0 | 20.3.0 | 21.1.0'], ]) interface NodeVersion {