commander known bugs

npm

29 known bugs in commander, with affected versions, fixes and workarounds. Sourced from upstream issue trackers.

29
bugs
Known bugs
SeverityAffectedFixed inTitleStatusSource
medium2.9.0\u2014
git-style subcommands mess up argument order when using boolean flags
**index.js** ``` js var command = require('commander') var cmd = command .command('hello', 'description') .parse(process.argv) ``` **index-hello.js** ``` js var command = require('commander') var cmd = command .option('--dry-run', 'prints actions, but takes none') .parse(process.argv) console.log('opts', cmd.opts()) console.log('args', cmd.args) ``` **output** ``` $ node index.js hello 1 2 --dry-run 3 4 5 6 opts { dryRun: true } args [ '1', '2', '4', '5', '6', '3' ] ``` Note how `3` has been shifted to the end. This really messes with you when working with subcommands that expect a specific argument ordering. _Found and tested against `[email protected]`_
fixedgithub:508
mediumany\u2014
Cannot pass more than 4 arguments in literal mode
Ref to https://github.com/Unitech/pm2/issues/2064 [This is the main pm2](https://github.com/Unitech/pm2/blob/development/bin/pm2) file on which we use commander.js, but we don't do anything fancy with commander.js
fixedgithub:552
medium1.0.0\u2014
Command log + option log
When declaring a command with a defined name and declaring option with the same name, it does not works: ``` javascript var program = require('commander'); program.version('1.0.0') .option('--log [path]', 'log path') program.command('logs') .alias('log') .action(function() { console.log(program.log); }); program.parse(process.argv); ``` ``` bash $ node test.js log --log 'test' ``` It throws: ``` /home/unitech/keymetrics/pm2/node_modules/commander/index.js:298 args.push(self); ^ TypeError: args.push is not a function at Command.listener (/home/unitech/keymetrics/pm2/node_modules/commander/index.js:298:12) at emitOne (events.js:82:20) at Command.emit (events.js:169:7) at Command.parseOptions (/home/unitech/keymetrics/pm2/node_modules/commander/index.js:699:14) at Command.parse (/home/unitech/keymetrics/pm2/node_modules/commander/index.js:455:21) at Object.<anonymous> (/home/unitech/keymetrics/pm2/test.js:13:9) at Module._compile (module.js:409:26) at Object.Module._extensions..js (module.js:416:10) at Module.load (module.js:343:32) at Function.Module._load (module.js:300:12) ```
fixedgithub:553
medium0.0.1\u2014
When arguments() argument is provided, unrecognized flags are silently deleted (no error prints)
I am using commander 2.9.0 (graceful-readlink 1.0.1) on node v4.4.7 (on Windows, running in MSYS2, if it matters). I run the following test program: ``` var commander = require("commander") commander .version("0.0.1") .option('-x, --x-flag', 'A flag') .arguments("<file>") .parse(process.argv) if (commander.xFlag) console.log("Got -x") console.log("Args:", commander.args) ``` I find that if I do not supply the `<file>` argument, if I pass a nonsense flag like --nonsense, I will get a nice error message. If I _do_ supply the `<file>` argument, then any nonsense flags included will be silently discarded. Moreover, commander appears to assume each nonsense flag takes one option-argument, and it silently discards that, too. These flags are not appended to commander.args or anything. They just disappear. A demonstration: ``` $ node testcommander.js Args: [] $ node testcommander.js -x Got -x Args: [] $ node testcommander.js --nonsense -x error: unknown option `--nonsense' $ node testcommander.js -x 1 2 3 Got -x Args: [ '1', '2', '3' ] $ node testcommander.js --NONSENSE 1 2 3 Args: [ '2', '3' ] $ node testcommander.js 1 2 3 --NON-SENSE Args: [ '1', '2', '3' ] $ node testcommander.js 1 2 3 --NON-SENSE QQDFFR -x Got -x Args: [ '1', '2', '3' ] ``` **Expected behavior**: A --flag which is not recognized should result in commander printing an error. This is a pretty bad bug. Not only does commander allow something which should be an error, and not only does it do it inconsistently for the same script depending on input, but since commander does this totally silently I cannot even write my own recovery code. If the lost arguments had been appended to `commander.args` at least I could detect it and raise my own error.
fixedgithub:561
mediumany\u2014
Git-style subcommands not working if files are implicit '.js' but command is ran without '.js'
If your command files use the `.js` extension, but you run the command via `node mycommand` instead of `node mycommand.js`, any git-style sub-commands will fail in `Command.prototype#executeSubCommand` This failure is on line 531, column 15 of `index.js`: ```js var f = argv[1]; // ... link = fs.lstatSync(f).isSymbolicLink() ? fs.readlinkSync(f) : f; ``` Specifically this part is failing: ```js fs.lstatSync(f) ``` This is causing an error because Commander is looking for the file that corresponds to argv[1], so in this specific case, argv[1] doesn't match the actual file name.
fixedgithub:785
medium0.1.0\u2014
Option Coercion - parseInt when combined with a default value will result in NaN
Adding a default value to an option with `parseInt` will result in `NaN` in many cases. `parseInt` take two arguments -- `string` and `radix` -- and if you pass a default value to the option, the option will call `parseInt` with the default value as the `radix`. For example, an option with a default value of 90 and an actual value of 100 will invoke `parseInt(100, 90)`. This is not a problem with `parseFloat` because it only takes one argument. Source: ```javascript #!/usr/bin/env node 'use strict'; const program = require('commander'); const version = require('./package.json').version; process.title = 'my-app'; program .name('my-app') .version(version, '-v, --version'); program .command('start') .description('start the app') .option('-d, --directory <directory>', 'directory for the thing', '/srv') .option('-p, --port <port>', 'port number for the thing', parseInt, 8080) .action(({ directory, port }) => console.log(directory, port)); program.parse(process.argv); if (!program.args.length) program.help(); ``` Expected: ``` $ ./cli.js start --port 80 /srv 80 ``` Actual: ``` $ ./cli.js start --port 80 /srv NaN ``` I'm not sure what the fix should be in this case. Based on the Coercion section of the REAMDE, the way that commander deals with the default value argument is desirable. The `collect` function in particular shows that the default value of an empty array is being used as part of the coercion: (reproduced from README) ```javascript function range(val) { return val.split('..').map(Number); } function list(val) { return val.split(','); } function collect(val, memo) { memo.push(val); return memo; } function increaseVerbosity(v, total) { return total + 1; } program .version('0.1.0') .usage('[options] <file ...>') .option('-i, --integer <n>', 'An integer argument', parseInt) .option('-f, --float <n>', 'A float argument', parseFloat) .option('-r, --range <a>..<b>', 'A range', range) .option('-l, --list <items>', 'A list', list) .option('-o, --optional [value]', 'An optional value') .option('-c, --collect [value]', 'A repeatable value', collect, []) .option('-v, --verbose', 'A value that can be increased', increaseVerbosity, 0) .parse(process.argv); console.log(' int: %j', program.integer); console.log(' float: %j', program.float); console.log(' optional: %j', program.optional); program.range = program.range || []; console.log(' range: %j..%j', program.range[0], program.range[1]); console.log(' list: %j', program.list); console.log(' collect: %j', program.collect); console.log(' verbosity: %j', program.verbose); console.log(' args: %j', program.args); ``` If this really is desirable, then I think a note about it in the Coercion section is appropriate. It's still possible to use parseInt, you just have to wrap it: ```javascript #!/usr/bin/env node 'use strict'; const program = require('commander'); const version = require('./package.json').version; process.title = 'my-app'; program .name('my-app') .version(version, '-v, --version'); const int = (value) => parseInt(value); program .command('start') .description('start the app') .option('-d, --directory <directory>', 'directory for the thing', '/srv') .option('-p, --port <port>', 'port number for the thing', int, 8080) .action(({ directory, port }) => console.log(directory, port)); program.parse(process.argv); if (!program.args.length) program.help(); ```
fixedgithub:834
medium0.0.1\u2014
Regression between v1.16 and v1.17 when no command are passed and '*' is registered
There is a regression in the version v1.17 See this sample: ```js var program = require("commander"); program .version("0.0.1") .command("*") .description("test") .action(function(cmd) { cmdValue = cmd; }); program.parse(process.argv); if (typeof cmdValue === "undefined") { console.error("no command given!"); } else { console.log("command:", cmdValue); } ``` ## v1.16 ```bash $ node test.js no command given! ``` ## v1.17 ```bash $ node test.js command: Command { commands: [], options: [], _execs: {}, _allowUnknownOption: false, _args: [], _name: '*', _noHelp: false, parent: Command { commands: [ [Circular] ], options: [ [Object] ], _execs: {}, _allowUnknownOption: false, _args: [], _name: 'test', Command: { [Function: Command] super_: [Object] }, Option: [Function: Option], _version: '0.0.1', _versionOptionName: 'version', _events: { 'option:version': [Function], 'command:*': [Function: listener] }, _eventsCount: 2, rawArgs: [ 'C:\\Program Files\\nodejs\\node.exe', 'C:\\Users\\schroeterm\\Desktop\\test\\test.js' ], args: [] }, _description: 'test', _argsDescription: undefined } ```
fixedgithub:843
medium0.0.1\u2014
Built-in help subcommand does not work with aliased git-style commands
# Example ```js #!/usr/bin/env node const program = require('commander'); program .version('0.0.1') .description('Fake package manager') .command('install [name]', 'install one or more packages').alias('i'); program.parse(process.argv); ``` When running the built-in help command on the alias (`pm help i`), this happens: ## Expected Behavior The alias gets resolved to `install`, and the information is read from `pm-install` ## Actual Behavior The command attempts to read `pm-i` and fails, as it does not exist.
fixedgithub:948
medium2.13.0\u2014
Subcommand destroys ordering of options
Commander.js version: 2.13.0 The feature "subcommand in dedicated binary" destroys option ordering for boolean longopts. The bug is that, for unknown options, commander always assumes they have an argument. Boolean longopts don't have an argument, so commander assumes the next option to be an argument to the boolean option. Unknown options get sorted to the end of the argument list, so option ordering is nonsensical after the aforementioned wrong assumption has taken place. Example: ``` $ ls somecommand somecommand-subcommand1 ``` Contents of somecommand: ``` program.command('subcommand1', 'execute subcommand1'). ``` Triggering the bug: `$ ./somecommand subcommand1 --bool-option subcommand2 --subcommand2-option subcommand2-argument` should result in `./somecommand-subcommand1 --bool-option subcommand2 --subcommand2-option subcommand2-argument` being called but commander executes `./somecommand-subcommand1 subcommand2-argument --bool-option subcommand2` This is a serious bug because the usage output cannot be made correct for the user, it is confusing the user and it results in the program not working without user feedback in combination with bug #961 . It also could lead to random logic being executed if the options are implemented in a specific manner in the subcommand.
fixedgithub:962
mediumany\u2014
The Command.prototype.parse() method has issues.
This method has the following issues: * when registered `subcommand`, thier arguments and options isn't parsed to check valid. * when registered `action`, `this.parseArgs()` called subcommand without parsing their arguments and options. As a result, this method's arguments are not evaluted correctly in subcommand. In the following code expect to occur `error: missing required argument "file"` but not now. ``` parse .command('install <file>') .parse('node', 'main.js', 'install') // Expect error but not. ``` Also now `the required argument` will not correctly work. [Fix to fail if required arguments don't exist.](https://github.com/tj/commander.js/pull/941) So it seems that this method should be reconsidered fundamentally. Thank you for the wonderful library. # Related https://github.com/tj/commander.js/pull/941
fixedgithub:995
medium0.0.1\u2014
Passing command option leaves content in args
As [discussed here](https://github.com/tj/commander.js/issues/978#issuecomment-525692913), opening as a new issue. I'm trying to find out whether a command has been executed. The simple idea is that if a command is given, it should be executed (and nothing else). If no command is given, the default logic at the bottom should execute (but not otherwise). In all cases, the global option --load should be supported. Here's the test code: ```js var program = require('commander'); program.version('0.0.1').option('-l, --load <name>', 'load something'); program .command('doit [id]') .description('do something') .option('--better', 'do it better') .action((id, cmd) => { console.log('executing doit action'); console.log('id is', id); console.log('global load option is ', cmd.parent.load); console.log('cmd.better is', cmd.better); }); program.parse(process.argv); if (program.args.length === 0) console.log('started without command, executing main logic'); ``` This works correctly when I execute like this: ```shell ➜ node test.js -l loadname doit myid executing doit action id is myid global load option is loadname cmd.better is undefined ``` However, when I pass the --better option to the command, the whole thing breaks and the "main logic" is executed in addition to the command: ```shell ➜ node test.js -l loadname doit --better myid executing doit action id is myid global load option is loadname cmd.better is true started without command, executing main logic ``` Unexpectedly, `args` contains information after the action has been executed, *if* the command option `--better` is passed.
fixedgithub:1032
medium0.0.1\u2014
*Bug* When specify none-defined options followed by values don't exit program with error
```js // File: index.js const program = require('commander'); program .version('0.0.1') .parse(process.argv); const args = program.args; console.log(args); ``` ```bash $ node index.js --bug error: unknown option '--bug' $ node index.js --bug 0 error: unknown option '--bug' $ node index.js --bug 0 1 2 3 [ '1', '2', '3' ] ``` dependency: ```json $ cat package.json { "dependencies": { "commander": "^3.0.1" } } ``` Expecting exit code with an error instead of continue of it.
fixedgithub:1039
mediumany\u2014
Help option does not display help when using requiredOption
Hi, I wanted to have one option required. Once I added one, the help message will no longer show unless you include the required option. I would have expected it to show the help. I created some sample code, from one of your samples. Test Code: ``` const commander = require("commander"); const program = new commander.Command(); program .option("-d, --debug", "output extra debugging") .requiredOption("-s, --small", "small pizza size") .option("-p, --pizza-type <type>", "flavour of pizza"); program.parse(process.argv); if (program.debug) console.log(program.opts()); console.log("pizza details:"); if (program.small) console.log("- small pizza size"); if (program.pizzaType) console.log(`- ${program.pizzaType}`); ``` Output: ``` $ node test.js -h error: required option '-s, --small' not specified ``` If I remove the requiredOption I get the expected output: ``` $ node test.js -h Usage: test [options] Options: -d, --debug output extra debugging -s, --small small pizza size -p, --pizza-type <type> flavour of pizza -h, --help output usage information ```
fixedgithub:1089
mediumany\u2014
about commander -h and help command
First, the cli code as: ```javascript const cli = require('commander'); const plugin = require('./commandos/plugin'); cli. command('plugin [command] [pluginName]'). description(DESCRIPTION.plugin). action(plugin); cli. command('help'). description(DESCRIPTION.help). action(()=>cli.help()); cli.parse(process.argv); ``` When I type the command as in terminal: ```shell cli plugin help ``` it was not run the [plugin] function, I can not get [command] param, it just print help information in the terminal? it is a bug, right?
fixedgithub:1153
mediumany\u2014
TypeError when running nested subcommand
Repo with minimal example code to reproduce: https://github.com/maximilianschmitt/commander-debug --- Hi! I'm currently developing a CLI where I'm wanting to nest the subcommands. I have the following files: ``` cli/ hello hello-world # `hello world` hello-world-germany # `hello world germany` ``` And I'm trying to run them like so: ``` $ node cli/hello # Should run cli/hello $ node cli/hello world # Should run cli/hello-world $ node cli/hello world germany # Should run cli/hello-world-germany ``` I've read that when defining nested subcommands, you need to specify the `executableFile`, so I've done this in `cli/hello`: ``` #!/usr/bin/env node const { program, Command } = require("commander"); const packageJSON = require("../package.json"); program.version(packageJSON.version); const helloWorld = new Command("world"); helloWorld.command("germany", "Saying hello to Germany", { executableFile: "hello-world-germany", }); program.addCommand(helloWorld); program.parse(process.argv); ``` However, when I run `node cli/hello world germany`, I get a TypeError: ``` ~/Desktop/commander-debug $ node cli/hello world germany internal/validators.js:120 throw new ERR_INVALID_ARG_TYPE(name, 'string', value); ^ TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received null at validateString (internal/validators.js:120:11) at Object.extname (path.js:1229:5) at Command._executeSubCommand (/Users/max/Desktop/commander-debug/node_modules/commander/index.js:774:46) at Command._dispatchSubcommand (/Users/max/Desktop/commander-debug/node_modules/commander/index.js:863:12) at Command._parseCommand (/Users/max/Desktop/commander-debug/node_modules/commander/index.js:882:12) at Command._dispatchSubcommand (/Users/max/Desktop/commander-debug/node_modules/commander/index.js:865:18) at Command._parseCommand (/Users/max/Desktop/commander-debug/node_modules/commander/index.js:882:12) at Command.parse (/Users/max/Desktop/commander-debug/node_modules/commander/index.js:717:10) at Object.<anonymous> (/Users/max/Desktop/commander-debug/cli/hello:14:9) at Module._compile (internal/modules/cjs/loader.js:1138:30) { code: 'ERR_INVALID_ARG_TYPE' } ``` Is this a bug or am I doing something wrong? Thanks for your help!
fixedgithub:1274
mediumany\u2014
BUG: defining an option which includes `no-` makes the option true by default
**Current Behavior -** If we define an option whose name contains `no-` for e.g. `module-no-parse`, it makes the option `true` by default. **Expected Behavior -** It is supposed to do this only for flags with leading `no-` as mentioned in docs. https://github.com/tj/commander.js/#other-option-types-negatable-boolean-and-flagvalue > You can specify a boolean option long name with a leading no- to set the option value to false when used. Defined alone this also makes the option true by default. **Steps to reproduce -** Define an option whose name includes `no-` e.g. `module-no-parse`. Check its default value in the parser. ![Screenshot at 2020-07-16 20-28-38](https://user-images.githubusercontent.com/46647141/87770313-813be300-c83c-11ea-859e-4ad9ac7fc54e.png) **Addition Info** Bug found via https://github.com/webpack/webpack-cli/issues/1679
fixedgithub:1301
mediumany\u2014
addHelpCommand missing from TypeScript definitions
Hello, It looks the addHelpCommand method definition is missing in the TypeScript definitions file here: https://github.com/tj/commander.js/blob/master/typings/index.d.ts Is this a bug?
fixedgithub:1374
mediumany\u2014
`command:<name>` event doesn't bubble to the parent
Hey, Not sure if I am using this correctly, but it does seem to be a good use case and not far away from working. My program is as follows: ``` const config = program.commad('config'); const start = program.command('start'); program.on('command:*', () => /* handle unexpected command */); program.on('command:config', () => /* never gets called */); ``` In the above example, when `config` command is executed, the `command:config` listener never gets executed. After console logging around the Commander source code, I have found out that the reason this doesn't work is that listener is registered on `parent` (in this context, main program) whereas the `emit` function is called on a subcommand (`config`). Changing `this.emit` to `this.parent.emit` fixes it https://github.com/tj/commander.js/blob/master/index.js#L1003 Is there any way to bubble events up? It seems to be quite natural to listen to `command:<name>` on the main object, otherwise, there's no difference from attaching a listener to `config` vs tweaking action handler.
fixedgithub:1402
medium4.0.1\u2014
Options parsed before validating argument
Hi there, This is a great project, thank you for maintaining this. We're in the process of upgrading from v4.0.1 to v7.0.0 with the new features. We have a small problem whereby options are being parsed before the arguments themselves are validated. We were hoping to be able to continue to listen to `command:*` to detect bad arguments, as we've currently hooked it up to our own suggestion engine to provide "did you mean" suggestions for the bad argument. Upgrading to v7.0.0 has broken this functionality for us. E.g. ``` $ program bad_argument --help # Outputs the help menu instead of complaining that bad_argument is a bad argument ``` Another example: ``` $ program lintt --fix # Complains that --fix is not a valid option. Instead, we expected `lintt` to be # detected as a bad argument so we can suggest `lint` to the user. ``` Minimal reproduction: ``` import commander from 'commander'; const program = new commander.Command(); program.on('command:*', (arg: string) => { console.log(`Detected bad arg: ${arg}`); }); program.command('lint').action(() => { console.log('lint'); }); program.parse(); ``` I dug into the source code a bit and think I found it. It appears to be parsing the options and throwing the error first, before reaching the "command:*" section. https://github.com/tj/commander.js/blob/034ad9f326ee2b26001b864adda5fea465ee148b/index.js#L1472 Is there a solution or workaround to this that I haven't found? Thanks :).
fixedgithub:1460
mediumany\u2014
Command' is not assignable to type CommanderStatic.Command
I try to create an init command using TypeScript, as follows: ```ts import { Command } from "commander"; export const init = ():Command => { const init = new Command("init"); init .arguments("[name]") .option("--disable-lint", "disable lint", false) .action(async (name = "", options) => { // my action }); return init; }; ``` But at last return init, typescript report error: TS2322: Type 'import("/Users/qishaoxuan/work/leo/node_modules/commander/typings/index").Command' is not assignable to type 'import("/Users/qishaoxuan/work/leo/node_modules/commander/typings/index").CommanderStatic.Command'.   The types returned by 'version(...)' are incompatible between these types.     Type 'Command' is not assignable to type 'this'.       'Command' is assignable to the constraint of type 'this', but 'this' could be instantiated with a different subtype of constraint 'Command'.
fixedgithub:1465
mediumany\u2014
[Question] How to get option name?
From docs: ``` program .option('-d, --debug', 'output extra debugging') .option('-s, --small', 'small pizza size') .option('-p, --pizza-type <type>', 'flavour of pizza'); program.parse(process.argv); const options = program.opts(); if (options.debug) console.log(options); console.log('pizza details:'); if (options.small) console.log('- small pizza size'); if (options.pizzaType) console.log(`- ${options.pizzaType}`); ``` so, the question is how do know option `pizza-type` after parse will get from field `pizzaType`? Do commanderjs provide any function to get value `pizzaType` after bind option `.option('-d, --debug', 'output extra debugging')`? Thanks!
fixedgithub:1480
mediumany\u2014
Option.argumentRejected declared but not implemented.
Hi in your typing file your write: ````typescript /** * Validation of option argument failed. * Intended for use from custom argument processing functions. */ argumentRejected(messsage: string): never; ```` but `argumentRejected` do not exist anywhere.
fixedgithub:1598
medium2.20.0\u2014
Refactor option value processing to improve maintainability and fix bugs
There is some subtle code in `addOption` which is hard to make sense of, and has some bugs. If is solid on options used once on command line, but from code inspection I was able to reproduce some logic errors affecting repeated options for boolean with a non-boolean default value (bit obscure!) and optional options. The problems have been present for a long time. I was able to reproduce with v2.20.0 and traced code back to at least v1.1.0. The issues have not been generating reports, and the motivation for changing the code is as much to make the code easier to work on as to improve the behaviour. https://github.com/tj/commander.js/blob/43f4743864e2f670db5eebcf88c92aa4612c54f1/lib/command.js#L515
fixedgithub:1648
medium9.1.0\u2014
9.1.0 - option.conflicts not working
I'm trying to use the option conflicts configuration, but it doesn't appear to catch the conflicts. ``` const { program, Option } = require("commander"); const handleAction = (command) => { const options = program.opts(); //options.exact && (options.wild || options.all) && console.log("conflict"); console.log( `${command.name()} with options ${JSON.stringify(program.opts())}` ); }; //Global options program .addOption( new Option("-a, --all", "all wallets").conflicts(["exact", "wild"]) ) .addOption( new Option("-x, --exact <name>", "exact wallet name").conflicts([ "all", "wild", ]) ) .addOption( new Option("-w, --wild <partial>", "wild card").conflicts(["all", "exact"]) ) .option("-p, --password <password>"); //Sub commands program.command("claim").action((options, command) => { handleAction(command); }); program.parse(); ``` When I run with: node commands.js claim -a -x OG The result is: claim with options {"all":true,"exact":"OG"} Have I configured it incorrectly? Also tried specifying just the short names. Same result. Thanks.
fixedgithub:1710
mediumany\u2014
.helpOption(false) also disables subcommand help command
In this example, I'd like to disable impilcit help **option** and only leave impicit help **command**. `test.mjs`: ``` #!/usr/bin/env node import { Command } from 'commander'; const cmd = new Command (); cmd .helpOption (false) .command ('meow') .option ('-l, [--loud]') cmd.parse (); ``` If I run `test.mjs`, I get ``` Usage: test [command] Commands: meow [options] help [command] display help for command ``` as expected, but if I run `test.mjs help meow`, I get an error: `error: unknown option '--help' // what option, I thought I was calling help command?`, while expected outcome would be ``` Usage: test meow [options] Options: -l, [--loud] ```
fixedgithub:1863
mediumany\u2014
Exit Code is Zero if Subcommand Killed by Signal
If a subcommand child process is killed by a signal (e.g. `SIGKILL`), then commander will exit with exit code zero. I'm seeing this where OOM was killing the subcommand but commander was exiting with zero. Relevant code looks to be here. The arguments to the `close` event are `(code, signal)` and in the case of killed by signal, `code` will be `null`, so `process.exit` gets called with `null` which leads to exiting with zero. Additionally, should the `exitCallback` case (on line 1036) be using `proc.exitCode` instead of `process.exitCode`? The latter doesn't seem correct. https://github.com/tj/commander.js/blob/4ef19faac1564743d8c7e3ce89ef8d190e1551b4/lib/command.js#L1032-L1038 Possible fix for the issue could be to bubble up signals, although I'm not sure how to handle the `exitCallback` case then, since AFAIK there's no way to get an exit code for a signal from Node.js (other than mapping it yourself). ```js proc.on('close', (code, signal) => { if (signal) { process.kill(process.pid, signal); } else { process.exit.bind(process)(code); } }); ``` Alternatively a fixed exit code of 1 could be used in the case of a signal, which would work for the `exitCallback` case. However, that's not desirable since it will hide the underlying exit code from the subcommand. Manually mapping signals to exit codes might be the simplest way to handle this for both cases.
fixedgithub:2021
mediumany\u2014
Option.fullDescription() does not exist
`Option.fullDescription()` is defined in the TypeScript definition file `index.d.ts`, but it does not exist in the implementation (`Option.js`). Either fix type definition or add implementation.
fixedgithub:2190
mediumany\u2014
Strange API behaviour for command description
When adding description to command declaration, command does not work. Working code: ``` program.command('analyze') .description('Do analyze.') .action(() => console.info("Hello explain!"); ``` Execute: ``` > node index.js analyze > Hello explain! ``` Not working code: ``` program.command('analyze', 'Do analyze.') .action(() => console.info("Hello explain!"); ``` Execute: ``` > node index.js analyze internal/modules/cjs/loader.js:892 throw err; ^ Error: Cannot find module 'C:\Dev\stuff\npm-dependency-inspector\index-analyze' ?[90m at Function.Module._resolveFilename (internal/modules/cjs/loader.js:889:15)?[39m ?[90m at Function.Module._load (internal/modules/cjs/loader.js:745:27)?[39m ?[90m at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:76:12)?[39m ?[90m at internal/main/run_main_module.js:17:47?[39m { code: ?[32m'MODULE_NOT_FOUND'?[39m, requireStack: [] } ``` I spent HOURS to find a way to make commander work for simpliest command. Read all docummentation, tried several versions, and only happy accident helped me - I added description for one command, and do not added to another. So I found, that another command working and this give me a tip. I think, when description specified, or command options specified, commander begin interpretate it as executable command. If it is true, then action() should throw error - it is usless for executable command. WTF? Why simple adding description change behaviour totally? And where in documentation this behaviour is specified?
fixedgithub:2290
mediumany\u2014
copyInheritedSettings and configureOutput have side-effects
Hi - noticed something that maybe isn't desired behaviour with the above two methods. Since `copyInheritedSettings` sets `this._outputConfiguration = sourceCommand._outputConfiguration` and `configureOutput` does `Object.assign(...)` - this means that one command can change another command's settings unexpectedly: ```ts import {program, Command} from 'commander' const one = new Command('one') .description('A very very very very very very very very very very very very very very very very very very very very very very very very long description') .action(() => console.log('hi i am one')) .configureOutput({ writeOut: str => console.log(str + '🚀🚀🚀🚀'), getOutHelpWidth: () => 70, }) const two = new Command('two') .copyInheritedSettings(one) .description('Another very very very very very very very very very very very very very very very very very very very very very very very very long description') .action(() => console.log('hi i am two')) .configureOutput({ getOutHelpWidth: () => 200, }) program .addCommand(one) .addCommand(two) program.parse() ``` When you do `mycommand one --help` it uses 200 for the help width, not 70 as I'd expect. (Note: `mycommand two --help` prints the `🚀🚀🚀🚀` at the bottom, which _is_ correct/expected, IMO). Suggested solution: use a spread operator in either/both of the methods.
fixedgithub:2342
API access

Get this data programmatically \u2014 free, no authentication.

curl https://depscope.dev/api/bugs/npm/commander
commander bugs — known issues per version | DepScope | DepScope