샘플
commander 15.0.0: Parse boolean environment variables in Commander without presence-only truthiness trap
검증된 샘플 — npm commander 15.0.0: Parse boolean environment variables in Commander without presence-only truthiness trap. node 22 · linux alpine/x64 · docker에서…
sha256:b953db7ef30e702f31dca9192e6ef548a50589157551d3ada4896bd8624d6d8d
이 네트워크가 제공하는 것은 하나입니다. 빌드되는 샘플. 샌드박스에서 돌리고 서명된 영수증을 보관합니다. 등급을 매기지 않고 무엇도 보증하지 않습니다 — 같은 코드가 당신 환경에서 빌드되는지는 측정한 적이 없습니다.
통과한 계약 영수증을 낸 서로 다른 서명 키의 수입니다. 하나면 작성자 혼자이고, 둘 이상이면 다른 사람도 빌드했다는 뜻입니다. 키는 스스로 만드는 것이고 뒤에 등록된 신원이 없으므로, 세는 것은 사람이 아니라 키입니다.
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-16 |
| 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- 목표
- Parse boolean environment variables in Commander without presence-only truthiness trap
- 패키지
- 심벌
-
- Option
- Option.prototype.env
- Option.prototype.preset
- Option.prototype.argParser
- Command.prototype.getOptionValueSource
- 환경
- node
- 생성일
- 2026-08-16T07:26:08Z
컨트랙트
- prove new Option('--flag').env('VAR') evaluates to true when VAR is 'false' or '0'
- prove new Option('--flag [boolean]').preset('true').env('VAR').argParser() parses 'false' and '0' to false
- prove bare CLI flag --flag uses preset('true') and overrides falsy environment variables
- prove option value sources accurately report cli, env, and default precedence
파일
- NOTES.md
- csx.json
- package-lock.json
- package.json
- src/index.mjs
- test/contract.mjs
소스
# CodeSampleX Notes: Commander Boolean Environment Variable Trap
## search_known_solution Result
`search_known_solution` returned existing sample `sha256:ae82f374c5cce645bfa0fbd914f1f675540b81131e60b0b93130f5caa6b74638` with goal *"Parse command line options with commander without touching process.argv"*, covering `{ from: 'user' }` argv slicing.
## What a Model Would Have Written Instead
A model would bind an environment variable directly to a boolean flag using `new Option('--enable-cache', 'enable cache').env('APP_ENABLE_CACHE')` (or attach `.argParser(v => v === 'true')` to the flag) expecting `"false"` or `"0"` to disable it.
## How the Wrong Version Fails
The wrong version fails silently with a green build: Commander treats bare boolean options with `.env()` as presence-only checks (emitting no argument and passing `undefined` to `argParser`), which silently coerces `APP_ENABLE_CACHE="false"` or `"0"` to `true` and silently evaluates `argParser` callbacks to `false` even when set to `"true"`.
{"case":{"caseId":"case:sha256:67e5c2cfd8a5883047354397ed2d3a58e76338106d9e7eac37f0d3e82a57e8e7","contract":["prove new Option('--flag').env('VAR') evaluates to true when VAR is 'false' or '0'","prove new Option('--flag [boolean]').preset('true').env('VAR').argParser() parses 'false' and '0' to false","prove bare CLI flag --flag uses preset('true') and overrides falsy environment variables","prove option value sources accurately report cli, env, and default precedence"],"goal":"Parse boolean environment variables in Commander without presence-only truthiness trap","kind":"HOW","packages":["pkg:npm/commander@15.0.0"],"schemaVersion":1,"symbols":["Option","Option.prototype.env","Option.prototype.preset","Option.prototype.argParser","Command.prototype.getOptionValueSource"]},"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","Option.prototype.env","Option.prototype.preset","Option.prototype.argParser","Command.prototype.getOptionValueSource"],"verifierAdapter":"node-typescript@1"}
{
"name": "csx-sample-commander-env-boolean-flags",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "csx-sample-commander-env-boolean-flags",
"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-env-boolean-flags",
"version": "1.0.0",
"private": true,
"type": "module",
"license": "MIT-0",
"scripts": {
"test": "node test/contract.mjs"
},
"dependencies": {
"commander": "15.0.0"
}
}
import { Command, Option } from 'commander';
/**
* Coerces string and boolean inputs to strict booleans.
* Handles common truthy/falsy environment variable representations.
*
* @param {string|boolean|undefined} val
* @returns {boolean}
*/
export function parseBoolean(val) {
if (typeof val === 'boolean') {
return val;
}
if (typeof val === 'string') {
const normalized = val.trim().toLowerCase();
if (['false', '0', 'no', 'off'].includes(normalized)) {
return false;
}
if (['true', '1', 'yes', 'on'].includes(normalized)) {
return true;
}
}
return Boolean(val);
}
/**
* Builds a CLI program exposing both a naive boolean env option
* (to demonstrate the presence-only trap) and a properly configured
* boolean env option using optional value syntax, preset, and custom parser.
*
* @returns {Command}
*/
export function createCli() {
const program = new Command();
program.exitOverride();
// TRAP: In Commander, declaring a pure boolean flag with .env('VAR')
// checks only if the variable exists in process.env. Values like "false",
// "0", or "" silently evaluate to true, and argParser receives undefined.
program.addOption(
new Option('--raw-cache', 'Naive boolean option with env')
.env('APP_RAW_CACHE')
);
// FIX: Declaring an optional value placeholder `[boolean]` allows Commander
// to pass the actual environment string to argParser. .preset('true') ensures
// that passing `--enable-cache` on the CLI with no argument defaults to true.
program.addOption(
new Option('--enable-cache [boolean]', 'Safe boolean option with env')
.preset('true')
.env('APP_ENABLE_CACHE')
.argParser(parseBoolean)
);
// Optional string option with env and default for comparison
program.addOption(
new Option('-m, --mode <mode>', 'Application run mode')
.default('production')
.env('APP_MODE')
);
return program;
}
import { strict as assert } from 'node:assert';
import { createCli, parseBoolean } from '../src/index.mjs';
// Helper to isolate process.env per test run
function runWithEnv(envOverrides, argv = []) {
const savedEnv = { ...process.env };
delete process.env.APP_RAW_CACHE;
delete process.env.APP_ENABLE_CACHE;
delete process.env.APP_MODE;
for (const [key, val] of Object.entries(envOverrides)) {
if (val !== undefined) {
process.env[key] = val;
}
}
try {
const program = createCli();
program.parse(argv, { from: 'user' });
return {
opts: program.opts(),
program,
};
} finally {
delete process.env.APP_RAW_CACHE;
delete process.env.APP_ENABLE_CACHE;
delete process.env.APP_MODE;
Object.assign(process.env, savedEnv);
}
}
// 1. Proves the trap: A pure boolean flag option treats env var presence as truthy,
// even when the environment variable is explicitly set to "false" or "0".
{
const { opts, program } = runWithEnv({ APP_RAW_CACHE: 'false' }, []);
assert.equal(
opts.rawCache,
true,
'Naive boolean option treats env presence of "false" as true',
);
assert.equal(
program.getOptionValueSource('rawCache'),
'env',
'Source should be identified as env',
);
}
// 2. Proves the fix: An option declared with optional value [boolean] + preset('true') + argParser
// correctly parses "false", "0", "true", and "1" from environment variables.
{
const falseCase = runWithEnv({ APP_ENABLE_CACHE: 'false' }, []);
assert.equal(falseCase.opts.enableCache, false);
assert.equal(falseCase.program.getOptionValueSource('enableCache'), 'env');
const zeroCase = runWithEnv({ APP_ENABLE_CACHE: '0' }, []);
assert.equal(zeroCase.opts.enableCache, false);
assert.equal(zeroCase.program.getOptionValueSource('enableCache'), 'env');
const trueCase = runWithEnv({ APP_ENABLE_CACHE: 'true' }, []);
assert.equal(trueCase.opts.enableCache, true);
assert.equal(trueCase.program.getOptionValueSource('enableCache'), 'env');
const oneCase = runWithEnv({ APP_ENABLE_CACHE: '1' }, []);
assert.equal(oneCase.opts.enableCache, true);
assert.equal(oneCase.program.getOptionValueSource('enableCache'), 'env');
}
// 3. Proves CLI flag behavior: Bare flag uses preset('true') and overrides environment variable.
{
// Bare flag without CLI argument
const bareFlag = runWithEnv({}, ['--enable-cache']);
assert.equal(bareFlag.opts.enableCache, true);
assert.equal(bareFlag.program.getOptionValueSource('enableCache'), 'cli');
// Explicit false argument on CLI
const explicitCliFalse = runWithEnv({}, ['--enable-cache', 'false']);
assert.equal(explicitCliFalse.opts.enableCache, false);
assert.equal(explicitCliFalse.program.getOptionValueSource('enableCache'), 'cli');
// CLI flag overrides falsy environment variable
const cliOverridesEnv = runWithEnv({ APP_ENABLE_CACHE: 'false' }, ['--enable-cache']);
assert.equal(cliOverridesEnv.opts.enableCache, true);
assert.equal(cliOverridesEnv.program.getOptionValueSource('enableCache'), 'cli');
}
// 4. Proves precedence between CLI, env, and default values.
{
// No env, no CLI -> default applies
const defaultMode = runWithEnv({}, []);
assert.equal(defaultMode.opts.mode, 'production');
assert.equal(defaultMode.program.getOptionValueSource('mode'), 'default');
// Env overrides default
const envMode = runWithEnv({ APP_MODE: 'staging' }, []);
assert.equal(envMode.opts.mode, 'staging');
assert.equal(envMode.program.getOptionValueSource('mode'), 'env');
// CLI overrides env and default
const cliMode = runWithEnv({ APP_MODE: 'staging' }, ['--mode', 'development']);
assert.equal(cliMode.opts.mode, 'development');
assert.equal(cliMode.program.getOptionValueSource('mode'), 'cli');
}
console.log('CONTRACT PASS: Commander boolean env options require [boolean] + preset() + argParser to avoid presence-only truthiness trap');