Socket
Socket
Sign inDemoInstall

commander

Package Overview
Dependencies
Maintainers
6
Versions
115
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

commander - npm Package Compare versions

Comparing version 5.1.0 to 6.0.0-0

11

CHANGELOG.md

@@ -10,2 +10,10 @@ # Changelog

## [6.0.0-0] (2020-06-20)
### Added
- add support for variadic options ([#1250])
- allow options to be added with just a short flag ([#1256])
- throw an error if there might be a clash between option name and a Command property, with advice on how to resolve ([#1275])
## [5.1.0] (2020-04-25)

@@ -368,2 +376,5 @@

[#1248]: https://github.com/tj/commander.js/pull/1248
[#1250]: https://github.com/tj/commander.js/pull/1250
[#1256]: https://github.com/tj/commander.js/pull/1256
[#1275]: https://github.com/tj/commander.js/pull/1275

@@ -370,0 +381,0 @@ [Unreleased]: https://github.com/tj/commander.js/compare/master...develop

188

index.js

@@ -23,9 +23,14 @@ /**

this.flags = flags;
this.required = flags.indexOf('<') >= 0; // A value must be supplied when the option is specified.
this.optional = flags.indexOf('[') >= 0; // A value is optional when the option is specified.
this.required = flags.includes('<'); // A value must be supplied when the option is specified.
this.optional = flags.includes('['); // A value is optional when the option is specified.
// variadic test ignores <value,...> et al which might be used to describe custom splitting of single argument
this.variadic = /\w\.\.\.[>\]]$/.test(flags); // The option can take multiple values.
this.mandatory = false; // The option must have a value after parsing, which usually means it must be specified on command line.
this.negate = flags.indexOf('-no-') !== -1;
const flagParts = flags.split(/[ ,|]+/);
if (flagParts.length > 1 && !/^[[<]/.test(flagParts[1])) this.short = flagParts.shift();
this.long = flagParts.shift();
const optionFlags = _parseOptionFlags(flags);
this.short = optionFlags.shortFlag;
this.long = optionFlags.longFlag;
this.negate = false;
if (this.long) {
this.negate = this.long.startsWith('--no-');
}
this.description = description || '';

@@ -43,3 +48,6 @@ this.defaultValue = undefined;

name() {
return this.long.replace(/^--/, '');
if (this.long) {
return this.long.replace(/^--/, '');
}
return this.short.replace(/^-/, '');
};

@@ -115,2 +123,3 @@

this._storeOptionsAsProperties = true; // backwards compatible by default
this._storeOptionsAsPropertiesCalled = false;
this._passCommandToAction = true; // backwards compatible by default

@@ -266,3 +275,3 @@ this._actionResults = [];

* addHelpCommand(false); // force off
* addHelpCommand('help [cmd]', 'display help for [cmd]'); // force on with custom detais
* addHelpCommand('help [cmd]', 'display help for [cmd]'); // force on with custom details
*

@@ -430,2 +439,43 @@ * @return {Command} `this` command for chaining

/**
* Internal routine to check whether there is a clash storing option value with a Command property.
*
* @param {Option} option
* @api private
*/
_checkForOptionNameClash(option) {
if (!this._storeOptionsAsProperties || this._storeOptionsAsPropertiesCalled) {
// Storing options safely, or user has been explicit and up to them.
return;
}
// User may override help, and hard to tell if worth warning.
if (option.name() === 'help') {
return;
}
const commandProperty = this._getOptionValue(option.attributeName());
if (commandProperty === undefined) {
// no clash
return;
}
let foundClash = true;
if (option.negate) {
// It is ok if define foo before --no-foo.
const positiveLongFlag = option.long.replace(/^--no-/, '--');
foundClash = !this._findOption(positiveLongFlag);
} else if (option.long) {
const negativeLongFlag = option.long.replace(/^--/, '--no-');
foundClash = !this._findOption(negativeLongFlag);
}
if (foundClash) {
throw new Error(`option '${option.name()}' clashes with existing property '${option.attributeName()}' on Command
- call storeOptionsAsProperties(false) to store option values safely,
- or call storeOptionsAsProperties(true) to suppress this check,
- or change option name`);
}
};
/**
* Internal implementation shared by .option() and .requiredOption()

@@ -436,3 +486,3 @@ *

* @param {string} description
* @param {Function|*} [fn] - custom option processing function or default vaue
* @param {Function|*} [fn] - custom option processing function or default value
* @param {*} [defaultValue]

@@ -449,2 +499,4 @@ * @return {Command} `this` command for chaining

this._checkForOptionNameClash(option);
// default as 3rd arg

@@ -486,9 +538,17 @@ if (typeof fn !== 'function') {

this.on('option:' + oname, (val) => {
// coercion
const oldValue = this._getOptionValue(name);
// custom processing
if (val !== null && fn) {
val = fn(val, this._getOptionValue(name) === undefined ? defaultValue : this._getOptionValue(name));
val = fn(val, oldValue === undefined ? defaultValue : oldValue);
} else if (val !== null && option.variadic) {
if (oldValue === defaultValue || !Array.isArray(oldValue)) {
val = [val];
} else {
val = oldValue.concat(val);
}
}
// unassigned or boolean value
if (typeof this._getOptionValue(name) === 'boolean' || typeof this._getOptionValue(name) === 'undefined') {
if (typeof oldValue === 'boolean' || typeof oldValue === 'undefined') {
// if no value, negate false, and we have a default, then use it!

@@ -557,3 +617,3 @@ if (val == null) {

* @param {string} description
* @param {Function|*} [fn] - custom option processing function or default vaue
* @param {Function|*} [fn] - custom option processing function or default value
* @param {*} [defaultValue]

@@ -568,3 +628,3 @@ * @return {Command} `this` command for chaining

/*
/**
* Add a required option which must have a value after parsing. This usually means

@@ -577,3 +637,3 @@ * the option must be specified on the command line. (Otherwise the same as .option().)

* @param {string} description
* @param {Function|*} [fn] - custom option processing function or default vaue
* @param {Function|*} [fn] - custom option processing function or default value
* @param {*} [defaultValue]

@@ -610,2 +670,3 @@ * @return {Command} `this` command for chaining

storeOptionsAsProperties(value) {
this._storeOptionsAsPropertiesCalled = true;
this._storeOptionsAsProperties = (value === undefined) || value;

@@ -906,3 +967,3 @@ if (this.options.length) {

if (this.commands.length && this.args.length === 0 && !this._actionHandler && !this._defaultCommandName) {
// probaby missing subcommand and no handler, user needs help
// probably missing subcommand and no handler, user needs help
this._helpAndError();

@@ -1014,2 +1075,3 @@ }

// parse options
let activeVariadicOption = null;
while (args.length) {

@@ -1025,2 +1087,8 @@ const arg = args.shift();

if (activeVariadicOption && !maybeOption(arg)) {
this.emit(`option:${activeVariadicOption.name()}`, arg);
continue;
}
activeVariadicOption = null;
if (maybeOption(arg)) {

@@ -1044,2 +1112,3 @@ const option = this._findOption(arg);

}
activeVariadicOption = option.variadic ? option : null;
continue;

@@ -1206,5 +1275,5 @@ }

const versionOption = new Option(flags, description);
this._versionOptionName = versionOption.long.substr(2) || 'version';
this._versionOptionName = versionOption.attributeName();
this.options.push(versionOption);
this.on('option:' + this._versionOptionName, () => {
this.on('option:' + versionOption.name(), () => {
process.stdout.write(str + '\n');

@@ -1572,9 +1641,6 @@ this._exit(0, 'commander.version', str);

const splitFlags = this._helpFlags.split(/[ ,|]+/);
const helpFlags = _parseOptionFlags(this._helpFlags);
this._helpShortFlag = helpFlags.shortFlag;
this._helpLongFlag = helpFlags.longFlag;
this._helpShortFlag = undefined;
if (splitFlags.length > 1) this._helpShortFlag = splitFlags.shift();
this._helpLongFlag = splitFlags.shift();
return this;

@@ -1730,2 +1796,24 @@ };

/**
* Parse the short and long flag out of something like '-m,--mixed <value>'
*
* @api private
*/
function _parseOptionFlags(flags) {
let shortFlag;
let longFlag;
// Use original very loose parsing to maintain backwards compatibility for now,
// which allowed for example unintended `-sw, --short-word` [sic].
const flagParts = flags.split(/[ |,]+/);
if (flagParts.length > 1 && !/^[[<]/.test(flagParts[1])) shortFlag = flagParts.shift();
longFlag = flagParts.shift();
// Add support for lone short flag without significantly changing parsing!
if (!shortFlag && /^-[^-]$/.test(longFlag)) {
shortFlag = longFlag;
longFlag = undefined;
}
return { shortFlag, longFlag };
}
/**
* Scan arguments and increment port number for inspect calls (to avoid conflicts when spawning new command).

@@ -1744,33 +1832,33 @@ *

return args.map((arg) => {
let result = arg;
if (arg.indexOf('--inspect') === 0) {
let debugOption;
let debugHost = '127.0.0.1';
let debugPort = '9229';
let 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];
if (!arg.startsWith('--inspect')) {
return arg;
}
let debugOption;
let debugHost = '127.0.0.1';
let debugPort = '9229';
let 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];
debugPort = match[4];
}
} 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}`;
}
if (debugOption && debugPort !== '0') {
return `${debugOption}=${debugHost}:${parseInt(debugPort) + 1}`;
}
return result;
return arg;
});
}
{
"name": "commander",
"version": "5.1.0",
"version": "6.0.0-0",
"description": "the complete solution for node.js command-line programs",

@@ -35,8 +35,8 @@ "keywords": [

"@types/jest": "^25.2.1",
"@types/node": "^12.12.36",
"@typescript-eslint/eslint-plugin": "^2.29.0",
"@types/node": "^12.12.38",
"@typescript-eslint/eslint-plugin": "^2.31.0",
"eslint": "^6.8.0",
"eslint-config-standard-with-typescript": "^15.0.1",
"eslint-plugin-jest": "^23.8.2",
"jest": "^25.4.0",
"eslint-config-standard-with-typescript": "^16.0.0",
"eslint-plugin-jest": "^23.10.0",
"jest": "^26.0.1",
"standard": "^14.3.3",

@@ -43,0 +43,0 @@ "typescript": "^3.7.5"

@@ -21,2 +21,3 @@ # Commander.js

- [Required option](#required-option)
- [Variadic option](#variadic-option)
- [Version option](#version-option)

@@ -45,3 +46,2 @@ - [Commands](#commands)

- [Examples](#examples)
- [License](#license)
- [Support](#support)

@@ -68,7 +68,7 @@ - [Commander for enterprise](#commander-for-enterprise)

```js
const { Command } = require('commander');
const program = new Command();
program.version('0.0.1');
```
```js
const { Command } = require('commander');
const program = new Command();
program.version('0.0.1');
```

@@ -94,5 +94,5 @@ ## Options

Example file: [options-common.js](./examples/options-common.js)
```js
const { program } = require('commander');
program

@@ -133,5 +133,5 @@ .option('-d, --debug', 'output extra debugging')

Example file: [options-defaults.js](./examples/options-defaults.js)
```js
const { program } = require('commander');
program

@@ -160,5 +160,5 @@ .option('-c, --cheese <type>', 'add the specified type of cheese', 'blue');

Example file: [options-negatable.js](./examples/options-negatable.js)
```js
const { program } = require('commander');
program

@@ -188,5 +188,5 @@ .option('--no-sauce', 'Remove sauce')

Example file: [options-flag-or-value.js](./examples/options-flag-or-value.js)
```js
const { program } = require('commander');
program

@@ -220,5 +220,5 @@ .option('-c, --cheese [type]', 'Add cheese with optional type');

Example file: [options-custom-processing.js](./examples/options-custom-processing.js)
```js
const { program } = require('commander');
function myParseInt(value, dummyPrevious) {

@@ -275,5 +275,5 @@ // parseInt takes a string and an optional radix

Example file: [options-required.js](./examples/options-required.js)
```js
const { program } = require('commander');
program

@@ -290,2 +290,34 @@ .requiredOption('-c, --cheese <type>', 'pizza must have cheese');

### Variadic option
You may make an option variadic by appending `...` to the value placeholder when declaring the option. On the command line you
can then specify multiple option arguments, and the parsed option value will be an array. The extra arguments
are read until the first argument starting with a dash. The special argument `--` stops option processing entirely. If a value
is specified in the same argument as the option then no further values are read.
Example file: [options-variadic.js](./examples/options-variadic.js)
```js
program
.option('-n, --number <numbers...>', 'specify numbers')
.option('-l, --letter [letters...]', 'specify letters');
program.parse();
console.log('Options: ', program.opts());
console.log('Remaining arguments: ', program.args);
```
```bash
$ collect -n 1 2 3 --letter a b c
Options: { number: [ '1', '2', '3' ], letter: [ 'a', 'b', 'c' ] }
Remaining arguments: []
$ collect --letter=A -n80 operand
Options: { number: [ '80' ], letter: [ 'A' ] }
Remaining arguments: [ 'operand' ]
$ collect --letter -n 1 -n 2 3 -- operand
Options: { number: [ '1', '2', '3' ], letter: true }
Remaining arguments: [ 'operand' ]
```
### Version option

@@ -305,3 +337,3 @@

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.
the same syntax for flags as the `option` method.

@@ -350,5 +382,5 @@ ```js

Example file: [env](./examples/env)
```js
const { program } = require('commander');
program

@@ -437,6 +469,5 @@ .version('0.1.0')

Example file: [pm](./examples/pm)
```js
// file: ./examples/pm
const { program } = require('commander');
program

@@ -446,5 +477,6 @@ .version('0.1.0')

.command('search [query]', 'search with optional query')
.command('update', 'update installed packages', {executableFile: 'myUpdateSubCommand'})
.command('list', 'list packages installed', {isDefault: true})
.parse(process.argv);
.command('update', 'update installed packages', { executableFile: 'myUpdateSubCommand' })
.command('list', 'list packages installed', { isDefault: true });
program.parse(process.argv);
```

@@ -457,4 +489,6 @@

The help information is auto-generated based on the information commander already knows about your program. The default
help option is `-h,--help`. ([example](./examples/pizza))
help option is `-h,--help`.
Example file: [pizza](./examples/pizza)
```bash

@@ -487,4 +521,6 @@ $ node ./examples/pizza --help

You can display extra information by listening for "--help". ([example](./examples/custom-help))
You can display extra information by listening for "--help".
Example file: [custom-help](./examples/custom-help)
```js

@@ -616,3 +652,3 @@ program

([example](./examples/storeOptionsAsProperties-action.js))
Example file: [storeOptionsAsProperties-action.js](./examples/storeOptionsAsProperties-action.js)

@@ -688,3 +724,3 @@ ```js

``` js
```js
program.exitOverride();

@@ -701,2 +737,4 @@

Example file: [deploy](./examples/deploy)
```js

@@ -741,6 +779,2 @@ const { program } = require('commander');

## License
[MIT](https://github.com/tj/commander.js/blob/master/LICENSE)
## Support

@@ -747,0 +781,0 @@

@@ -78,3 +78,3 @@ // Type definitions for commander

* .command('start <service>', 'start named service')
* .command('stop [service]', 'stop named serice, or all if no name supplied');
* .command('stop [service]', 'stop named service, or all if no name supplied');
* ```

@@ -81,0 +81,0 @@ *

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc