CodeSampleX

Exemplo

commander 15.0.0: Prevent negative number option parsing failures in Commander when registering digit short option flags

Amostra verificada para npm commander 15.0.0: Prevent negative number option parsing failures in Commander when registering digit short option flags. O…

sha256:e84a5f7f9b0e235218dd1ae017a1fdba5fdf2fce9c93b2143bdf8d153a9953fc

Esta rede oferece uma coisa: uma amostra que compila. Ela a executou em um sandbox e guardou o recibo assinado. Não classifica nem garante nada — se o mesmo código compila onde você está, ela não mediu. Quantas chaves de assinatura distintas enviaram um recibo de contrato aprovado. Uma é só o autor; mais de uma significa que outra pessoa também o compilou. Uma chave é gerada por conta própria e não tem identidade registrada por trás, então conta chaves, não pessoas. MIT-0

Evidência de execução

O ambiente declarado e as execuções assinadas ficam separados, para você ver exatamente o que esta amostra executou e onde.

Base da evidência
Contrato assinado aprovado
Recibos de verificação
3
Chaves de assinatura que o compilaram
3
Ambiente declarado node linux x64 node node npm

Ambientes das execuções de verificação

Ambiente Contrato Etapas Execução
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

Caso

HOW
Objetivo
Prevent negative number option parsing failures in Commander when registering digit short option flags
Pacotes
Símbolos
  • Command.option
  • Command.parse
  • Option
Ambiente
node
Criado
2026-08-17T01:48:52Z

Contrato

  1. Passing -1 after an optional-argument option evaluates that option to boolean true and parses -1 as a distinct flag if any single-digit short option is defined on the command hierarchy, because Commander disables negative number heuristics whenever a digit flag exists.
  2. Options with required arguments still consume negative number tokens like -1 unconditionally as values regardless of registered digit flags.
  3. Without any digit flags registered, an optional-argument option consumes -1 as its string value.
  4. Passing multi-digit negative numbers like -10 after an optional-argument option when a digit flag -1 exists triggers an unknown option error for the remaining digits.
  5. Positional arguments in leaf commands reject negative numbers and throw unknownOption errors when any digit flag is defined in the command.

Arquivos

  • NOTES.md
  • csx.json
  • package-lock.json
  • package.json
  • test/contract.mjs
  • test1.mjs
  • test2.mjs
  • test3.mjs
  • test4.mjs
  • test5.mjs
  • test6.mjs
  • test_clean.mjs
  • test_prototype.mjs

Baixar o artefato de código-fonte (tar.gz)

Código-fonte

NOTES.md
# Negative Number Option Parsing and Digit Short Flags in Commander

## Known Solutions Search

A search via `search_known_solution` returned existing compatible samples covering:
- Subcommand action argument unpacking and custom coerce radix traps (`sha256:05e524cd641f3e66c380604099a1c591c4fbe976012949d4819b1f3ec255ed9f`)
- Positional argument default value retrieval via `processedArgs` (`sha256:3fc59d6ae2df342949bb6f6c09dcdc027cda2183237046c0189f6cabfae569e9`)
- `Option.preset` vs `Option.default` behavior on optional flags (`sha256:9ed29f29e55e4074676913ca3bb9009038881ff559b26efc27a6df45e0d7e648`)
- Error interception and `CommanderError` wrapping (`sha256:94607693bb374f0a65026f93ee8ff32d6560d2668a0b2e16a5e6ebc40f4ddd52`)
- Boolean negation option default behavior in Commander 15 (`sha256:e9734b35dd9bf261570327aa6767cba61b29225dbb1b6eebc59d47cb344f1141`)
- Boolean environment variable truthiness parsing (`sha256:b953db7ef30e702f31dca9192e6ef548a50589157551d3ada4896bd8624d6d8d`)

None of the existing samples addressed negative number argument parsing interactions with single-digit short flags.

## Failure Mode

The wrong version fails loudly with an unknownOption error when passing multi-digit negative values or positional arguments, and fails silently with a green build when passing single-digit negative arguments to optional options by assigning boolean true and inadvertently activating the digit flag.
csx.json
{"case":{"believed":"An option configured with an optional value accepts negative numbers like -1 as its argument regardless of what other short option flags are registered on the command.","caseId":"case:sha256:a1a54d8409b0c3eea40222c758c8fd3c05f023431c8ca98a9181518b5f1da0d4","contract":["Passing -1 after an optional-argument option evaluates that option to boolean true and parses -1 as a distinct flag if any single-digit short option is defined on the command hierarchy, because Commander disables negative number heuristics whenever a digit flag exists.","Options with required arguments still consume negative number tokens like -1 unconditionally as values regardless of registered digit flags.","Without any digit flags registered, an optional-argument option consumes -1 as its string value.","Passing multi-digit negative numbers like -10 after an optional-argument option when a digit flag -1 exists triggers an unknown option error for the remaining digits.","Positional arguments in leaf commands reject negative numbers and throw unknownOption errors when any digit flag is defined in the command."],"goal":"Prevent negative number option parsing failures in Commander when registering digit short option flags","kind":"HOW","packages":["pkg:npm/commander@15.0.0"],"schemaVersion":1,"symbols":["Command.option","Command.parse","Option"]},"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":["Command.option","Command.parse","Option"],"verifierAdapter":"node-typescript@1"}
package-lock.json
{
  "name": "npm-commander-d8",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "npm-commander-d8",
      "version": "1.0.0",
      "license": "ISC",
      "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"
      }
    }
  }
}
package.json
{
  "name": "npm-commander-d8",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "test": "node test/contract.mjs"
  },
  "dependencies": {
    "commander": "^15.0.0"
  }
}
test/contract.mjs
import assert from 'node:assert/strict';
import { Command, CommanderError } from 'commander';

// 1. Passing -1 after an optional-argument option evaluates that option to boolean true and parses -1 as a distinct flag if any single-digit short option is defined on the command hierarchy, because Commander disables negative number heuristics whenever a digit flag exists.
{
  const program = new Command();
  program.exitOverride();
  program.configureOutput({ writeErr: () => {} });
  program.option('-1, --one-line', 'display one line');
  program.option('-t, --threshold [val]', 'cutoff threshold');

  program.parse(['node', 'cli', '-t', '-1']);
  const opts = program.opts();

  assert.strictEqual(opts.threshold, true);
  assert.strictEqual(opts.oneLine, true);
}

// 2. Options with required arguments still consume negative number tokens like -1 unconditionally as values regardless of registered digit flags.
{
  const program = new Command();
  program.exitOverride();
  program.configureOutput({ writeErr: () => {} });
  program.option('-1, --one-line', 'display one line');
  program.option('-r, --required <val>', 'required value');

  program.parse(['node', 'cli', '-r', '-1']);
  const opts = program.opts();

  assert.strictEqual(opts.required, '-1');
  assert.strictEqual(opts.oneLine, undefined);
}

// 3. Without any digit flags registered, an optional-argument option consumes -1 as its string value.
{
  const program = new Command();
  program.exitOverride();
  program.configureOutput({ writeErr: () => {} });
  program.option('-v, --verbose', 'verbose output');
  program.option('-t, --threshold [val]', 'cutoff threshold');

  program.parse(['node', 'cli', '-t', '-1']);
  const opts = program.opts();

  assert.strictEqual(opts.threshold, '-1');
  assert.strictEqual(opts.verbose, undefined);
}

// 4. Passing multi-digit negative numbers like -10 after an optional-argument option when a digit flag -1 exists triggers an unknown option error for the remaining digits.
{
  const program = new Command();
  program.exitOverride();
  program.configureOutput({ writeErr: () => {} });
  program.option('-1, --one-line', 'display one line');
  program.option('-t, --threshold [val]', 'cutoff threshold');

  assert.throws(
    () => program.parse(['node', 'cli', '-t', '-10']),
    (err) => {
      assert(err instanceof CommanderError);
      assert.strictEqual(err.code, 'commander.unknownOption');
      assert.match(err.message, /unknown option '-0'/);
      return true;
    }
  );
}

// 5. Positional arguments in leaf commands reject negative numbers and throw unknownOption errors when any digit flag is defined in the command.
{
  const program = new Command();
  program.exitOverride();
  program.configureOutput({ writeErr: () => {} });
  program.option('-1, --one-line', 'display one line');
  program.argument('[offset]', 'coordinate offset');

  assert.throws(
    () => program.parse(['node', 'cli', '-5']),
    (err) => {
      assert(err instanceof CommanderError);
      assert.strictEqual(err.code, 'commander.unknownOption');
      assert.match(err.message, /unknown option '-5'/);
      return true;
    }
  );
}
test1.mjs
import { Command, Option, InvalidArgumentError } from 'commander';

console.log('Testing commander edge cases...');

// Test 1: Negative numbers and digit options
{
  const p1 = new Command();
  p1.exitOverride();
  p1.option('-n, --num <n>');
  p1.parse(['node', 'test', '-n', '-5']);
  console.log('p1 opts:', p1.opts());

  const p2 = new Command();
  p2.exitOverride();
  p2.option('-1, --one');
  p2.option('-n, --num <n>');
  try {
    p2.parse(['node', 'test', '-n', '-5']);
    console.log('p2 opts:', p2.opts());
  } catch (e) {
    console.log('p2 threw with digit option:', e.code, e.message);
  }
}

// Test 2: Optional argument with negative numbers vs flags vs empty string
{
  const p3 = new Command();
  p3.exitOverride();
  p3.option('-o, --optional [val]', 'opt val', 'defaultVal');
  p3.parse(['node', 'test', '-o', '-5']);
  console.log('p3 with -5:', p3.opts());

  const p3b = new Command();
  p3b.exitOverride();
  p3b.option('-1, --one');
  p3b.option('-o, --optional [val]', 'opt val', 'defaultVal');
  try {
    p3b.parse(['node', 'test', '-o', '-5']);
    console.log('p3b with -5:', p3b.opts());
  } catch (e) {
    console.log('p3b threw:', e.code, e.message);
  }
}

// Test 3: Optional argument with empty string or '0' or following operand
{
  const p4 = new Command();
  p4.exitOverride();
  p4.option('-o, --opt [val]');
  p4.argument('[target]');
  p4.parse(['node', 'test', '-o', 'hello']);
  console.log('p4 opts:', p4.opts(), 'args:', p4.args);

  const p5 = new Command();
  p5.exitOverride();
  p5.option('-o, --opt [val]');
  p5.argument('[target]');
  p5.parse(['node', 'test', '-o', '']);
  console.log('p5 opts:', p5.opts(), 'args:', p5.args);
}
test2.mjs
import { Command, Option, InvalidArgumentError } from 'commander';

console.log('--- TEST 2 ---');

// Edge 1: Empty string "" as positional argument vs optional argument
{
  const p = new Command();
  p.exitOverride();
  p.argument('<req>');
  p.parse(['node', 'test', '']);
  console.log('p req with "":', p.processedArgs, p.args);
}

// Edge 2: Variadic argument with empty string or multiple empty strings
{
  const p = new Command();
  p.exitOverride();
  p.argument('<items...>');
  p.parse(['node', 'test', '', '']);
  console.log('variadic arg with "":', p.processedArgs);
}

// Edge 3: Variadic option with empty string
{
  const p = new Command();
  p.exitOverride();
  p.option('-v, --val <items...>');
  p.parse(['node', 'test', '-v', '', '']);
  console.log('variadic opt with "":', p.opts());
}

// Edge 4: Option with empty string default vs unset
{
  const p = new Command();
  p.exitOverride();
  p.option('-s, --str <val>', 'string val', '');
  p.parse(['node', 'test']);
  console.log('opt default "":', p.opts(), 'source:', p.getOptionValueSource('str'));

  const p2 = new Command();
  p2.exitOverride();
  p2.option('-s, --str <val>', 'string val', '');
  p2.parse(['node', 'test', '-s', '']);
  console.log('opt passed "":', p2.opts(), 'source:', p2.getOptionValueSource('str'));
}

// Edge 5: Negative numbers as positional arguments when subcommands exist vs leaf commands
{
  const root = new Command();
  root.exitOverride();
  root.argument('[pos]');
  const sub = root.command('sub');
  sub.argument('[pos]');
  
  try {
    root.parse(['node', 'test', '-5']);
    console.log('root with sub received -5:', root.args);
  } catch (e) {
    console.log('root with sub threw on -5:', e.code, e.message);
  }
}

// Edge 6: Single dash '-' as argument or option value
{
  const p = new Command();
  p.exitOverride();
  p.argument('<file>');
  p.option('-o, --output <file>');
  p.parse(['node', 'test', '-o', '-', '-']);
  console.log('single dash opts:', p.opts(), 'args:', p.args);
}

