Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

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 7.0.0-1 to 7.0.0-2

122

CHANGELOG.md

@@ -11,2 +11,116 @@ # Changelog

## [7.0.0-2] (2020-12-14)
### Changed
- *Breaking:* options are stored safely by default, not as properties on the command
- this especially affects accessing options on program, use `program.opts()`
- revert behaviour with `.storeOptionsAsProperties()`
- *Breaking:* action handlers are passed options and command separately
### Added
- *Breaking:* error message if there are too many command-arguments on command line for the action handler
- if should be allowed then declare extra arguments, or use `.allowExcessArguments()`
### Deleted
- *Breaking:* `.passCommandToAction()`
- no longer needed as action handler is passed options and command
- *Breaking:* "extra arguments" parameter to action handler
- if being used to detect excess arguments, there is now an error displayed by default
### Migration Tips
The biggest change is the parsed option values. Previously the options were stored by default as properties on the command object, and now the options are stored separately.
If you wish to restore the old behaviour and get running quickly you can call `.storeOptionsAsProperties()`.
To allow you to move to the new code patterns incrementally, the action handler will be passed the command _twice_,
to match the new "options" and "command" parameters (see below).
**program options**
Use the `.opts()` method to access the options. This is available on any command but is used most with the program.
```js
program.option('-d, --debug');
program.parse();
// Old code before Commander 7
if (program.debug) console.log(`Program name is ${program.name()}`);
```
```js
// New code
const options = program.opts();
if (options.debug) console.log(`Program name is ${program.name()}`);
```
**action handler**
The action handler gets passed a parameter for each command-argument you declared. Previously by default the next parameter was the command object with the options as properties. Now the next two parameters are instead the options and the command. If you
only accessed the options there may be no code changes required.
```js
program
.command('compress <filename>')
.option('-t, --trace')
// Old code before Commander 7
.action((filename, cmd)) => {
if (cmd.trace) console.log(`Command name is ${cmd.name()}`);
});
```
```js
// New code
.action((filename, options, command)) => {
if (options.trace) console.log(`Command name is ${command.name()}`);
});
```
If you already set `.storeOptionsAsProperties(false)` you may still need to adjust your code.
```js
program
.command('compress <filename>')
.storeOptionsAsProperties(false)
.option('-t, --trace')
// Old code before Commander 7
.action((filename, command)) => {
if (command.opts().trace) console.log(`Command name is ${command.name()}`);
});
```
```js
// New code
.action((filename, options, command)) => {
if (command.opts().trace) console.log(`Command name is ${command.name()}`);
});
```
**excess command-arguments**
There is now an error if there are too many command-arguments on the command line (only checked if there is an action handler).
If the extra arguments are supported by your command then you can either declare the expected arguments, or allow excess arguments.
```js
// Old code before Commander 7
program
.action(() => {});
program.parse(['a', 'b', 'c'], { from: 'user' }); // now causes an error
```
```js
// New code, declare arguments
program
.arguments('[args...]')
.action(() => {});
```
```js
// New code, allow excess arguments
program
.allowExcessArguments()
.action(() => {});
```
## [7.0.0-1] (2020-11-21)

@@ -55,3 +169,8 @@

- initialise the command description to empty string (previously undefined) ([#1365])
## [6.2.1] (2020-12-13)
### Fixed
- some tests failed if directory path included a space ([1390])
## [6.2.0] (2020-10-25)

@@ -289,6 +408,9 @@

[#1387]: https://github.com/tj/commander.js/pull/1387
[#1390]: https://github.com/tj/commander.js/pull/1390
[Unreleased]: https://github.com/tj/commander.js/compare/master...develop
[7.0.0-1]: https://github.com/tj/commander.js/compare/v7.0.0-1...v7.0.0-2
[7.0.0-1]: https://github.com/tj/commander.js/compare/v7.0.0-0...v7.0.0-1
[7.0.0-0]: https://github.com/tj/commander.js/compare/v6.2.0...v7.0.0-0
[6.2.1]: https://github.com/tj/commander.js/compare/v6.2.0..v6.2.1
[6.2.0]: https://github.com/tj/commander.js/compare/v6.1.0..v6.2.0

@@ -295,0 +417,0 @@ [6.1.0]: https://github.com/tj/commander.js/compare/v6.0.0..v6.1.0

25

package.json
{
"name": "commander",
"version": "7.0.0-1",
"version": "7.0.0-2",
"description": "the complete solution for node.js command-line programs",

@@ -36,11 +36,16 @@ "keywords": [

"devDependencies": {
"@types/jest": "^26.0.15",
"@types/node": "^14.14.2",
"@typescript-eslint/eslint-plugin": "^4.5.0",
"eslint": "^7.11.0",
"@types/jest": "^26.0.16",
"@types/node": "^14.14.10",
"@typescript-eslint/eslint-plugin": "^4.9.0",
"eslint": "^7.15.0",
"eslint-config-standard": "^16.0.2",
"eslint-config-standard-with-typescript": "^19.0.1",
"eslint-plugin-jest": "^24.1.0",
"jest": "^26.6.0",
"standard": "^15.0.0",
"typescript": "^4.0.3"
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-jest": "^24.1.3",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.1.0",
"jest": "^26.6.3",
"standard": "^16.0.3",
"typescript": "^4.1.2"
},

@@ -52,4 +57,4 @@ "typings": "typings/index.d.ts",

"engines": {
"node": ">= 6"
"node": ">= 10"
}
}

219

Readme.md

@@ -26,3 +26,3 @@ # Commander.js

- [Specify the argument syntax](#specify-the-argument-syntax)
- [Action handler (sub)commands](#action-handler-subcommands)
- [Action handler](#action-handler)
- [Stand-alone executable (sub)commands](#stand-alone-executable-subcommands)

@@ -39,3 +39,3 @@ - [Automated help](#automated-help)

- [.parse() and .parseAsync()](#parse-and-parseasync)
- [Avoiding option name clashes](#avoiding-option-name-clashes)
- [Legacy options as properties](#legacy-options-as-properties)
- [TypeScript](#typescript)

@@ -82,3 +82,3 @@ - [createCommand()](#createcommand)

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. See also optional new behaviour to [avoid name clashes](#avoiding-option-name-clashes).
The parsed options can be accessed by calling `.opts()` on a `Command` object, and are passed to the action handler. Multi-word options such as "--template-engine" are camel-cased, becoming `program.opts().templateEngine` etc.

@@ -107,6 +107,7 @@ Multiple short flags may optionally be combined in a single argument following the dash: boolean flags, followed by a single option taking a value (possibly followed by the value).

if (program.debug) console.log(program.opts());
const options = program.opts();
if (options.debug) console.log(options);
console.log('pizza details:');
if (program.small) console.log('- small pizza size');
if (program.pizzaType) console.log(`- ${program.pizzaType}`);
if (options.small) console.log('- small pizza size');
if (options.pizzaType) console.log(`- ${options.pizzaType}`);
```

@@ -130,3 +131,3 @@

`program.parse(arguments)` processes the arguments, leaving any args not consumed by the program options in the `program.args` array.
`program.parse(arguments)` processes the arguments, leaving any args not consumed by the program options in the `program.args` array. The parameter is optional and defaults to `process.argv`.

@@ -143,5 +144,5 @@ ### Default option value

program.parse(process.argv);
program.parse();
console.log(`cheese: ${program.cheese}`);
console.log(`cheese: ${program.opts().cheese}`);
```

@@ -171,6 +172,7 @@

.option('--no-cheese', 'plain with no cheese')
.parse(process.argv);
.parse();
const sauceStr = program.sauce ? 'sauce' : 'no sauce';
const cheeseStr = (program.cheese === false) ? 'no cheese' : `${program.cheese} cheese`;
const options = program.opts();
const sauceStr = options.sauce ? 'sauce' : 'no sauce';
const cheeseStr = (options.cheese === false) ? 'no cheese' : `${options.cheese} cheese`;
console.log(`You ordered a pizza with ${sauceStr} and ${cheeseStr}`);

@@ -201,5 +203,6 @@ ```

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}`);
const options = program.opts();
if (options.cheese === undefined) console.log('no cheese');
else if (options.cheese === true) console.log('add cheese');
else console.log(`add cheese type ${options.cheese}`);
```

@@ -228,3 +231,3 @@

program.parse(process.argv);
program.parse();
```

@@ -315,3 +318,3 @@

$ extra --drink huge
error: option '-d, --drink <size>' argument of 'huge' not in allowed choices: small, medium, large
error: option '-d, --drink <size>' argument 'huge' is invalid. Allowed choices are small, medium, large.
```

@@ -332,4 +335,8 @@

function myParseInt(value, dummyPrevious) {
// parseInt takes a string and an optional radix
return parseInt(value);
// parseInt takes a string and a radix
const parsedValue = parseInt(value, 10);
if (isNaN(parsedValue)) {
throw new commander.InvalidOptionArgumentError('Not a number.');
}
return parsedValue;
}

@@ -357,9 +364,10 @@

program.parse(process.argv);
program.parse();
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);
const options = program.opts();
if (options.float !== undefined) console.log(`float: ${options.float}`);
if (options.integer !== undefined) console.log(`integer: ${options.integer}`);
if (options.verbose > 0) console.log(`verbosity: ${options.verbose}`);
if (options.collect.length > 0) console.log(options.collect);
if (options.list !== undefined) console.log(options.list);
```

@@ -423,3 +431,3 @@

Example file: [env](./examples/env)
Example file: [arguments.js](./examples/arguments.js)

@@ -429,13 +437,11 @@ ```js

.version('0.1.0')
.arguments('<cmd> [env]')
.arguments('<username> [password]')
.description('test command', {
cmd: 'command to run',
env: 'environment to run test in'
username: 'user to login',
password: 'password for user, if required'
})
.action(function (cmd, env) {
console.log('command:', cmd);
console.log('environment:', env || 'no environment given');
.action((username, password) => {
console.log('username:', username);
console.log('environment:', password || 'no password given');
});
program.parse(process.argv);
```

@@ -447,17 +453,10 @@

```js
const { program } = require('commander');
program
.version('0.1.0')
.command('rmdir <dir> [otherDirs...]')
.action(function (dir, otherDirs) {
console.log('rmdir %s', dir);
if (otherDirs) {
otherDirs.forEach(function (oDir) {
console.log('rmdir %s', oDir);
});
}
.command('rmdir <dirs...>')
.action(function (dirs) {
dirs.forEach((dir) => {
console.log('rmdir %s', dir);
});
});
program.parse(process.argv);
```

@@ -467,19 +466,21 @@

### Action handler (sub)commands
### Action handler
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.
The action handler gets passed a parameter for each command-argument you declared, and two additional parameters
which are the parsed options and the command object itself.
Example file: [thank.js](./examples/thank.js)
```js
const { program } = require('commander');
program
.command('rm <dir>')
.option('-r, --recursive', 'Remove recursively')
.action(function (dir, cmdObj) {
console.log('remove ' + dir + (cmdObj.recursive ? ' recursively' : ''))
})
program.parse(process.argv)
.arguments('<name>')
.option('-t, --title <honorific>', 'title to use before name')
.option('-d, --debug', 'display some debugging')
.action((name, options, command) => {
if (options.debug) {
console.error('Called %s with options %o', command.name(), options);
}
const title = options.title ? `${options.title} ` : '';
console.log(`Thank-you ${title}${name}`);
});
```

@@ -500,3 +501,3 @@

A command's options on the command line are validated when the command is used. Any unknown options will be reported as an error.
A command's options and arguments on the command line are validated when the command is used. Any unknown options or unexpected command-arguments will be reported as an error, or you can suppress these checks with `.allowUnknownOption()` and `.allowExcessArguments()`.

@@ -537,6 +538,5 @@ ### Stand-alone executable (sub)commands

An application for pizzas ordering
An application for pizza ordering
Options:
-V, --version output the version number
-p, --peppers Add peppers

@@ -705,38 +705,17 @@ -c, --cheese <type> Add the specified type of cheese (default: "marble")

### Avoiding option name clashes
### Legacy options as properties
The original and default behaviour is that the option values are stored
as properties on the program, and the action handler is passed a
command object with the options values stored as properties.
This is very convenient to code, but the downside is possible clashes with
existing properties of Command.
Before Commander 7, the option values were stored as properties on the command.
This was convenient to code but the downside was possible clashes with
existing properties of `Command`. You can revert to the old behaviour to run unmodified legacy code by using `.storeOptionsAsProperties()`.
There are two new routines to change the behaviour, and the default behaviour may change in the future:
- `storeOptionsAsProperties`: whether to store option values as properties on command object, or store separately (specify false) and access using `.opts()`
- `passCommandToAction`: whether to pass command to action handler,
or just the options (specify false)
Example file: [storeOptionsAsProperties-action.js](./examples/storeOptionsAsProperties-action.js)
```js
program
.storeOptionsAsProperties(false)
.passCommandToAction(false);
program
.name('my-program-name')
.option('-n,--name <name>');
program
.command('show')
.option('-a,--action <action>')
.action((options) => {
console.log(options.action);
.storeOptionsAsProperties()
.option('-d, --debug')
.action((commandAndOptions) => {
if (commandAndOptions.debug) {
console.error(`Called ${commandAndOptions.name()}`);
}
});
program.parse(process.argv);
const programOptions = program.opts();
console.log(programOptions.name);
```

@@ -843,4 +822,6 @@

Example file: [deploy](./examples/deploy)
In a single command program, you might not need an action handler.
Example file: [pizza](./examples/pizza)
```js

@@ -850,24 +831,46 @@ const { program } = require('commander');

program
.version('0.1.0')
.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');
.description('An application for pizza ordering')
.option('-p, --peppers', 'Add peppers')
.option('-c, --cheese <type>', 'Add the specified type of cheese', 'marble')
.option('-C, --no-cheese', 'You do not want any cheese');
program.parse();
const options = program.opts();
console.log('you ordered a pizza with:');
if (options.peppers) console.log(' - peppers');
const cheese = !options.cheese ? 'no' : options.cheese;
console.log(' - %s cheese', cheese);
```
In a multi-command program, you will have action handlers for each command (or stand-alone executables for the commands).
Example file: [deploy](./examples/deploy)
```js
const { Command } = require('commander');
const program = new Command();
program
.version('0.0.1')
.option('-c, --config <path>', 'set config path', './deploy.conf');
program
.command('setup [env]')
.description('run setup commands for all envs')
.option("-s, --setup_mode [mode]", "Which setup mode to use")
.action(function(env, options){
const mode = options.setup_mode || "normal";
.option('-s, --setup_mode <mode>', 'Which setup mode to use', 'normal')
.action((env, options) => {
env = env || 'all';
console.log('setup for %s env(s) with %s mode', env, mode);
console.log('read config from %s', program.opts().config);
console.log('setup for %s env(s) with %s mode', env, options.setup_mode);
});
program
.command('exec <cmd>')
.command('exec <script>')
.alias('ex')
.description('execute the given remote cmd')
.option("-e, --exec_mode <mode>", "Which exec mode to use")
.action(function(cmd, options){
console.log('exec "%s" using %s mode', cmd, options.exec_mode);
.option('-e, --exec_mode <mode>', 'Which exec mode to use', 'fast')
.action((script, options) => {
console.log('read config from %s', program.opts().config);
console.log('exec "%s" using %s mode and config %s', script, options.exec_mode, program.opts().config);
}).addHelpText('after', `

@@ -878,7 +881,7 @@ Examples:

);
program.parse(process.argv);
```
More Demos can be found in the [examples](https://github.com/tj/commander.js/tree/master/examples) directory.
More samples can be found in the [examples](https://github.com/tj/commander.js/tree/master/examples) directory.

@@ -885,0 +888,0 @@ ## Support

@@ -17,2 +17,6 @@ // Type definitions for commander

interface InvalidOptionArgumentError extends CommanderError {
}
type InvalidOptionArgumentErrorConstructor = new (message: string) => InvalidOptionArgumentError;
interface Option {

@@ -149,4 +153,2 @@ flags: string;

interface Command {
[key: string]: any; // options as properties
args: string[];

@@ -378,10 +380,2 @@

/**
* Whether to pass command to action handler,
* or just the options (specify false).
*
* @returns `this` command for chaining
*/
passCommandToAction(passCommand?: boolean): this;
/**
* Alter parsing of short flags with optional values.

@@ -406,2 +400,9 @@ *

/**
* Allow excess arguments on the command line.
*
* @returns `this` command for chaining
*/
allowExcessArguments(allowExcess?: boolean): this;
/**
* Parse `argv`, setting options and invoking commands when defined.

@@ -574,2 +575,3 @@ *

// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface ParseOptionsResult {

@@ -580,2 +582,3 @@ operands: string[];

// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface CommanderStatic extends Command {

@@ -586,2 +589,3 @@ program: Command;

CommanderError: CommanderErrorConstructor;
InvalidOptionArgumentError: InvalidOptionArgumentErrorConstructor;
Help: HelpConstructor;

@@ -588,0 +592,0 @@ }

Sorry, the diff of this file is too big to display

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