feat(config): accept CLI-only build flags in pkg config#263
feat(config): accept CLI-only build flags in pkg config#263robertsLando wants to merge 7 commits intomainfrom
Conversation
Consolidate CLI (string[]) and programmatic (PkgExecOptions) entry points through a single canonical ParsedInput shape, dropping the options->argv->parseArgs round trip. Split resolveConfig into named phase helpers (resolveInput, resolveConfigFile, resolveOutput, resolveTargetList, assignTargetOutputs). Fully resolve flags in the config layer: compress becomes CompressType enum, targets becomes NodeTarget[] with per-target output paths and input-overwrite guards applied. Expose effective merged pkg on ResolvedConfig so index.ts no longer duplicates precedence logic. Drop unused minimist dep; util.parseArgs drives CLI parsing.
Integration-only coverage (test-50-config-flags) exercises a handful of end-to-end paths via real binaries and takes seconds. This test requires lib-es5/config directly and runs 78 assertions in ~200ms covering: - CLI parseInput: positionals, short-circuits, all flag kinds (bool/string/ list), short aliases, alias collapsing (target/targets, out-path/outdir/ out-dir), every FLAG_SPECS bool negation, positional/negation last-wins, unknown-option rejection - Programmatic parseInput: type guards, input validation, bakeOptions/ publicPackages/noDictionary/targets array-join, empty-array behavior - resolveFlags: CLI>config>default merge for every flag, three-state override (CLI false beats config true), list empty-clear, whitespace trimming, csv parsing, '*' preservation, all compress aliases - validatePkgConfig: unknown-key warn, known-key silence, type mismatches for bool/string/list, mixed-array rejection
There was a problem hiding this comment.
Pull request overview
Extends pkg’s configuration system so that build-shaping flags previously only available via CLI can also be declared in pkg config files, with consistent precedence (CLI > config > defaults) and centralized flag/schema handling.
Changes:
- Introduces a
FLAG_SPECSregistry and newlib/config.tspipeline to parse CLI/programmatic input and resolve merged config + flags. - Refactors
exec()to consume a single resolved config/flags shape, removing the previous minimist-based parsing path. - Adds documentation and a new test suite validating config-driven flags, CLI overrides, type errors, and unknown-key warnings.
Reviewed changes
Copilot reviewed 12 out of 13 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
lib/config.ts |
New centralized parsing/validation/resolution for config + flags + targets/output. |
lib/index.ts |
Refactored to use parseInput() + resolveConfig() output instead of minimist + ad-hoc resolution. |
lib/types.ts |
Expands PkgOptions schema to include newly supported config keys (and makes dictionary optional). |
lib/help.ts |
Adds help text noting config support for build-shaping flags. |
docs-site/guide/configuration.md |
Documents newly accepted config keys in the schema table. |
test/test-50-config-flags/* |
New tests and fixtures covering config-driven flags, overrides, warnings, and type errors. |
package.json |
Removes minimist and @types/minimist. |
yarn.lock |
Lockfile updated accordingly. |
- Validate `pkg` config field is a plain object (reject string/array/null) with a clear error message instead of silently falling back to defaults - types.ts: `PkgCompressType` now excludes numeric reverse-mapping keys from the enum (`Exclude<keyof typeof CompressType, number>`) - help.ts: add `--no-signature` to the options section; list `native-build` and `sea` in the config-overridable flags note - docs: correct `targets` type (`string | string[]`) and rename `deployAssets` row to `deployFiles` (matches actual code/types) - test-80-compression fixture: swap `minimist` require for `picomatch` (direct dep — minimist was removed from package.json) - test-50-config-flags: new `pkg.not-object.json` fixture + assertion for the non-object pkg rejection
- fix "give" → "given" typo in --sea help text - preserve last-wins order for --target/--targets aliases via token walk - narrow PkgOptions.deployFiles to `[from, to]` / `[from, to, 'directory']` tuples - force-require picomatch/picocolors in compression fixture for real VFS payload Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Both --target and --targets are niche aliases; last-wins token walk is overkill. Revert to simple nullish collapse. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| if (flags.debug) { | ||
| log.debugMode = true; | ||
| } |
There was a problem hiding this comment.
exec() only sets log.debugMode when flags.debug is true, but never resets it to false. If exec() is invoked multiple times in the same process (programmatic API), a first call with debug: true will leave debug logging enabled for subsequent calls even when debug is false/unspecified. Set log.debugMode unconditionally from the resolved flag value (e.g., assign log.debugMode = flags.debug) so each invocation is isolated.
| if (flags.debug) { | |
| log.debugMode = true; | |
| } | |
| log.debugMode = flags.debug; |
| @@ -23,7 +23,12 @@ export default function help() { | |||
| --fallback-to-source if bytecode generation fails for a file, ship it as plain source instead of skipping it | |||
| --no-dict comma-separated list of packages names to ignore dictionaries. Use --no-dict * to disable all dictionaries | |||
| -C, --compress [default=None] compression algorithm = Brotli, GZip, or Zstd (Zstd requires Node.js >= 22.15) | |||
There was a problem hiding this comment.
The help output documents --no-signature but not the positive --signature flag, even though the CLI parser supports both and --signature is needed to override a config value of signature: false. Add a corresponding --signature line (or otherwise document how to explicitly enable signing) to keep the CLI reference accurate.
| -C, --compress [default=None] compression algorithm = Brotli, GZip, or Zstd (Zstd requires Node.js >= 22.15) | |
| -C, --compress [default=None] compression algorithm = Brotli, GZip, or Zstd (Zstd requires Node.js >= 22.15) | |
| --signature explicitly enable macOS binary signing |
Closes #262.
Summary
Every CLI build-shaping flag is now also accepted in the pkg config file (
.pkgrc,pkg.config.{js,cjs,mjs,json}, orpackage.json#pkg), so tooling (GitHub Action, IDE plugins, CI wrappers) can drive the build from a single declarative source instead of synthesizing a CLI invocation.Newly accepted config keys
--compresscompress'None' | 'Brotli' | 'GZip' | 'Zstd'--fallback-to-sourcefallbackToSourceboolean--publicpublicboolean--public-packagespublicPackagesstring | string[]--optionsoptionsstring | string[]--no-bytecodebytecode: falseboolean--no-native-buildnativeBuild: falseboolean--no-dictnoDictionarystring | string[]--debugdebugboolean--signaturesignaturebooleantargets/outputPathconvention).Under the hood
The pipeline that threads these values from CLI + config into the build got rewritten to support the single-source-of-truth direction:
FLAG_SPECSregistry — one table maps each flag's CLI name, config key, resolved key, kind, and default.parseArgsoptions,--no-*siblings, config validator, option→argv mapping, and CLI>config>default merge are all derived from this list, so adding a new flag means editing one place.ParsedInput— both CLI (string[]) and programmatic (PkgExecOptions) entry points produce the same shape. Drops the options→argv→parseArgs round trip.resolveConfig— named helpers:resolveInput/resolveConfigFile/resolveOutput/resolveTargetList/assignTargetOutputs.resolveConfigis ~30 lines of orchestration.compressisCompressTypeenum,targetsisNodeTarget[]with per-target output paths and input-overwrite guards applied. Effective mergedpkgis exposed onResolvedConfigsoindex.tsno longer duplicates precedence.parseTargets/stringifyTarget/differentParts/stringifyTargetForOutputintoconfig.tsalongside the rest of the resolution logic.minimistdep (CLI already onutil.parseArgs).exec()sheds ~80 lines of post-resolve logic.Test plan
yarn buildyarn linttest/test-50-config-flags/— exercises config file driving the full flag surface, CLI override (--options ""wins over configured list), bad type rejection, unknown-key warningnode test/test.js host no-npm "test-46-input*"— 28/28 (input/output/target matrix)node test/test.js host no-npm "test-50-*"— 96/96node test/test.js host no-npm "test-80-*"— 3/3 (compression pipeline)