// Edge 7: Zero value '0' vs false vs empty string in env variables or boolean flags
{
  const p = new Command();
  p.exitOverride();
  p.addOption(new Option('-b, --bool').env('TEST_BOOL'));
  process.env.TEST_BOOL = '0';
  p.parse(['node', 'test']);
  console.log('bool env TEST_BOOL="0":', p.opts());
}

// Edge 8: Option with choices including empty string or negative numbers
{
  const p = new Command();
  p.exitOverride();
  p.addOption(new Option('-c, --choice <val>').choices(['', '0', '-1']));
  p.parse(['node', 'test', '-c', '']);
  console.log('choices with "":', p.opts());
  
  const p_neg = new Command();
  p_neg.exitOverride();
  p_neg.addOption(new Option('-c, --choice <val>').choices(['', '0', '-1']));
  try {
    p_neg.parse(['node', 'test', '-c', '-1']);
    console.log('choices with -1:', p_neg.opts());
  } catch (e) {
    console.log('choices with -1 threw:', e.code, e.message);
  }
}
test3.mjs
import { Command } from 'commander';

console.log('--- TEST 3: Negative numbers & digit options ---');

// Case A: Leaf command without digit options
const pA = new Command();
pA.exitOverride();
pA.option('-t, --threshold [val]', 'threshold');
pA.option('-v, --verbose', 'verbose');
pA.parse(['node', 'test', '-t', '-10']);
console.log('Case A (no digit options) opts:', pA.opts());

// Case B: Leaf command WITH digit option (-1)
const pB = new Command();
pB.exitOverride();
pB.option('-1, --fast', 'fast mode');
pB.option('-t, --threshold [val]', 'threshold');
pB.parse(['node', 'test', '-t', '-10']);
console.log('Case B (with digit option -1, passing -10):');
test4.mjs
import { Command } from 'commander';

console.log('--- TEST 4: Comparing behavior of negative numbers with and without digit options ---');

// Setup 1: No digit option
const p1 = new Command();
p1.exitOverride();
p1.option('-t, --threshold [val]', 'threshold');
p1.parse(['node', 'test', '-t', '-1']);
console.log('p1 (-t -1 without digit option):', p1.opts());
// Output: { threshold: '-1' }

// Setup 2: With digit option -1
const p2 = new Command();
p2.exitOverride();
p2.option('-1, --fast', 'fast mode');
p2.option('-t, --threshold [val]', 'threshold');
p2.parse(['node', 'test', '-t', '-1']);
console.log('p2 (-t -1 with digit option -1):', p2.opts());
// Output: { fast: true, threshold: undefined } or { fast: true }!

// Setup 3: Required argument vs Optional argument
const p3 = new Command();
p3.exitOverride();
p3.option('-1, --fast', 'fast mode');
p3.option('-r, --required <val>', 'required arg');
p3.parse(['node', 'test', '-r', '-1']);
console.log('p3 (-r -1 with digit option -1, required arg):', p3.opts());
// Output: { required: '-1' }!
test5.mjs
import { Command } from 'commander';

console.log('--- TEST 5: Variadic options with negative numbers ---');

// Variadic required
const p1 = new Command();
p1.exitOverride();
p1.option('-n, --numbers <vals...>');
p1.parse(['node', 'test', '-n', '-1', '-2', '3']);
console.log('Variadic required without digit opt:', p1.opts());

// Variadic required WITH digit opt
const p2 = new Command();
p2.exitOverride();
p2.option('-1, --one');
p2.option('-n, --numbers <vals...>');
try {
  p2.parse(['node', 'test', '-n', '-1', '-2', '3']);
  console.log('Variadic required with digit opt:', p2.opts());
} catch (e) {
  console.log('Variadic required with digit opt threw:', e.code, e.message);
}

// Variadic optional
const p3 = new Command();
p3.exitOverride();
p3.option('-n, --numbers [vals...]');
p3.parse(['node', 'test', '-n', '-1', '-2', '3']);
console.log('Variadic optional without digit opt:', p3.opts());

// Variadic optional WITH digit opt
const p4 = new Command();
p4.exitOverride();
p4.option('-1, --one');
p4.option('-n, --numbers [vals...]');
try {
  p4.parse(['node', 'test', '-n', '-1', '-2', '3']);
  console.log('Variadic optional with digit opt:', p4.opts());
} catch (e) {
  console.log('Variadic optional with digit opt threw:', e.code, e.message);
}
test6.mjs
import { Command } from 'commander';

