Socket
Socket
Sign inDemoInstall

commander

Package Overview
Dependencies
0
Maintainers
6
Versions
115
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 2.20.0 to 3.0.0-0

26

CHANGELOG.md

@@ -0,2 +1,28 @@

3.0.0-0 Prerelease
=====
* Add option to specify executable file name (#999)
* e.g. `.command('clone', 'clone description', { executableFile: 'myClone' })`
* Change docs for `.command` to contrast action handler vs git-style executable. TypeScript now uses overloaded function. (#938 #990)
* Change to use straight quotes around strings in error messages (like 'this' instead of `this') (#915)
* Add TypeScript "reference types" for node (#974)
* Add support for hyphen as an option argument in subcommands (#697)
* Add support for a short option flag and its value to be concatenated for action handler subcommands (#599)
* e.g. `-p 80` can also be supplied as `-p80`
* Add executable arguments to spawn in win32, for git-style executables (#611)
* e.g. `node --harmony myCommand.js clone`
* Add parent command as prefix of subcommand in help (#980)
* Add optional custom description to `.version` (#963)
* e.g. `program.version('0.0.1', '-v, --vers', 'output the current version')`
* Add `.helpOption(flags, description)` routine to customise help flags and description (#963)
* e.g. `.helpOption('-e, --HELP', 'read more information')`
* Fix behavior of --no-* options (#795)
* can now define both `--foo` and `--no-foo`
* custom event listeners: `--no-foo` on cli now emits `option:no-foo` (previously `option:foo`)
* default value: defining `--no-foo` after defining `--foo` leaves the default value unchanged (previously set it to false)
* allow boolean default value, such as from environment (#987)
* Increment inspector port for spawned subcommands (#991)
* e.g. `node --inspect myCommand.js clone`
2.20.0 / 2019-04-02

@@ -3,0 +29,0 @@ ==================

334

index.js

@@ -48,3 +48,3 @@ /**

this.optional = flags.indexOf('[') >= 0;
this.bool = flags.indexOf('-no-') === -1;
this.negate = flags.indexOf('-no-') !== -1;
flags = flags.split(/[ ,|]+/);

@@ -64,5 +64,3 @@ if (flags.length > 1 && !/^[[<]/.test(flags[1])) this.short = flags.shift();

Option.prototype.name = function() {
return this.long
.replace('--', '')
.replace('no-', '');
return this.long.replace(/^--/, '');
};

@@ -79,3 +77,3 @@

Option.prototype.attributeName = function() {
return camelcase(this.name());
return camelcase(this.name().replace(/^no-/, ''));
};

@@ -109,66 +107,39 @@

this._name = name || '';
this._helpFlags = '-h, --help';
this._helpDescription = 'output usage information';
this._helpShortFlag = '-h';
this._helpLongFlag = '--help';
}
/**
* Add command `name`.
* Define a command.
*
* The `.action()` callback is invoked when the
* command `name` is specified via __ARGV__,
* and the remaining arguments are applied to the
* function for access.
* There are two styles of command: pay attention to where to put the description.
*
* When the `name` is "*" an un-matched command
* will be passed as the first arg, followed by
* the rest of __ARGV__ remaining.
*
* Examples:
*
* // Command implemented using action handler (description is supplied separately to `.command`)
* program
* .version('0.0.1')
* .option('-C, --chdir <path>', 'change the working directory')
* .option('-c, --config <path>', 'set config path. defaults to ./deploy.conf')
* .option('-T, --no-tests', 'ignore test hook')
*
* program
* .command('setup')
* .description('run remote setup commands')
* .action(function() {
* console.log('setup');
* .command('clone <source> [destination]')
* .description('clone a repository into a newly created directory')
* .action((source, destination) => {
* console.log('clone command called');
* });
*
* // Command implemented using separate executable file (description is second parameter to `.command`)
* program
* .command('exec <cmd>')
* .description('run the given remote command')
* .action(function(cmd) {
* console.log('exec "%s"', cmd);
* });
* .command('start <service>', 'start named service')
* .command('stop [service]', 'stop named serice, or all if no name supplied');
*
* program
* .command('teardown <dir> [otherDirs...]')
* .description('run teardown commands')
* .action(function(dir, otherDirs) {
* console.log('dir "%s"', dir);
* if (otherDirs) {
* otherDirs.forEach(function (oDir) {
* console.log('dir "%s"', oDir);
* });
* }
* });
*
* program
* .command('*')
* .description('deploy the given env')
* .action(function(env) {
* console.log('deploying "%s"', env);
* });
*
* program.parse(process.argv);
*
* @param {String} name
* @param {String} [desc] for git-style sub-commands
* @return {Command} the new command
* @param {string} nameAndArgs - command name and arguments, args are `<required>` or `[optional]` and last may also be `variadic...`
* @param {Object|string} [actionOptsOrExecDesc] - configuration options (for action), or description (for executable)
* @param {Object} [execOpts] - configuration options (for executable)
* @return {Command} returns new command for action handler, or top-level command for executable command
* @api public
*/
Command.prototype.command = function(name, desc, opts) {
Command.prototype.command = function(nameAndArgs, actionOptsOrExecDesc, execOpts) {
var desc = actionOptsOrExecDesc;
var opts = execOpts;
if (typeof desc === 'object' && desc !== null) {

@@ -179,3 +150,3 @@ opts = desc;

opts = opts || {};
var args = name.split(/ +/);
var args = nameAndArgs.split(/ +/);
var cmd = new Command(args.shift());

@@ -190,2 +161,7 @@

cmd._noHelp = !!opts.noHelp;
cmd._helpFlags = this._helpFlags;
cmd._helpDescription = this._helpDescription;
cmd._helpShortFlag = this._helpShortFlag;
cmd._helpLongFlag = this._helpLongFlag;
cmd._executableFile = opts.executableFile; // Custom name for executable file
this.commands.push(cmd);

@@ -344,10 +320,13 @@ cmd.parseExpectedArgs(args);

*
* // simple boolean defaulting to false
* // simple boolean defaulting to undefined
* program.option('-p, --pepper', 'add pepper');
*
* program.pepper
* // => undefined
*
* --pepper
* program.pepper
* // => Boolean
* // => true
*
* // simple boolean defaulting to true
* // simple boolean defaulting to true (unless non-negated option is also defined)
* program.option('-C, --no-cheese', 'remove cheese');

@@ -389,2 +368,4 @@ *

if (fn instanceof RegExp) {
// This is a bit simplistic (especially no error messages), and probably better handled by caller using custom option processing.
// No longer documented in README, but still present for backwards compatibility.
var regex = fn;

@@ -401,6 +382,9 @@ fn = function(val, def) {

// preassign default value only for --no-*, [optional], or <required>
if (!option.bool || option.optional || option.required) {
// when --no-* we make sure default is true
if (!option.bool) defaultValue = true;
// preassign default value for --no-*, [optional], <required>, or plain flag if boolean value
if (option.negate || option.optional || option.required || typeof defaultValue === 'boolean') {
// when --no-foo we make sure default is true, unless a --foo option is already defined
if (option.negate) {
var opts = self.opts();
defaultValue = Object.prototype.hasOwnProperty.call(opts, name) ? opts[name] : true;
}
// preassign only if we have a default

@@ -424,9 +408,9 @@ if (defaultValue !== undefined) {

// unassigned or bool
// unassigned or boolean value
if (typeof self[name] === 'boolean' || typeof self[name] === 'undefined') {
// if no value, bool true, and we have a default, then use it!
// if no value, negate false, and we have a default, then use it!
if (val == null) {
self[name] = option.bool
? defaultValue || true
: false;
self[name] = option.negate
? false
: defaultValue || true;
} else {

@@ -437,3 +421,3 @@ self[name] = val;

// reassign
self[name] = val;
self[name] = option.negate ? false : val;
}

@@ -478,7 +462,8 @@ });

// this user needs help
argv.push('--help');
argv.push(this._helpLongFlag);
}
// process argv
var parsed = this.parseOptions(this.normalize(argv.slice(2)));
var normalized = this.normalize(argv.slice(2));
var parsed = this.parseOptions(normalized);
var args = this.args = parsed.args;

@@ -489,22 +474,35 @@

// executable sub-commands
// (Debugging note for future: args[0] is not right if an action has been called)
var name = result.args[0];
var subCommand = null;
var aliasCommand = null;
// check alias of sub commands
// Look for subcommand
if (name) {
aliasCommand = this.commands.filter(function(command) {
subCommand = this.commands.find(function(command) {
return command._name === name;
});
}
// Look for alias
if (!subCommand && name) {
subCommand = this.commands.find(function(command) {
return command.alias() === name;
})[0];
});
if (subCommand) {
name = subCommand._name;
args[0] = name;
}
}
// Look for default subcommand
if (!subCommand && this.defaultExecutable) {
name = this.defaultExecutable;
args.unshift(name);
subCommand = this.commands.find(function(command) {
return command._name === name;
});
}
if (this._execs[name] && typeof this._execs[name] !== 'function') {
return this.executeSubCommand(argv, args, parsed.unknown);
} else if (aliasCommand) {
// is alias of a subCommand
args[0] = aliasCommand._name;
return this.executeSubCommand(argv, args, parsed.unknown);
} else if (this.defaultExecutable) {
// use the default subcommand
args.unshift(this.defaultExecutable);
return this.executeSubCommand(argv, args, parsed.unknown);
return this.executeSubCommand(argv, args, parsed.unknown, subCommand ? subCommand._executableFile : undefined);
}

@@ -521,6 +519,7 @@

* @param {Array} unknown
* @param {String} specifySubcommand
* @api private
*/
Command.prototype.executeSubCommand = function(argv, args, unknown) {
Command.prototype.executeSubCommand = function(argv, args, unknown, executableFile) {
args = args.concat(unknown);

@@ -534,9 +533,17 @@

args[0] = args[1];
args[1] = '--help';
args[1] = this._helpLongFlag;
}
var isExplicitJS = false; // Whether to use node to launch "executable"
// executable
var f = argv[1];
// name of the subcommand, link `pm-install`
var bin = basename(f, path.extname(f)) + '-' + args[0];
var pm = argv[1];
// name of the subcommand, like `pm-install`
var bin = basename(pm, path.extname(pm)) + '-' + args[0];
if (executableFile != null) {
bin = executableFile;
// Check for same extensions as we scan for below so get consistent launch behaviour.
var executableExt = path.extname(executableFile);
isExplicitJS = executableExt === '.js' || executableExt === '.ts' || executableExt === '.mjs';
}

@@ -547,3 +554,3 @@ // In case of globally installed, get the base dir where executable

var resolvedLink = fs.realpathSync(f);
var resolvedLink = fs.realpathSync(pm);

@@ -556,3 +563,2 @@ baseDir = dirname(resolvedLink);

// whether bin file is a js script with explicit `.js` or `.ts` extension
var isExplicitJS = false;
if (exists(localBin + '.js')) {

@@ -564,2 +570,5 @@ bin = localBin + '.js';

isExplicitJS = true;
} else if (exists(localBin + '.mjs')) {
bin = localBin + '.mjs';
isExplicitJS = true;
} else if (exists(localBin)) {

@@ -576,3 +585,3 @@ bin = localBin;

// add executable arguments to spawn
args = (process.execArgv || []).concat(args);
args = incrementNodeInspectorPort(process.execArgv).concat(args);

@@ -585,2 +594,4 @@ proc = spawn(process.argv[0], args, { stdio: 'inherit', customFds: [0, 1, 2] });

args.unshift(bin);
// add executable arguments to spawn
args = incrementNodeInspectorPort(process.execArgv).concat(args);
proc = spawn(process.execPath, args, { stdio: 'inherit' });

@@ -625,3 +636,5 @@ }

lastOpt,
index;
index,
short,
opt;

@@ -640,6 +653,13 @@ for (var i = 0, len = args.length; i < len; ++i) {

ret.push(arg);
} else if (arg.length > 1 && arg[0] === '-' && arg[1] !== '-') {
arg.slice(1).split('').forEach(function(c) {
ret.push('-' + c);
});
} else if (arg.length > 2 && arg[0] === '-' && arg[1] !== '-') {
short = arg.slice(0, 2);
opt = this.optionFor(short);
if (opt && (opt.required || opt.optional)) {
ret.push(short);
ret.push(arg.slice(2));
} else {
arg.slice(1).split('').forEach(function(c) {
ret.push('-' + c);
});
}
} else if (/^--/.test(arg) && ~(index = arg.indexOf('='))) {

@@ -762,3 +782,3 @@ ret.push(arg.slice(0, index), arg.slice(index + 1));

this.emit('option:' + option.name(), arg);
// bool
// flag
} else {

@@ -777,3 +797,3 @@ this.emit('option:' + option.name());

// If it isn't, then it'll simply be ignored
if ((i + 1) < argv.length && argv[i + 1][0] !== '-') {
if ((i + 1) < argv.length && (argv[i + 1][0] !== '-' || argv[i + 1] === '-')) {
unknownOptions.push(argv[++i]);

@@ -816,3 +836,3 @@ }

Command.prototype.missingArgument = function(name) {
console.error("error: missing required argument `%s'", name);
console.error("error: missing required argument '%s'", name);
process.exit(1);

@@ -831,5 +851,5 @@ };

if (flag) {
console.error("error: option `%s' argument missing, got `%s'", option.flags, flag);
console.error("error: option '%s' argument missing, got '%s'", option.flags, flag);
} else {
console.error("error: option `%s' argument missing", option.flags);
console.error("error: option '%s' argument missing", option.flags);
}

@@ -848,3 +868,3 @@ process.exit(1);

if (this._allowUnknownOption) return;
console.error("error: unknown option `%s'", flag);
console.error("error: unknown option '%s'", flag);
process.exit(1);

@@ -861,3 +881,3 @@ };

Command.prototype.variadicArgNotLast = function(name) {
console.error("error: variadic arguments must be last `%s'", name);
console.error("error: variadic arguments must be last '%s'", name);
process.exit(1);

@@ -872,4 +892,7 @@ };

*
* You can optionally supply the flags and description to override the defaults.
*
* @param {String} str
* @param {String} [flags]
* @param {String} [description]
* @return {Command} for chaining

@@ -879,7 +902,8 @@ * @api public

Command.prototype.version = function(str, flags) {
Command.prototype.version = function(str, flags, description) {
if (arguments.length === 0) return this._version;
this._version = str;
flags = flags || '-V, --version';
var versionOption = new Option(flags, 'output the version number');
description = description || 'output the version number';
var versionOption = new Option(flags, description);
this._versionOptionName = versionOption.long.substr(2) || 'version';

@@ -1018,4 +1042,5 @@ this.options.push(versionOption);

options.push({
flags: '-h, --help'
flags: this._helpFlags
});
return options.reduce(function(max, option) {

@@ -1076,4 +1101,4 @@ return Math.max(max, option.flags.length);

return pad(option.flags, width) + ' ' + option.description +
((option.bool && option.defaultValue !== undefined) ? ' (default: ' + JSON.stringify(option.defaultValue) + ')' : '');
}).concat([pad('-h, --help', width) + ' ' + 'output usage information'])
((!option.negate && option.defaultValue !== undefined) ? ' (default: ' + JSON.stringify(option.defaultValue) + ')' : '');
}).concat([pad(this._helpFlags, width) + ' ' + this._helpDescription])
.join('\n');

@@ -1136,4 +1161,8 @@ };

}
var parentCmdNames = '';
for (var parentCmd = this.parent; parentCmd; parentCmd = parentCmd.parent) {
parentCmdNames = parentCmd.name() + ' ' + parentCmdNames;
}
var usage = [
'Usage: ' + cmdName + ' ' + this.usage(),
'Usage: ' + parentCmdNames + cmdName + ' ' + this.usage(),
''

@@ -1160,4 +1189,7 @@ ];

