Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: tj/commander.js
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v9.3.0
Choose a base ref
...
head repository: tj/commander.js
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v9.4.0
Choose a head ref
  • 9 commits
  • 15 files changed
  • 4 contributors

Commits on May 28, 2022

  1. Add target-branch

    shadowspawn authored and abetomo committed May 28, 2022
    Copy the full SHA
    fd24e92 View commit details

Commits on May 29, 2022

  1. Copy the full SHA
    3e202f3 View commit details
  2. Bump actions/setup-node from 2 to 3

    Bumps [actions/setup-node](https://github.com/actions/setup-node) from 2 to 3.
    - [Release notes](https://github.com/actions/setup-node/releases)
    - [Commits](actions/setup-node@v2...v3)
    
    ---
    updated-dependencies:
    - dependency-name: actions/setup-node
      dependency-type: direct:production
      update-type: version-update:semver-major
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    dependabot[bot] authored and abetomo committed May 29, 2022
    Copy the full SHA
    becb22f View commit details
  3. Bump actions/checkout from 2 to 3

    Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3.
    - [Release notes](https://github.com/actions/checkout/releases)
    - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
    - [Commits](actions/checkout@v2...v3)
    
    ---
    updated-dependencies:
    - dependency-name: actions/checkout
      dependency-type: direct:production
      update-type: version-update:semver-major
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    dependabot[bot] authored and abetomo committed May 29, 2022
    Copy the full SHA
    211ff69 View commit details
  4. Bump github/codeql-action from 1 to 2

    Bumps [github/codeql-action](https://github.com/github/codeql-action) from 1 to 2.
    - [Release notes](https://github.com/github/codeql-action/releases)
    - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
    - [Commits](github/codeql-action@v1...v2)
    
    ---
    updated-dependencies:
    - dependency-name: github/codeql-action
      dependency-type: direct:production
      update-type: version-update:semver-major
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    dependabot[bot] authored and abetomo committed May 29, 2022
    Copy the full SHA
    dccc906 View commit details

Commits on Jun 20, 2022

  1. Copy the full SHA
    3ae30a2 View commit details

Commits on Jul 12, 2022

  1. Copy the full SHA
    2c7f687 View commit details

Commits on Jul 13, 2022

  1. Update dependencies (#1767)

    * Update to eslint@8 and standard dependencies
    * Update jest and typescript and tsd (using npm 8)
    shadowspawn authored Jul 13, 2022
    Copy the full SHA
    177cc6e View commit details

Commits on Jul 15, 2022

  1. Update CHANGELOG preparing for 9.4.0

    shadowspawn authored and abetomo committed Jul 15, 2022
    Copy the full SHA
    82fcb98 View commit details
Showing with 3,452 additions and 4,569 deletions.
  1. +1 −0 .github/dependabot.yml
  2. +6 −6 .github/workflows/codeql-analysis.yml
  3. +2 −2 .github/workflows/tests.yml
  4. +18 −0 CHANGELOG.md
  5. +4 −4 Readme.md
  6. +4 −4 Readme_zh-CN.md
  7. +1 −0 esm.mjs
  8. +28 −19 examples/hook.js
  9. +32 −6 lib/command.js
  10. +3,296 −4,511 package-lock.json
  11. +14 −14 package.json
  12. +36 −0 tests/command.hook.test.js
  13. +2 −1 tests/esm-imports-test.mjs
  14. +2 −2 typings/index.d.ts
  15. +6 −0 typings/index.test-d.ts
1 change: 1 addition & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
version: 2
updates:
- package-ecosystem: "github-actions"
target-branch: "develop"
directory: "/"
schedule:
interval: "weekly"
12 changes: 6 additions & 6 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
@@ -2,10 +2,10 @@ name: "CodeQL"

on:
push:
branches: [ master ]
branches: [ master, develop ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
branches: [ master, develop ]
schedule:
- cron: '27 5 * * 6'

@@ -25,11 +25,11 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v3

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -40,7 +40,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
uses: github/codeql-action/autobuild@v2

# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@@ -54,4 +54,4 @@ jobs:
# make release

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v2
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -16,9 +16,9 @@ jobs:
os: [ubuntu-latest, windows-latest, macos-latest]

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
uses: actions/setup-node@v3
with:
cache: 'npm'
node-version: ${{ matrix.node-version }}
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -8,6 +8,20 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
<!-- markdownlint-disable MD024 -->
<!-- markdownlint-disable MD004 -->

## [9.4.0] (2022-07-15)

### Added

- `preSubcommand` hook called before direct subcommands ([#1763])

### Fixed

- export `InvalidOptionArgumentError` in esm ([#1756])

### Changed

- update dependencies ([#1767])

## [9.3.0] (2022-05-28)

### Added
@@ -1078,6 +1092,9 @@ program
[#1724]: https://github.com/tj/commander.js/pull/1724
[#1726]: https://github.com/tj/commander.js/pull/1726
[#1727]: https://github.com/tj/commander.js/pull/1727
[#1756]: https://github.com/tj/commander.js/pull/1756
[#1763]: https://github.com/tj/commander.js/pull/1763
[#1767]: https://github.com/tj/commander.js/pull/1767

<!-- Referenced in 5.x -->
[#1]: https://github.com/tj/commander.js/issues/1
@@ -1156,6 +1173,7 @@ program
[#1028]: https://github.com/tj/commander.js/pull/1028

[Unreleased]: https://github.com/tj/commander.js/compare/master...develop
[9.4.0]: https://github.com/tj/commander.js/compare/v9.3.0...v9.4.0
[9.3.0]: https://github.com/tj/commander.js/compare/v9.2.0...v9.3.0
[9.2.0]: https://github.com/tj/commander.js/compare/v9.1.0...v9.2.0
[9.1.0]: https://github.com/tj/commander.js/compare/v9.0.0...v9.1.0
8 changes: 4 additions & 4 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -719,10 +719,10 @@ The callback hook can be `async`, in which case you call `.parseAsync` rather th

The supported events are:

- `preAction`: called before action handler for this command and its subcommands
- `postAction`: called after action handler for this command and its subcommands

The hook is passed the command it was added to, and the command running the action handler.
| event name | when hook called | callback parameters |
| :-- | :-- | :-- |
| `preAction`, `postAction` | before/after action handler for this command and its nested subcommands | `(thisCommand, actionCommand)` |
| `preSubcommand` | before parsing direct subcommand | `(thisCommand, subcommand)` |

## Automated help

8 changes: 4 additions & 4 deletions Readme_zh-CN.md
Original file line number Diff line number Diff line change
@@ -696,10 +696,10 @@ program

支持的事件有:

- `preAction`:在本命令或其子命令的处理函数执行前
- `postAction`:在本命令或其子命令的处理函数执行后

钩子函数的参数为添加上钩子的命令,及实际执行的命令。
| 事件名称 | 触发时机 | 参数列表 |
| :-- | :-- | :-- |
| `preAction`, `postAction` | 本命令或其子命令的处理函数执行前/后 | `(thisCommand, actionCommand)` |
| `preSubcommand` | 在其直接子命令解析之前调用 | `(thisCommand, subcommand)` |

## 自动化帮助信息

1 change: 1 addition & 0 deletions esm.mjs
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ export const {
createOption,
CommanderError,
InvalidArgumentError,
InvalidOptionArgumentError, // deprecated old name
Command,
Argument,
Option,
47 changes: 28 additions & 19 deletions examples/hook.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
#!/usr/bin/env node

// const commander = require('commander'); // (normal include)
const commander = require('../'); // include commander in git clone of commander repo
const program = new commander.Command();
const { Command, Option } = require('../'); // include commander in git clone of commander repo
const program = new Command();

// This example shows using some hooks for life cycle events.

const timeLabel = 'command duration';
program
.option('-p, --profile', 'show how long command takes')
.option('--profile', 'show how long command takes')
.hook('preAction', (thisCommand) => {
if (thisCommand.opts().profile) {
console.time(timeLabel);
@@ -21,7 +21,7 @@ program
});

program
.option('-t, --trace', 'display trace statements for commands')
.option('--trace', 'display trace statements for commands')
.hook('preAction', (thisCommand, actionCommand) => {
if (thisCommand.opts().trace) {
console.log('>>>>');
@@ -32,25 +32,34 @@ program
}
});

program.command('delay')
.option('--message <value>', 'custom message to display', 'Thanks for waiting')
.argument('[seconds]', 'how long to delay', '1')
.action(async(waitSeconds, options) => {
await new Promise(resolve => setTimeout(resolve, parseInt(waitSeconds) * 1000));
console.log(options.message);
program
.option('--env <filename>', 'specify environment file')
.hook('preSubcommand', (thisCommand, subcommand) => {
if (thisCommand.opts().env) {
// One use case for this hook is modifying environment variables before
// parsing the subcommand, say by reading .env file.
console.log(`Reading ${thisCommand.opts().env}...`);
process.env.PORT = 80;
console.log(`About to call subcommand: ${subcommand.name()}`);
}
});

program.command('hello')
.option('-e, --example')
.action(() => console.log('Hello, world'));
program.command('start')
.argument('[script]', 'script name', 'server.js')
.option('-d, --delay <seconds>', 'how long to delay before starting')
.addOption(new Option('-p, --port <number>', 'port number').default(8080).env('PORT'))
.action(async(script, options) => {
if (options.delay) {
await new Promise(resolve => setTimeout(resolve, parseInt(options.delay) * 1000));
}
console.log(`Starting ${script} on port ${options.port}`);
});

// Some of the hooks or actions are async, so call parseAsync rather than parse.
program.parseAsync().then(() => {});

// Try the following:
// node hook.js hello
// node hook.js --profile hello
// node hook.js --trace hello --example
// node hook.js delay
// node hook.js --trace delay 5 --message bye
// node hook.js --profile delay
// node hook.js start
// node hook.js --trace start --port 9000 test.js
// node hook.js --profile start --delay 5
// node hook.js --env=production.env start
38 changes: 32 additions & 6 deletions lib/command.js
Original file line number Diff line number Diff line change
@@ -399,7 +399,7 @@ class Command extends EventEmitter {
*/

hook(event, listener) {
const allowedValues = ['preAction', 'postAction'];
const allowedValues = ['preSubcommand', 'preAction', 'postAction'];
if (!allowedValues.includes(event)) {
throw new Error(`Unexpected value for event passed to hook : '${event}'.
Expecting one of '${allowedValues.join("', '")}'`);
@@ -1054,11 +1054,16 @@ Expecting one of '${allowedValues.join("', '")}'`);
const subCommand = this._findCommand(commandName);
if (!subCommand) this.help({ error: true });

if (subCommand._executableHandler) {
this._executeSubCommand(subCommand, operands.concat(unknown));
} else {
return subCommand._parseCommand(operands, unknown);
}
let hookResult;
hookResult = this._chainOrCallSubCommandHook(hookResult, subCommand, 'preSubcommand');
hookResult = this._chainOrCall(hookResult, () => {
if (subCommand._executableHandler) {
this._executeSubCommand(subCommand, operands.concat(unknown));
} else {
return subCommand._parseCommand(operands, unknown);
}
});
return hookResult;
}

/**
@@ -1185,6 +1190,27 @@ Expecting one of '${allowedValues.join("', '")}'`);
return result;
}

/**
*
* @param {Promise|undefined} promise
* @param {Command} subCommand
* @param {string} event
* @return {Promise|undefined}
* @api private
*/

_chainOrCallSubCommandHook(promise, subCommand, event) {
let result = promise;
if (this._lifeCycleHooks[event] !== undefined) {
this._lifeCycleHooks[event].forEach((hook) => {
result = this._chainOrCall(result, () => {
return hook(this, subCommand);
});
});
}
return result;
}

/**
* Process arguments in context of this command.
* Returns action result, in case it is a promise.
Loading