console.log('--- TEST 6: Positional arguments and negative numbers ---');

// Root with argument only (leaf)
const leaf = new Command();
leaf.exitOverride();
leaf.argument('<target>', 'target position');
leaf.parse(['node', 'test', '-50']);
console.log('Leaf command with -50:', leaf.processedArgs);

// Root with argument AND subcommand
const rootWithSub = new Command();
rootWithSub.exitOverride();
rootWithSub.argument('[target]', 'target position');
rootWithSub.command('build');
try {
  rootWithSub.parse(['node', 'test', '-50']);
  console.log('Root with sub with -50:', rootWithSub.processedArgs);
} catch (e) {
  console.log('Root with sub threw on -50:', e.code, e.message);
}
test_clean.mjs
import assert from 'node:assert/strict';
import { Command, CommanderError } from 'commander';

const program = new Command();
program.exitOverride();
program.configureOutput({ writeErr: () => {} });
program.option('-1, --one-line');
program.argument('[offset]');

assert.throws(
  () => program.parse(['node', 'cli', '-5']),
  (err) => {
    assert(err instanceof CommanderError);
    assert.strictEqual(err.code, 'commander.unknownOption');
    return true;
  }
);
console.log('Clean error handling verified');
test_prototype.mjs
import assert from 'node:assert/strict';
import { Command, CommanderError } from 'commander';

// 1. First contract line: With a digit flag (-1), optional option receives `true` instead of '-1', and -1 triggers the digit option
{
  const program = new Command();
  program.exitOverride();
  program.option('-1, --one-line', 'display one line');
  program.option('-t, --threshold [val]', 'cutoff threshold');

  program.parse(['node', 'cli', '-t', '-1']);
  const opts = program.opts();

  assert.strictEqual(opts.threshold, true);
  assert.strictEqual(opts.oneLine, true);
}

// 2. Without digit flags, optional option consumes -1 as its value string
{
  const program = new Command();
  program.exitOverride();
  program.option('-v, --verbose', 'verbose output');
  program.option('-t, --threshold [val]', 'cutoff threshold');

  program.parse(['node', 'cli', '-t', '-1']);
  const opts = program.opts();

  assert.strictEqual(opts.threshold, '-1');
  assert.strictEqual(opts.verbose, undefined);
}

// 3. Required argument options unconditionally consume negative numbers as values even when digit flags exist
{
  const program = new Command();
  program.exitOverride();
  program.option('-1, --one-line', 'display one line');
  program.option('-r, --required <val>', 'required value');

  program.parse(['node', 'cli', '-r', '-1']);
  const opts = program.opts();

  assert.strictEqual(opts.required, '-1');
  assert.strictEqual(opts.oneLine, undefined);
}

// 4. Multi-digit negative number -10 with digit flag -1 parses -1 and throws unknownOption for remaining -0
{
  const program = new Command();
  program.exitOverride();
  program.option('-1, --one-line', 'display one line');
  program.option('-t, --threshold [val]', 'cutoff threshold');

  assert.throws(
    () => program.parse(['node', 'cli', '-t', '-10']),
    (err) => {
      assert(err instanceof CommanderError);
      assert.strictEqual(err.code, 'commander.unknownOption');
      assert.match(err.message, /unknown option '-0'/);
      return true;
    }
  );
}

// 5. Leaf command positional arguments reject negative numbers when a digit flag exists
{
  const program = new Command();
  program.exitOverride();
  program.option('-1, --one-line', 'display one line');
  program.argument('[offset]', 'coordinate offset');

  assert.throws(
    () => program.parse(['node', 'cli', '-5']),
    (err) => {
      assert(err instanceof CommanderError);
      assert.strictEqual(err.code, 'commander.unknownOption');
      assert.match(err.message, /unknown option '-5'/);
      return true;
    }
  );
}

// 6. Without digit flags, leaf command accepts negative number positional argument
{
  const program = new Command();
  program.exitOverride();
  program.argument('[offset]', 'coordinate offset');

  program.parse(['node', 'cli', '-5']);
  assert.deepStrictEqual(program.processedArgs, ['-5']);
}

console.log('All prototype contract assertions passed!');

Seeder de origem

csx-seed