/**
* Output help information for this command
* Output help information for this command.
*
* When listener(s) are available for the helpLongFlag
* those callbacks are invoked.
*
* @api public

@@ -1172,9 +1204,37 @@ */

}
process.stdout.write(cb(this.helpInformation()));
this.emit('--help');
const cbOutput = cb(this.helpInformation());
if (typeof cbOutput !== 'string' && !Buffer.isBuffer(cbOutput)) {
throw new Error('outputHelp callback must return a string or a Buffer');
}
process.stdout.write(cbOutput);
this.emit(this._helpLongFlag);
};
/**
* You can pass in flags and a description to override the help
* flags and help description for your command.
*
* @param {String} [flags]
* @param {String} [description]
* @return {Command}
* @api public
*/
Command.prototype.helpOption = function(flags, description) {
this._helpFlags = flags || this._helpFlags;
this._helpDescription = description || this._helpDescription;
var splitFlags = this._helpFlags.split(/[ ,|]+/);
if (splitFlags.length > 1) this._helpShortFlag = splitFlags.shift();
this._helpLongFlag = splitFlags.shift();
return this;
};
/**
* Output help information and exit.
*
* @param {Function} [cb]
* @api public

@@ -1226,4 +1286,5 @@ */

options = options || [];
for (var i = 0; i < options.length; i++) {
if (options[i] === '--help' || options[i] === '-h') {
if (options[i] === cmd._helpLongFlag || options[i] === cmd._helpShortFlag) {
cmd.outputHelp();

@@ -1261,1 +1322,48 @@ process.exit(0);

}
/**
* Scan arguments and increment port number for inspect calls (to avoid conflicts when spawning new command).
*
* @param {string[]} args - array of arguments from node.execArgv
* @returns {string[]}
* @api private
*/
function incrementNodeInspectorPort(args) {
// Testing for these options:
// --inspect[=[host:]port]
// --inspect-brk[=[host:]port]
// --inspect-port=[host:]port
return args.map((arg) => {
var result = arg;
if (arg.indexOf('--inspect') === 0) {
var debugOption;
var debugHost = '127.0.0.1';
var debugPort = '9229';
var match;
if ((match = arg.match(/^(--inspect(-brk)?)$/)) !== null) {
// e.g. --inspect
debugOption = match[1];
} else if ((match = arg.match(/^(--inspect(-brk|-port)?)=([^:]+)$/)) !== null) {
debugOption = match[1];
if (/^\d+$/.test(match[3])) {
// e.g. --inspect=1234
debugPort = match[3];
} else {
// e.g. --inspect=localhost
debugHost = match[3];
}
} else if ((match = arg.match(/^(--inspect(-brk|-port)?)=([^:]+):(\d+)$/)) !== null) {
// e.g. --inspect=localhost:1234
debugOption = match[1];
debugHost = match[3];
debugPort = match[4];
}
if (debugOption && debugPort !== '0') {
result = `${debugOption}=${debugHost}:${parseInt(debugPort) + 1}`;
}
}
return result;
});
}
{
"name": "commander",
"version": "2.20.0",
"version": "3.0.0-0",
"description": "the complete solution for node.js command-line programs",

@@ -29,11 +29,11 @@ "keywords": [

"devDependencies": {
"@types/node": "^10.11.3",
"eslint": "^5.6.1",
"@types/node": "^12.6.2",
"eslint": "^6.0.1",
"should": "^13.2.3",
"sinon": "^6.3.4",
"standard": "^12.0.1",
"ts-node": "^7.0.1",
"typescript": "^2.9.2"
"sinon": "^7.3.2",
"standard": "^13.0.1",
"ts-node": "^8.3.0",
"typescript": "^3.5.3"
},
"typings": "typings/index.d.ts"
}
# Commander.js
[![Build Status](https://api.travis-ci.org/tj/commander.js.svg?branch=master)](http://travis-ci.org/tj/commander.js)

@@ -8,8 +7,5 @@ [![NPM Version](http://img.shields.io/npm/v/commander.svg?style=flat)](https://www.npmjs.org/package/commander)

[![Install Size](https://packagephobia.now.sh/badge?p=commander)](https://packagephobia.now.sh/result?p=commander)
[![Join the chat at https://gitter.im/tj/commander.js](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/tj/commander.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
The complete solution for [node.js](http://nodejs.org) command-line interfaces, inspired by Ruby's [commander](https://github.com/commander-rb/commander).
[API documentation](http://tj.github.com/commander.js/)
The complete solution for [node.js](http://nodejs.org) command-line interfaces, inspired by Ruby's [commander](https://github.com/commander-rb/commander).
## Installation

@@ -19,168 +15,276 @@

## Option parsing
## Declaring _program_ variable
Options with commander are defined with the `.option()` method, also serving as documentation for the options. The example below parses args and options from `process.argv`, leaving remaining args as the `program.args` array which were not consumed by options.
Commander exports a global object which is convenient for quick programs.
This is used in the examples in this README for brevity.
```js
#!/usr/bin/env node
const program = require('commander');
program.version('0.0.1');
```
/**
* Module dependencies.
*/
For larger programs which may use commander in multiple ways, including unit testing, it is better to create a local Command object to use.
var program = require('commander');
```js
const commander = require('commander');
const program = new commander.Command();
program.version('0.0.1');
```
program
.version('0.1.0')
.option('-p, --peppers', 'Add peppers')
.option('-P, --pineapple', 'Add pineapple')
.option('-b, --bbq-sauce', 'Add bbq sauce')
.option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble')
.parse(process.argv);
console.log('you ordered a pizza with:');
if (program.peppers) console.log(' - peppers');
if (program.pineapple) console.log(' - pineapple');
if (program.bbqSauce) console.log(' - bbq');
console.log(' - %s cheese', program.cheese);
```
## Options
Short flags may be passed as a single arg, for example `-abc` is equivalent to `-a -b -c`. Multi-word options such as "--template-engine" are camel-cased, becoming `program.templateEngine` etc.
Options are defined with the `.option()` method, also serving as documentation for the options. Each option can have a short flag (single character) and a long name, separated by a comma or space.
Note that multi-word options starting with `--no` prefix negate the boolean value of the following word. For example, `--no-sauce` sets the value of `program.sauce` to false.
The options can be accessed as properties on the Command object. Multi-word options such as "--template-engine" are camel-cased, becoming `program.templateEngine` etc. Multiple short flags may be combined as a single arg, for example `-abc` is equivalent to `-a -b -c`.
```js
#!/usr/bin/env node
### Common option types, boolean and value
/**
* Module dependencies.
*/
The two most used option types are a boolean flag, and an option which takes a value (declared using angle brackets). Both are `undefined` unless specified on command line.
var program = require('commander');
```js
const program = require('commander');
program
.option('--no-sauce', 'Remove sauce')
.parse(process.argv);
.option('-d, --debug', 'output extra debugging')
.option('-s, --small', 'small pizza size')
.option('-p, --pizza-type <type>', 'flavour of pizza');
console.log('you ordered a pizza');
if (program.sauce) console.log(' with sauce');
else console.log(' without sauce');
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}`);
```
To get string arguments from options you will need to use angle brackets <> for required inputs or square brackets [] for optional inputs.
```bash
$ pizza-options -d
{ debug: true, small: undefined, pizzaType: undefined }
pizza details:
$ pizza-options -p
error: option '-p, --pizza-type <type>' argument missing
$ pizza-options -ds -p vegetarian
{ debug: true, small: true, pizzaType: 'vegetarian' }
pizza details:
- small pizza size
- vegetarian
$ pizza-options --pizza-type=cheese
pizza details:
- cheese
```
e.g. ```.option('-m --myarg [myVar]', 'my super cool description')```
`program.parse(arguments)` processes the arguments, leaving any args not consumed by the options as the `program.args` array.
Then to access the input if it was passed in.
### Default option value
e.g. ```var myInput = program.myarg```
You can specify a default value for an option which takes a value.
**NOTE**: If you pass a argument without using brackets the example above will return true and not the value passed in.
```js
const program = require('commander');
program
.option('-c, --cheese <type>', 'add the specified type of cheese', 'blue');
## Version option
program.parse(process.argv);
Calling the `version` implicitly adds the `-V` and `--version` options to the command.
When either of these options is present, the command prints the version number and exits.
console.log(`cheese: ${program.cheese}`);
```
$ ./examples/pizza -V
0.0.1
```bash
$ pizza-options
cheese: blue
$ pizza-options --cheese stilton
cheese: stilton
```
If you want your program to respond to the `-v` option instead of the `-V` option, simply pass custom flags to the `version` method using the same syntax as the `option` method.
### Other option types, negatable boolean and flag|value
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.
If you define `--foo` first, adding `--no-foo` does not change the default value from what it would
otherwise be. You can specify a default boolean value for a boolean flag and it can be overridden on command line.
```js
const program = require('commander');
program
.version('0.0.1', '-v, --version')
.option('--no-sauce', 'Remove sauce')
.option('--cheese <flavour>', 'cheese flavour', 'mozzarella')
.option('--no-cheese', 'plain with no cheese')
.parse(process.argv);
const sauceStr = program.sauce ? 'sauce' : 'no sauce';
const cheeseStr = (program.cheese === false) ? 'no cheese' : `${program.cheese} cheese`;
console.log(`You ordered a pizza with ${sauceStr} and ${cheeseStr}`);
```
The version flags can be named anything, but the long option is required.
```bash
$ pizza-options
You ordered a pizza with sauce and mozzarella cheese
$ pizza-options --sauce
error: unknown option '--sauce'
$ pizza-options --cheese=blue
You ordered a pizza with sauce and blue cheese
$ pizza-options --no-sauce --no-cheese
You ordered a pizza with no sauce and no cheese
```
## Command-specific options
You can specify an option which functions as a flag but may also take a value (declared using square brackets).
You can attach options to a command.
```js
#!/usr/bin/env node
const program = require('commander');
var program = require('commander');
program
.command('rm <dir>')
.option('-r, --recursive', 'Remove recursively')
.action(function (dir, cmd) {
console.log('remove ' + dir + (cmd.recursive ? ' recursively' : ''))
})
.option('-c, --cheese [type]', 'Add cheese with optional type');
program.parse(process.argv)
program.parse(process.argv);
if (program.cheese === undefined) console.log('no cheese');
else if (program.cheese === true) console.log('add cheese');
else console.log(`add cheese type ${program.cheese}`);
```
A command's options are validated when the command is used. Any unknown options will be reported as an error. However, if an action-based command does not define an action, then the options are not validated.
```bash
$ pizza-options
no cheese
$ pizza-options --cheese
add cheese
$ pizza-options --cheese mozzarella
add cheese type mozzarella
```
## Coercion
### Custom option processing
You may specify a function to do custom processing of option values. The callback function receives two parameters, the user specified value and the
previous value for the option. It returns the new value for the option.
This allows you to coerce the option value to the desired type, or accumulate values, or do entirely custom processing.
You can optionally specify the default/starting value for the option after the function.
```js
function range(val) {
return val.split('..').map(Number);
const program = require('commander');
function myParseInt(value, dummyPrevious) {
// parseInt takes a string and an optional radix
return parseInt(value);
}
function list(val) {
return val.split(',');
function increaseVerbosity(dummyValue, previous) {
return previous + 1;
}
function collect(val, memo) {
memo.push(val);
return memo;
function collect(value, previous) {
return previous.concat([value]);
}
function increaseVerbosity(v, total) {
return total + 1;
function commaSeparatedList(value, dummyPrevious) {
return value.split(',');
}
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);
.option('-f, --float <number>', 'float argument', parseFloat)
.option('-i, --integer <number>', 'integer argument', myParseInt)
.option('-v, --verbose', 'verbosity that can be increased', increaseVerbosity, 0)
.option('-c, --collect <value>', 'repeatable value', collect, [])
.option('-l, --list <items>', 'comma separated list', commaSeparatedList)
;
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);
program.parse(process.argv);
if (program.float !== undefined) console.log(`float: ${program.float}`);
if (program.integer !== undefined) console.log(`integer: ${program.integer}`);
if (program.verbose > 0) console.log(`verbosity: ${program.verbose}`);
if (program.collect.length > 0) console.log(program.collect);
if (program.list !== undefined) console.log(program.list);
```
## Regular Expression
```bash
$ custom -f 1e2
float: 100
$ custom --integer 2
integer: 2
$ custom -v -v -v
verbose: 3
$ custom -c a -c b -c c
[ 'a', 'b', 'c' ]
$ custom --list x,y,z
[ 'x', 'y', 'z' ]
```
### Version option
The optional `version` method adds handling for displaying the command version. The default option flags are `-V` and `--version`, and when present the command prints the version number and exits.
```js
program.version('0.0.1');
```
```bash
$ ./examples/pizza -V
0.0.1
```
You may change the flags and description by passing additional parameters to the `version` method, using
the same syntax for flags as the `option` method. The version flags can be named anything, but a long name is required.
```js
program.version('0.0.1', '-v, --vers', 'output the current version');
```
## Commands
You can specify (sub)commands for your top-level command using `.command`. There are two ways these can be implemented: using an action handler attached to the command, or as a separate executable file (described in more detail later). In the first parameter to `.command` you specify the command name and any command arguments. The arguments may be `<required>` or `[optional]`, and the last argument may also be `variadic...`.
For example:
```js
// Command implemented using action handler (description is supplied separately to `.command`)
// Returns new command for configuring.
program
.version('0.1.0')
.option('-s --size <size>', 'Pizza size', /^(large|medium|small)$/i, 'medium')
.option('-d --drink [drink]', 'Drink', /^(coke|pepsi|izze)$/i)
.parse(process.argv);
.command('clone <source> [destination]')
.description('clone a repository into a newly created directory')
.action((source, destination) => {
console.log('clone command called');
});
console.log(' size: %j', program.size);
console.log(' drink: %j', program.drink);
// Command implemented using separate executable file (description is second parameter to `.command`)
// Returns top-level command for adding more commands.
program
.command('start <service>', 'start named service')
.command('stop [service]', 'stop named service, or all if no name supplied');
```
## Variadic arguments
### Specify the argument syntax
The last argument of a command can be variadic, and only the last argument. To make an argument variadic you have to
append `...` to the argument name. Here is an example:
You use `.arguments` to specify the arguments for the top-level command, and for subcommands they are included in the `.command` call. Angled brackets (e.g. `<required>`) indicate required input. Square brackets (e.g. `[optional]`) indicate optional input.
```js
#!/usr/bin/env node
var program = require('commander');
/**
* Module dependencies.
*/
program
.version('0.1.0')
.arguments('<cmd> [env]')
.action(function (cmd, env) {
cmdValue = cmd;
envValue = env;
});
program.parse(process.argv);
if (typeof cmdValue === 'undefined') {
console.error('no command given!');
process.exit(1);
}
console.log('command:', cmdValue);
console.log('environment:', envValue || "no environment given");
```
The last argument of a command can be variadic, and only the last argument. To make an argument variadic you
append `...` to the argument name. For example:
```js
var program = require('commander');

@@ -203,33 +307,35 @@

An `Array` is used for the value of a variadic argument. This applies to `program.args` as well as the argument passed
to your action as demonstrated above.
The variadic argument is passed to the action handler as an array. (And this also applies to `program.args`.)
## Specify the argument syntax
### Action handler (sub)commands
You can add options to a command that uses an action handler.
The action handler gets passed a parameter for each argument you declared, and one additional argument which is the
command object itself. This command argument has the values for the command-specific options added as properties.
```js
#!/usr/bin/env node
var program = require('commander');
program
.version('0.1.0')
.arguments('<cmd> [env]')
.action(function (cmd, env) {
cmdValue = cmd;
envValue = env;
});
.command('rm <dir>')
.option('-r, --recursive', 'Remove recursively')
.action(function (dir, cmdObj) {
console.log('remove ' + dir + (cmdObj.recursive ? ' recursively' : ''))
})
program.parse(process.argv);
if (typeof cmdValue === 'undefined') {
console.error('no command given!');
process.exit(1);
}
console.log('command:', cmdValue);
console.log('environment:', envValue || "no environment given");
program.parse(process.argv)
```
Angled brackets (e.g. `<cmd>`) indicate required input. Square brackets (e.g. `[env]`) indicate optional input.
## Git-style sub-commands
A command's options on the command line are validated when the command is used. Any unknown options will be reported as an error. However, if an action-based command does not define an action, then the options are not validated.
Configuration options can be passed with the call to `.command()`. Specifying `true` for `opts.noHelp` will remove the command from the generated help output.
### Git-style executable (sub)commands
When `.command()` is invoked with a description argument, this tells commander that you're going to use separate executables for sub-commands, much like `git(1)` and other popular tools.
Commander will search the executables in the directory of the entry script (like `./examples/pm`) with the name `program-subcommand`, like `pm-install`, `pm-search`.
You can specify a custom name with the `executableFile` configuration option.
You handle the options for an executable (sub)command in the executable, and don't declare them at the top-level.
```js

@@ -243,2 +349,3 @@ // file: ./examples/pm

.command('search [query]', 'search with optional query')
.command('update', 'update installed packages', {executableFile: 'myUpdateSubCommand'})
.command('list', 'list packages installed', {isDefault: true})

@@ -248,15 +355,7 @@ .parse(process.argv);

When `.command()` is invoked with a description argument, no `.action(callback)` should be called to handle sub-commands, otherwise there will be an error. This tells commander that you're going to use separate executables for sub-commands, much like `git(1)` and other popular tools.
The commander will try to search the executables in the directory of the entry script (like `./examples/pm`) with the name `program-command`, like `pm-install`, `pm-search`.
Configuration options can be passed with the call to `.command()`. Specifying `true` for `opts.noHelp` will remove the command from the generated help output. Specifying `true` for `opts.isDefault` will run the subcommand if no other subcommand is specified.
Specifying a name with `executableFile` will override the default constructed name.
Options can be passed with the call to `.command()`. Specifying `true` for `opts.noHelp` will remove the subcommand from the generated help output. Specifying `true` for `opts.isDefault` will run the subcommand if no other subcommand is specified.
If the program is designed to be installed globally, make sure the executables have proper modes, like `755`.
### `--harmony`
You can enable `--harmony` option in two ways:
* Use `#! /usr/bin/env node --harmony` in the sub-commands scripts. Note some os version don’t support this pattern.
* Use the `--harmony` option when call the command, like `node --harmony examples/pm publish`. The `--harmony` option will be preserved when spawning sub-command process.
## Automated --help

@@ -273,3 +372,2 @@

Options:
-h, --help output usage information
-V, --version output the version number

@@ -279,4 +377,5 @@ -p, --peppers Add peppers

-b, --bbq Add bbq sauce
-c, --cheese <type> Add the specified type of cheese [marble]
-c, --cheese <type> Add the specified type of cheese (default: "marble")
-C, --no-cheese You do not want any cheese
-h, --help output usage information
```

@@ -365,2 +464,11 @@

## .helpOption(flags, description)
Override the default help flags and description.
```js
program
.helpOption('-e, --HELP', 'read more information');
```
## .help(cb)

@@ -387,2 +495,30 @@

## Bits and pieces
### TypeScript
The Commander package includes its TypeScript Definition file, but also requires the node types which you need to install yourself. e.g.
```bash
npm install commander
npm install --save-dev @types/node
```
If you use `ts-node` and git-style sub-commands written as `.ts` files, you need to call your program through node to get the sub-commands called correctly. e.g.
```bash
node -r ts-node/register pm.ts
```
### Node options such as `--harmony`
You can enable `--harmony` option in two ways:
* Use `#! /usr/bin/env node --harmony` in the sub-commands scripts. (Note Windows does not support this pattern.)
* Use the `--harmony` option when call the command, like `node --harmony examples/pm publish`. The `--harmony` option will be preserved when spawning sub-command process.
### Node debugging
If you are using the node inspector for [debugging](https://nodejs.org/en/docs/guides/debugging-getting-started/) git-style executable (sub)commands using `node -inspect` et al,
the inspector port is incremented by 1 for the spawned subcommand.
## Examples

@@ -389,0 +525,0 @@

@@ -6,2 +6,4 @@ // Type definitions for commander 2.11

///<reference types="node" />
declare namespace local {

@@ -40,73 +42,52 @@

/**
* Set the program version to `str`.
* Set the program version to `str`.
*
* This method auto-registers the "-V, --version" flag
* which will print the version number when passed.
*
* You can optionally supply the flags and description to override the defaults.
*
* @param {string} str
* @param {string} [flags]
* @returns {Command} for chaining
*/
version(str: string, flags?: string): Command;
version(str: string, flags?: string, description?: string): Command;
/**
* Add command `name`.
*
* The `.action()` callback is invoked when the
* command `name` is specified via __ARGV__,
* and the remaining arguments are applied to the
* function for access.
*
* When the `name` is "*" an un-matched command
* will be passed as the first arg, followed by
* the rest of __ARGV__ remaining.
*
* Define a command, implemented using an action handler.
*
* @remarks
* The command description is supplied using `.description`, not as a parameter to `.command`.
*
* @example
* program
* .version('0.0.1')
* .option('-C, --chdir <path>', 'change the working directory')
* .option('-c, --config <path>', 'set config path. defaults to ./deploy.conf')
* .option('-T, --no-tests', 'ignore test hook')
*
* program
* .command('setup')
* .description('run remote setup commands')
* .action(function() {
* console.log('setup');
* });
*
* program
* .command('exec <cmd>')
* .description('run the given remote command')
* .action(function(cmd) {
* console.log('exec "%s"', cmd);
* });
*
* program
* .command('teardown <dir> [otherDirs...]')
* .description('run teardown commands')
* .action(function(dir, otherDirs) {
* console.log('dir "%s"', dir);
* if (otherDirs) {
* otherDirs.forEach(function (oDir) {
* console.log('dir "%s"', oDir);
* });
* }
* });
*
* program
* .command('*')
* .description('deploy the given env')
* .action(function(env) {
* console.log('deploying "%s"', env);
* });
*
* program.parse(process.argv);
*
* @param {string} name
* @param {string} [desc] for git-style sub-commands
* @param {CommandOptions} [opts] command options
* @returns {Command} the new command
* ```ts
* program
* .command('clone <source> [destination]')
* .description('clone a repository into a newly created directory')
* .action((source, destination) => {
* console.log('clone command called');
* });
* ```
*
* @param nameAndArgs - command name and arguments, args are `<required>` or `[optional]` and last may also be `variadic...`
* @param opts - configuration options
* @returns new command
*/
command(name: string, desc?: string, opts?: commander.CommandOptions): Command;
command(nameAndArgs: string, opts?: commander.CommandOptions): Command;
/**
* Define a command, implemented in a separate executable file.
*
* @remarks
* The command description is supplied as the second parameter to `.command`.
*
* @example
* ```ts
* program
* .command('start <service>', 'start named service')
* .command('stop [service]', 'stop named serice, or all if no name supplied');
* ```
*
* @param nameAndArgs - command name and arguments, args are `<required>` or `[optional]` and last may also be `variadic...`
* @param description - description of executable command
* @param opts - configuration options
* @returns top level command for chaining more command definitions
*/
command(nameAndArgs: string, description: string, opts?: commander.CommandOptions): Command;

@@ -273,2 +254,5 @@ /**

*
* When listener(s) are available for the helpLongFlag
* those callbacks are invoked.
*
* @param {(str: string) => string} [cb]

@@ -278,6 +262,11 @@ */

/** Output help information and exit.
*
* @param {(str: string) => string} [cb]
/**
* You can pass in flags and a description to override the help
* flags and help description for your command.
*/
helpOption(flags?: string, description?: string): Command;
/**
* Output help information and exit.
*/
help(cb?: (str: string) => string): never;

@@ -284,0 +273,0 @@ }

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc