샘플
commander 15.0.0: Preserve option value types on optional-value flags by configuring Option.preset() to prevent Commander from coercing valueless flags to boolean true and bypassing argParser
검증된 샘플 — npm commander 15.0.0: Preserve option value types on optional-value flags by configuring Option.preset() to prevent Commander from coercing…
sha256:4bf9cbc16740182dbe7fcca88866b9e64c94372e4115587056c4b525005ba078
이 네트워크가 제공하는 것은 하나입니다. 빌드되는 샘플. 샌드박스에서 돌리고 서명된 영수증을 보관합니다. 등급을 매기지 않고 무엇도 보증하지 않습니다 — 같은 코드가 당신 환경에서 빌드되는지는 측정한 적이 없습니다.
통과한 계약 영수증을 낸 서로 다른 서명 키의 수입니다. 하나면 작성자 혼자이고, 둘 이상이면 다른 사람도 빌드했다는 뜻입니다. 키는 스스로 만드는 것이고 뒤에 등록된 신원이 없으므로, 세는 것은 사람이 아니라 키입니다.
MIT-0
실행 증거
선언된 환경과 서명된 실행을 분리해 두었습니다. 이 샘플이 무엇을 어디서 실행했는지 그대로 볼 수 있습니다.
- 증거 기준
- 서명된 컨트랙트 통과
- 검증 영수증
- 3
- 빌드한 서명 키
- 3
선언된 환경
node linux x64 node node npm
검증 실행 환경
| 환경 | 컨트랙트 | 단계 | 실행일 |
|---|---|---|---|
| node 22 · linux alpine/x64 · docker ed25519:d91480838ac982c9 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1 |
2026-08-17 |
| node 22 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1 |
2026-08-18 |
| node 22 · linux alpine/x64 · docker ed25519:c1973797be207ac4 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1node:22-alpine@sha256:c610fcdfb1d5… |
2026-09-08 |
케이스
HOW- 목표
- Preserve option value types on optional-value flags by configuring Option.preset() to prevent Commander from coercing valueless flags to boolean true and bypassing argParser
- 패키지
- 심벌
-
- Option.preset
- Option.default
- Option.argParser
- Option
- Command
- 환경
- node
- 생성일
- 2026-08-17T01:48:40Z
컨트랙트
- Option.preset() supplies a fallback value passed to argParser when an optional-value flag is invoked without arguments, preventing Commander from storing boolean true and bypassing custom parser coercion.
- opts() contains boolean true instead of a parsed number when an optional-value option lacks a preset and is passed without an argument
- opts() retains the default value when the optional-value flag is omitted entirely
- opts() contains the parsed custom argument when the flag is passed with an explicit value
- accumulating option collectors append preset values on valueless flag invocations instead of having the entire accumulated array overwritten by boolean true
- options configured with choices validate against preset values rather than assigning boolean true outside the allowed choices list
파일
- NOTES.md
- csx.json
- package-lock.json
- package.json
- src/index.mjs
- test/contract.mjs
소스
# Notes
- **search_known_solution answer:** Found samples `sha256:05e524cd641f3e66c380604099a1c591c4fbe976012949d4819b1f3ec255ed9f` (argument unpacking and radix traps), `sha256:5c6d27a5983a0c5c7ab82d8867250554602d63b07860b3cdacd2dcd58f498252` (string options in `Option.implies()`), and `sha256:b953db7ef30e702f31dca9192e6ef548a50589157551d3ada4896bd8624d6d8d` (boolean environment variable truthiness).
- **What a model would have written instead:** `program.addOption(new Option('-t, --timeout [ms]').default(5000).argParser(Number))` or `program.option('-t, --timeout [ms]', 'timeout', Number, 5000)` assuming Commander always routes flag invocations through `argParser` and retains the declared numeric/array type when `--timeout` is invoked without an argument.
- **How the wrong version fails:** Silently with a green build in loose test suites: without `.preset()`, Commander stores boolean `true` and bypasses `argParser` completely when an optional-value flag is passed without an argument, silently wiping out accumulated arrays or replacing numeric defaults with `true` and causing corrupted calculations or downstream runtime `TypeError` exceptions.
{"case":{"believed":"An option configured with an optional value and a custom argParser coerces a fallback value through argParser when the flag is invoked without an argument on the command line.","caseId":"case:sha256:9cc173dc63c1dd23b062d4ba1bdf581a7c23a497e9239492dfe39b88d32296e6","contract":["Option.preset() supplies a fallback value passed to argParser when an optional-value flag is invoked without arguments, preventing Commander from storing boolean true and bypassing custom parser coercion.","opts() contains boolean true instead of a parsed number when an optional-value option lacks a preset and is passed without an argument","opts() retains the default value when the optional-value flag is omitted entirely","opts() contains the parsed custom argument when the flag is passed with an explicit value","accumulating option collectors append preset values on valueless flag invocations instead of having the entire accumulated array overwritten by boolean true","options configured with choices validate against preset values rather than assigning boolean true outside the allowed choices list"],"goal":"Preserve option value types on optional-value flags by configuring Option.preset() to prevent Commander from coercing valueless flags to boolean true and bypassing argParser","kind":"HOW","packages":["pkg:npm/commander@15.0.0"],"schemaVersion":1,"symbols":["Option.preset","Option.default","Option.argParser","Option","Command"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","ecosystem":"npm","executionContext":"node","language":"node","os":"linux","packageManager":"npm","runtime":"node","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/commander@15.0.0"],"schemaVersion":1,"symbols":["Option.preset","Option.default","Option.argParser","Option","Command"],"verifierAdapter":"node-typescript@1"}
{
"name": "csx-sample-commander-optional-preset",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "csx-sample-commander-optional-preset",
"version": "1.0.0",
"license": "MIT-0",
"dependencies": {
"commander": "15.0.0"
}
},
"node_modules/commander": {
"version": "15.0.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-15.0.0.tgz",
"integrity": "sha512-z67u4ZhzCL/Tydu1lJARtEZYWbWaN7oYLHbsuzocr6y4N6WZAagG3RQ4FW61V1/0+jImpj293XfrcYnd1qxtPg==",
"license": "MIT",
"engines": {
"node": ">=22.12.0"
}
}
}
}
{
"name": "csx-sample-commander-optional-preset",
"version": "1.0.0",
"private": true,
"type": "module",
"license": "MIT-0",
"dependencies": {
"commander": "15.0.0"
}
}
import { Command, Option } from 'commander';
/**
* Creates a CLI command demonstrating optional-value option parsing with custom numeric coerce.
*
* When an option is defined with an optional value (e.g. `-t, --timeout [ms]`) and a custom
* argParser (e.g. `val => Number(val)`), omitting the option argument on CLI (passing `--timeout` alone)
* causes Commander to assign boolean `true` directly, completely bypassing `argParser`.
* Configuring `.preset('3000')` supplies an explicit fallback value that Commander passes to
* `argParser`, preserving the expected number type across all invocation forms.
*
* @param {{ usePreset?: boolean }} [options]
* @returns {Command}
*/
export function createTimeoutParser({ usePreset = false } = {}) {
const program = new Command();
const option = new Option('-t, --timeout [ms]', 'timeout in milliseconds')
.default(5000)
.argParser(val => Number(val));
if (usePreset) {
option.preset('3000');
}
program.name('demo-timeout').addOption(option).exitOverride();
return program;
}
/**
* Creates a CLI command demonstrating optional-value array accumulation.
*
* Without `.preset()`, passing a valueless flag to an accumulator option replaces the entire
* accumulated array with boolean `true`. With `.preset()`, Commander calls `argParser` with the
* preset value, appending to the existing array.
*
* @param {{ usePreset?: boolean }} [options]
* @returns {Command}
*/
export function createCollectorParser({ usePreset = false } = {}) {
const program = new Command();
const option = new Option('-t, --tag [label]', 'tags to attach')
.default([])
.argParser((val, prev) => [...prev, val]);
if (usePreset) {
option.preset('latest');
}
program.name('demo-collector').addOption(option).exitOverride();
return program;
}
/**
* Creates a CLI command demonstrating choices validation on optional-value options.
*
* Without `.preset()`, passing `--format` without an argument assigns boolean `true`, which is
* outside the declared choices array. With `.preset('json')`, the preset choice is used.
*
* @param {{ usePreset?: boolean }} [options]
* @returns {Command}
*/
export function createChoicesParser({ usePreset = false } = {}) {
const program = new Command();
const option = new Option('-f, --format [type]', 'output format')
.choices(['json', 'yaml', 'text'])
.default('text');
if (usePreset) {
option.preset('json');
}
program.name('demo-choices').addOption(option).exitOverride();
return program;
}
import { strict as assert } from 'node:assert';
import {
createTimeoutParser,
createCollectorParser,
createChoicesParser,
} from '../src/index.mjs';
// 1. Option.preset() supplies a fallback value passed to argParser when an optional-value flag is invoked without arguments, preventing Commander from storing boolean true and bypassing custom parser coercion.
const safeTimeoutParser = createTimeoutParser({ usePreset: true });
safeTimeoutParser.parse(['--timeout'], { from: 'user' });
assert.strictEqual(
safeTimeoutParser.opts().timeout,
3000,
'Option.preset() provides the fallback value passed to argParser when flag is passed without argument'
);
assert.strictEqual(
typeof safeTimeoutParser.opts().timeout,
'number',
'opts().timeout retains number type from argParser rather than becoming boolean true'
);
// 2. opts() contains boolean true instead of a parsed number when an optional-value option lacks a preset and is passed without an argument
const naiveTimeoutParser = createTimeoutParser({ usePreset: false });
naiveTimeoutParser.parse(['--timeout'], { from: 'user' });
assert.strictEqual(
naiveTimeoutParser.opts().timeout,
true,
'Commander assigns boolean true when an optional-value flag lacks a preset'
);
assert.strictEqual(
typeof naiveTimeoutParser.opts().timeout,
'boolean',
'Type changes from expected number to boolean when preset is omitted'
);
// 3. opts() retains the default value when the optional-value flag is omitted entirely
const defaultTimeoutParser = createTimeoutParser({ usePreset: true });
defaultTimeoutParser.parse([], { from: 'user' });
assert.strictEqual(defaultTimeoutParser.opts().timeout, 5000);
assert.strictEqual(typeof defaultTimeoutParser.opts().timeout, 'number');
// 4. opts() contains the parsed custom argument when the flag is passed with an explicit value
const explicitTimeoutParser = createTimeoutParser({ usePreset: true });
explicitTimeoutParser.parse(['--timeout', '8000'], { from: 'user' });
assert.strictEqual(explicitTimeoutParser.opts().timeout, 8000);
assert.strictEqual(typeof explicitTimeoutParser.opts().timeout, 'number');
// 5. accumulating option collectors append preset values on valueless flag invocations instead of having the entire accumulated array overwritten by boolean true
const safeCollectorParser = createCollectorParser({ usePreset: true });
safeCollectorParser.parse(['--tag', 'v1.0', '--tag', '--tag', 'stable'], { from: 'user' });
assert.deepStrictEqual(
safeCollectorParser.opts().tag,
['v1.0', 'latest', 'stable'],
'Collector appends preset value on valueless flag invocation'
);
const naiveCollectorParser = createCollectorParser({ usePreset: false });
naiveCollectorParser.parse(['--tag', 'v1.0', '--tag'], { from: 'user' });
assert.strictEqual(
naiveCollectorParser.opts().tag,
true,
'Valueless flag without preset wipes out accumulated array with boolean true'
);
// 6. options configured with choices validate against preset values rather than assigning boolean true outside the allowed choices list
const safeChoicesParser = createChoicesParser({ usePreset: true });
safeChoicesParser.parse(['--format'], { from: 'user' });
assert.strictEqual(safeChoicesParser.opts().format, 'json');
const naiveChoicesParser = createChoicesParser({ usePreset: false });
naiveChoicesParser.parse(['--format'], { from: 'user' });
assert.strictEqual(
naiveChoicesParser.opts().format,
true,
'Without preset, Commander stores boolean true bypassing the choices constraint'
);
console.log('CONTRACT PASS: Option.preset() preserves option types and argParser execution on optional-value flags');