From 5712a9f56be635df594068066e79590ca3e2e9f1 Mon Sep 17 00:00:00 2001 From: isaacs Date: Mon, 10 May 2021 15:10:25 -0700 Subject: [PATCH] Add workspaces support to reify/rebuild commands This adds `--workspace` support to: - audit (including audit fix) - ci - dedupe - find-dupes - install - install-ci-test - install-test - prune - rebuild - uninstall - update Also addresses missing error handling case, identified by @timoxley. https://github.com/npm/cli/pull/3227#discussion_r631024491 --- docs/content/commands/npm-audit.md | 32 +++++++++++++++++++ docs/content/commands/npm-dedupe.md | 32 +++++++++++++++++++ docs/content/commands/npm-find-dupes.md | 32 +++++++++++++++++++ docs/content/commands/npm-install-test.md | 32 +++++++++++++++++++ docs/content/commands/npm-install.md | 32 +++++++++++++++++++ docs/content/commands/npm-prune.md | 32 +++++++++++++++++++ docs/content/commands/npm-rebuild.md | 32 +++++++++++++++++++ docs/content/commands/npm-uninstall.md | 32 +++++++++++++++++++ docs/content/commands/npm-update.md | 32 +++++++++++++++++++ lib/audit.js | 7 ++-- lib/base-command.js | 1 + lib/ci.js | 5 +-- lib/dedupe.js | 6 ++-- lib/find-dupes.js | 5 +-- lib/install.js | 6 ++-- lib/prune.js | 7 ++-- lib/rebuild.js | 7 ++-- lib/uninstall.js | 8 ++--- lib/update.js | 6 ++-- lib/workspaces/arborist-cmd.js | 4 ++- .../test/lib/utils/npm-usage.js.test.cjs | 19 ++++++++++- test/lib/update.js | 16 ++++++++-- test/lib/workspaces/arborist-cmd.js | 16 ++++++++++ 23 files changed, 375 insertions(+), 26 deletions(-) diff --git a/docs/content/commands/npm-audit.md b/docs/content/commands/npm-audit.md index 27c4d972597a8..0771d897df90d 100644 --- a/docs/content/commands/npm-audit.md +++ b/docs/content/commands/npm-audit.md @@ -271,6 +271,38 @@ it will be included. If the resulting omit list includes `'dev'`, then the `NODE_ENV` environment variable will be set to `'production'` for all lifecycle scripts. +#### `workspace` + +* Default: +* Type: String (can be set multiple times) + +Enable running a command in the context of the configured workspaces of the +current project while filtering by running only the workspaces defined by +this configuration option. + +Valid values for the `workspace` config are either: + +* Workspace names +* Path to a workspace directory +* Path to a parent workspace directory (will result to selecting all of the + nested workspaces) + +When set for the `npm init` command, this may be set to the folder of a +workspace which does not yet exist, to create the folder and set it up as a +brand new workspace within the project. + +This value is not exported to the environment for child processes. + +#### `workspaces` + +* Default: false +* Type: Boolean + +Enable running a command in the context of **all** the configured +workspaces. + +This value is not exported to the environment for child processes. + ### See Also diff --git a/docs/content/commands/npm-dedupe.md b/docs/content/commands/npm-dedupe.md index e870ad269815d..fbccc41053292 100644 --- a/docs/content/commands/npm-dedupe.md +++ b/docs/content/commands/npm-dedupe.md @@ -202,6 +202,38 @@ commands that modify your local installation, eg, `install`, `update`, Note: This is NOT honored by other network related commands, eg `dist-tags`, `owner`, etc. +#### `workspace` + +* Default: +* Type: String (can be set multiple times) + +Enable running a command in the context of the configured workspaces of the +current project while filtering by running only the workspaces defined by +this configuration option. + +Valid values for the `workspace` config are either: + +* Workspace names +* Path to a workspace directory +* Path to a parent workspace directory (will result to selecting all of the + nested workspaces) + +When set for the `npm init` command, this may be set to the folder of a +workspace which does not yet exist, to create the folder and set it up as a +brand new workspace within the project. + +This value is not exported to the environment for child processes. + +#### `workspaces` + +* Default: false +* Type: Boolean + +Enable running a command in the context of **all** the configured +workspaces. + +This value is not exported to the environment for child processes. + ### See Also diff --git a/docs/content/commands/npm-find-dupes.md b/docs/content/commands/npm-find-dupes.md index 933c76e2fe231..28281d5678ab7 100644 --- a/docs/content/commands/npm-find-dupes.md +++ b/docs/content/commands/npm-find-dupes.md @@ -132,6 +132,38 @@ When "true" displays the message at the end of each `npm install` acknowledging the number of dependencies looking for funding. See [`npm fund`](/commands/npm-fund) for details. +#### `workspace` + +* Default: +* Type: String (can be set multiple times) + +Enable running a command in the context of the configured workspaces of the +current project while filtering by running only the workspaces defined by +this configuration option. + +Valid values for the `workspace` config are either: + +* Workspace names +* Path to a workspace directory +* Path to a parent workspace directory (will result to selecting all of the + nested workspaces) + +When set for the `npm init` command, this may be set to the folder of a +workspace which does not yet exist, to create the folder and set it up as a +brand new workspace within the project. + +This value is not exported to the environment for child processes. + +#### `workspaces` + +* Default: false +* Type: Boolean + +Enable running a command in the context of **all** the configured +workspaces. + +This value is not exported to the environment for child processes. + ### See Also diff --git a/docs/content/commands/npm-install-test.md b/docs/content/commands/npm-install-test.md index 1adf6490f9327..deefbd96b52fd 100644 --- a/docs/content/commands/npm-install-test.md +++ b/docs/content/commands/npm-install-test.md @@ -187,6 +187,38 @@ commands that modify your local installation, eg, `install`, `update`, Note: This is NOT honored by other network related commands, eg `dist-tags`, `owner`, etc. +#### `workspace` + +* Default: +* Type: String (can be set multiple times) + +Enable running a command in the context of the configured workspaces of the +current project while filtering by running only the workspaces defined by +this configuration option. + +Valid values for the `workspace` config are either: + +* Workspace names +* Path to a workspace directory +* Path to a parent workspace directory (will result to selecting all of the + nested workspaces) + +When set for the `npm init` command, this may be set to the folder of a +workspace which does not yet exist, to create the folder and set it up as a +brand new workspace within the project. + +This value is not exported to the environment for child processes. + +#### `workspaces` + +* Default: false +* Type: Boolean + +Enable running a command in the context of **all** the configured +workspaces. + +This value is not exported to the environment for child processes. + ### See Also diff --git a/docs/content/commands/npm-install.md b/docs/content/commands/npm-install.md index 9e61cf7268bd6..e5091e6604c91 100644 --- a/docs/content/commands/npm-install.md +++ b/docs/content/commands/npm-install.md @@ -571,6 +571,38 @@ commands that modify your local installation, eg, `install`, `update`, Note: This is NOT honored by other network related commands, eg `dist-tags`, `owner`, etc. +#### `workspace` + +* Default: +* Type: String (can be set multiple times) + +Enable running a command in the context of the configured workspaces of the +current project while filtering by running only the workspaces defined by +this configuration option. + +Valid values for the `workspace` config are either: + +* Workspace names +* Path to a workspace directory +* Path to a parent workspace directory (will result to selecting all of the + nested workspaces) + +When set for the `npm init` command, this may be set to the folder of a +workspace which does not yet exist, to create the folder and set it up as a +brand new workspace within the project. + +This value is not exported to the environment for child processes. + +#### `workspaces` + +* Default: false +* Type: Boolean + +Enable running a command in the context of **all** the configured +workspaces. + +This value is not exported to the environment for child processes. + ### Algorithm diff --git a/docs/content/commands/npm-prune.md b/docs/content/commands/npm-prune.md index 28890193295f2..ecb6bdcd6cb14 100644 --- a/docs/content/commands/npm-prune.md +++ b/docs/content/commands/npm-prune.md @@ -77,6 +77,38 @@ Whether or not to output JSON data, rather than the normal output. Not supported by all npm commands. +#### `workspace` + +* Default: +* Type: String (can be set multiple times) + +Enable running a command in the context of the configured workspaces of the +current project while filtering by running only the workspaces defined by +this configuration option. + +Valid values for the `workspace` config are either: + +* Workspace names +* Path to a workspace directory +* Path to a parent workspace directory (will result to selecting all of the + nested workspaces) + +When set for the `npm init` command, this may be set to the folder of a +workspace which does not yet exist, to create the folder and set it up as a +brand new workspace within the project. + +This value is not exported to the environment for child processes. + +#### `workspaces` + +* Default: false +* Type: Boolean + +Enable running a command in the context of **all** the configured +workspaces. + +This value is not exported to the environment for child processes. + ### See Also diff --git a/docs/content/commands/npm-rebuild.md b/docs/content/commands/npm-rebuild.md index 144dd7b09cd3a..49c822d730526 100644 --- a/docs/content/commands/npm-rebuild.md +++ b/docs/content/commands/npm-rebuild.md @@ -66,6 +66,38 @@ Note that commands explicitly intended to run a particular script, such as will still run their intended script if `ignore-scripts` is set, but they will *not* run any pre- or post-scripts. +#### `workspace` + +* Default: +* Type: String (can be set multiple times) + +Enable running a command in the context of the configured workspaces of the +current project while filtering by running only the workspaces defined by +this configuration option. + +Valid values for the `workspace` config are either: + +* Workspace names +* Path to a workspace directory +* Path to a parent workspace directory (will result to selecting all of the + nested workspaces) + +When set for the `npm init` command, this may be set to the folder of a +workspace which does not yet exist, to create the folder and set it up as a +brand new workspace within the project. + +This value is not exported to the environment for child processes. + +#### `workspaces` + +* Default: false +* Type: Boolean + +Enable running a command in the context of **all** the configured +workspaces. + +This value is not exported to the environment for child processes. + ### See Also diff --git a/docs/content/commands/npm-uninstall.md b/docs/content/commands/npm-uninstall.md index cffb9bdb55ffa..b6ba31393834d 100644 --- a/docs/content/commands/npm-uninstall.md +++ b/docs/content/commands/npm-uninstall.md @@ -68,6 +68,38 @@ Save installed packages to a package.json file as dependencies. When used with the `npm rm` command, removes the dependency from package.json. +#### `workspace` + +* Default: +* Type: String (can be set multiple times) + +Enable running a command in the context of the configured workspaces of the +current project while filtering by running only the workspaces defined by +this configuration option. + +Valid values for the `workspace` config are either: + +* Workspace names +* Path to a workspace directory +* Path to a parent workspace directory (will result to selecting all of the + nested workspaces) + +When set for the `npm init` command, this may be set to the folder of a +workspace which does not yet exist, to create the folder and set it up as a +brand new workspace within the project. + +This value is not exported to the environment for child processes. + +#### `workspaces` + +* Default: false +* Type: Boolean + +Enable running a command in the context of **all** the configured +workspaces. + +This value is not exported to the environment for child processes. + ### See Also diff --git a/docs/content/commands/npm-update.md b/docs/content/commands/npm-update.md index 044b1a82dc492..4c9271c6633c3 100644 --- a/docs/content/commands/npm-update.md +++ b/docs/content/commands/npm-update.md @@ -258,6 +258,38 @@ commands that modify your local installation, eg, `install`, `update`, Note: This is NOT honored by other network related commands, eg `dist-tags`, `owner`, etc. +#### `workspace` + +* Default: +* Type: String (can be set multiple times) + +Enable running a command in the context of the configured workspaces of the +current project while filtering by running only the workspaces defined by +this configuration option. + +Valid values for the `workspace` config are either: + +* Workspace names +* Path to a workspace directory +* Path to a parent workspace directory (will result to selecting all of the + nested workspaces) + +When set for the `npm init` command, this may be set to the folder of a +workspace which does not yet exist, to create the folder and set it up as a +brand new workspace within the project. + +This value is not exported to the environment for child processes. + +#### `workspaces` + +* Default: false +* Type: Boolean + +Enable running a command in the context of **all** the configured +workspaces. + +This value is not exported to the environment for child processes. + ### See Also diff --git a/lib/audit.js b/lib/audit.js index ea27b02001f76..a97fd9b30abd4 100644 --- a/lib/audit.js +++ b/lib/audit.js @@ -2,9 +2,9 @@ const Arborist = require('@npmcli/arborist') const auditReport = require('npm-audit-report') const reifyFinish = require('./utils/reify-finish.js') const auditError = require('./utils/audit-error.js') -const BaseCommand = require('./base-command.js') +const ArboristWorkspaceCmd = require('./workspaces/arborist-cmd.js') -class Audit extends BaseCommand { +class Audit extends ArboristWorkspaceCmd { /* istanbul ignore next - see test/lib/load-all-commands.js */ static get description () { return 'Run a security audit' @@ -24,6 +24,7 @@ class Audit extends BaseCommand { 'json', 'package-lock-only', 'omit', + ...super.params, ] } @@ -57,7 +58,9 @@ class Audit extends BaseCommand { audit: true, path: this.npm.prefix, reporter, + workspaces: this.workspaces, } + const arb = new Arborist(opts) const fix = args[0] === 'fix' await arb.audit({ fix }) diff --git a/lib/base-command.js b/lib/base-command.js index 322fd8963a203..e1efcff5832b3 100644 --- a/lib/base-command.js +++ b/lib/base-command.js @@ -6,6 +6,7 @@ class BaseCommand { constructor (npm) { this.wrapWidth = 80 this.npm = npm + this.workspaces = null } get name () { diff --git a/lib/ci.js b/lib/ci.js index d2a27059c4094..3a2a2b316a150 100644 --- a/lib/ci.js +++ b/lib/ci.js @@ -17,9 +17,9 @@ const removeNodeModules = async where => { await Promise.all(entries.map(f => rimraf(`${path}/${f}`, rimrafOpts))) process.emit('timeEnd', 'npm-ci:rm') } -const BaseCommand = require('./base-command.js') +const ArboristWorkspaceCmd = require('./workspaces/arborist-cmd.js') -class CI extends BaseCommand { +class CI extends ArboristWorkspaceCmd { /* istanbul ignore next - see test/lib/load-all-commands.js */ static get description () { return 'Install a project with a clean slate' @@ -55,6 +55,7 @@ class CI extends BaseCommand { path: where, log: this.npm.log, save: false, // npm ci should never modify the lockfile or package.json + workspaces: this.workspaces, } const arb = new Arborist(opts) diff --git a/lib/dedupe.js b/lib/dedupe.js index e58b6c55fd370..9a58316b80109 100644 --- a/lib/dedupe.js +++ b/lib/dedupe.js @@ -2,9 +2,9 @@ const Arborist = require('@npmcli/arborist') const reifyFinish = require('./utils/reify-finish.js') -const BaseCommand = require('./base-command.js') +const ArboristWorkspaceCmd = require('./workspaces/arborist-cmd.js') -class Dedupe extends BaseCommand { +class Dedupe extends ArboristWorkspaceCmd { /* istanbul ignore next - see test/lib/load-all-commands.js */ static get description () { return 'Reduce duplication in the package tree' @@ -28,6 +28,7 @@ class Dedupe extends BaseCommand { 'bin-links', 'fund', 'dry-run', + ...super.params, ] } @@ -49,6 +50,7 @@ class Dedupe extends BaseCommand { log: this.npm.log, path: where, dryRun, + workspaces: this.workspaces, } const arb = new Arborist(opts) await arb.dedupe(opts) diff --git a/lib/find-dupes.js b/lib/find-dupes.js index ff2700f5beeb1..69b30e8aa3dbb 100644 --- a/lib/find-dupes.js +++ b/lib/find-dupes.js @@ -1,7 +1,7 @@ // dedupe duplicated packages, or find them in the tree -const BaseCommand = require('./base-command.js') +const ArboristWorkspaceCmd = require('./workspaces/arborist-cmd.js') -class FindDupes extends BaseCommand { +class FindDupes extends ArboristWorkspaceCmd { /* istanbul ignore next - see test/lib/load-all-commands.js */ static get description () { return 'Find duplication in the package tree' @@ -24,6 +24,7 @@ class FindDupes extends BaseCommand { 'audit', 'bin-links', 'fund', + ...super.params, ] } diff --git a/lib/install.js b/lib/install.js index 490792a41a7bf..7c5f55bb9de8a 100644 --- a/lib/install.js +++ b/lib/install.js @@ -9,8 +9,8 @@ const { resolve, join } = require('path') const Arborist = require('@npmcli/arborist') const runScript = require('@npmcli/run-script') -const BaseCommand = require('./base-command.js') -class Install extends BaseCommand { +const ArboristWorkspaceCmd = require('./workspaces/arborist-cmd.js') +class Install extends ArboristWorkspaceCmd { /* istanbul ignore next - see test/lib/load-all-commands.js */ static get description () { return 'Install a package' @@ -37,6 +37,7 @@ class Install extends BaseCommand { 'bin-links', 'fund', 'dry-run', + ...super.params, ] } @@ -143,6 +144,7 @@ class Install extends BaseCommand { auditLevel: null, path: where, add: args, + workspaces: this.workspaces, } const arb = new Arborist(opts) await arb.reify(opts) diff --git a/lib/prune.js b/lib/prune.js index 4f04c3cddd2e9..a90e7595421ec 100644 --- a/lib/prune.js +++ b/lib/prune.js @@ -2,8 +2,8 @@ const Arborist = require('@npmcli/arborist') const reifyFinish = require('./utils/reify-finish.js') -const BaseCommand = require('./base-command.js') -class Prune extends BaseCommand { +const ArboristWorkspaceCmd = require('./workspaces/arborist-cmd.js') +class Prune extends ArboristWorkspaceCmd { /* istanbul ignore next - see test/lib/load-all-commands.js */ static get description () { return 'Remove extraneous packages' @@ -16,7 +16,7 @@ class Prune extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ static get params () { - return ['omit', 'dry-run', 'json'] + return ['omit', 'dry-run', 'json', ...super.params] } /* istanbul ignore next - see test/lib/load-all-commands.js */ @@ -34,6 +34,7 @@ class Prune extends BaseCommand { ...this.npm.flatOptions, path: where, log: this.npm.log, + workspaces: this.workspaces, } const arb = new Arborist(opts) await arb.prune(opts) diff --git a/lib/rebuild.js b/lib/rebuild.js index 9c2d729e73f4e..ef88dc5168d0c 100644 --- a/lib/rebuild.js +++ b/lib/rebuild.js @@ -4,8 +4,8 @@ const npa = require('npm-package-arg') const semver = require('semver') const completion = require('./utils/completion/installed-deep.js') -const BaseCommand = require('./base-command.js') -class Rebuild extends BaseCommand { +const ArboristWorkspaceCmd = require('./workspaces/arborist-cmd.js') +class Rebuild extends ArboristWorkspaceCmd { /* istanbul ignore next - see test/lib/load-all-commands.js */ static get description () { return 'Rebuild a package' @@ -22,6 +22,7 @@ class Rebuild extends BaseCommand { 'global', 'bin-links', 'ignore-scripts', + ...super.params, ] } @@ -45,6 +46,8 @@ class Rebuild extends BaseCommand { const arb = new Arborist({ ...this.npm.flatOptions, path: where, + // TODO when extending ReifyCmd + // workspaces: this.workspaces, }) if (args.length) { diff --git a/lib/uninstall.js b/lib/uninstall.js index 79a4420d89f39..cbbc62c2a4a75 100644 --- a/lib/uninstall.js +++ b/lib/uninstall.js @@ -5,8 +5,8 @@ const rpj = require('read-package-json-fast') const reifyFinish = require('./utils/reify-finish.js') const completion = require('./utils/completion/installed-shallow.js') -const BaseCommand = require('./base-command.js') -class Uninstall extends BaseCommand { +const ArboristWorkspaceCmd = require('./workspaces/arborist-cmd.js') +class Uninstall extends ArboristWorkspaceCmd { static get description () { return 'Remove a package' } @@ -18,7 +18,7 @@ class Uninstall extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ static get params () { - return ['save'] + return ['save', ...super.params] } /* istanbul ignore next - see test/lib/load-all-commands.js */ @@ -66,7 +66,7 @@ class Uninstall extends BaseCommand { path, log: this.npm.log, rm: args, - + workspaces: this.workspaces, } const arb = new Arborist(opts) await arb.reify(opts) diff --git a/lib/update.js b/lib/update.js index ff9ef9d5e8100..3cdeb8ea7dd31 100644 --- a/lib/update.js +++ b/lib/update.js @@ -6,8 +6,8 @@ const log = require('npmlog') const reifyFinish = require('./utils/reify-finish.js') const completion = require('./utils/completion/installed-deep.js') -const BaseCommand = require('./base-command.js') -class Update extends BaseCommand { +const ArboristWorkspaceCmd = require('./workspaces/arborist-cmd.js') +class Update extends ArboristWorkspaceCmd { /* istanbul ignore next - see test/lib/load-all-commands.js */ static get description () { return 'Update packages' @@ -32,6 +32,7 @@ class Update extends BaseCommand { 'bin-links', 'fund', 'dry-run', + ...super.params, ] } @@ -65,6 +66,7 @@ class Update extends BaseCommand { ...this.npm.flatOptions, log: this.npm.log, path: where, + workspaces: this.workspaces, }) await arb.reify({ update }) diff --git a/lib/workspaces/arborist-cmd.js b/lib/workspaces/arborist-cmd.js index f08843bd9ea5a..b12c0ee47b19f 100644 --- a/lib/workspaces/arborist-cmd.js +++ b/lib/workspaces/arborist-cmd.js @@ -3,12 +3,13 @@ // be able to run a filtered Arborist.reify() at some point. const BaseCommand = require('../base-command.js') -const getWorkspaces = require('../workspaces/get-workspaces.js') +const getWorkspaces = require('./get-workspaces.js') class ArboristCmd extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ static get params () { return [ 'workspace', + 'workspaces', ] } @@ -18,6 +19,7 @@ class ArboristCmd extends BaseCommand { this.workspaces = [...workspaces.keys()] this.exec(args, cb) }) + .catch(er => cb(er)) } } diff --git a/tap-snapshots/test/lib/utils/npm-usage.js.test.cjs b/tap-snapshots/test/lib/utils/npm-usage.js.test.cjs index 661deec269177..2abc8b4ff1412 100644 --- a/tap-snapshots/test/lib/utils/npm-usage.js.test.cjs +++ b/tap-snapshots/test/lib/utils/npm-usage.js.test.cjs @@ -210,6 +210,8 @@ All commands: [--audit-level ] [--dry-run] [-f|--force] [--json] [--package-lock-only] [--omit [--omit ...]] + [-w|--workspace [-w|--workspace ...]] + [-ws|--workspaces] Run "npm help audit" for more info @@ -309,6 +311,8 @@ All commands: [--global-style] [--legacy-bundling] [--strict-peer-deps] [--package-lock] [--omit [--omit ...]] [--ignore-scripts] [--audit] [--bin-links] [--fund] [--dry-run] + [-w|--workspace [-w|--workspace ...]] + [-ws|--workspaces] alias: ddp @@ -459,6 +463,8 @@ All commands: [--global-style] [--legacy-bundling] [--strict-peer-deps] [--package-lock] [--omit [--omit ...]] [--ignore-scripts] [--audit] [--bin-links] [--fund] + [-w|--workspace [-w|--workspace ...]] + [-ws|--workspaces] Run "npm help find-dupes" for more info @@ -554,6 +560,8 @@ All commands: [--strict-peer-deps] [--package-lock] [--omit [--omit ...]] [--ignore-scripts] [--audit] [--bin-links] [--fund] [--dry-run] + [-w|--workspace [-w|--workspace ...]] + [-ws|--workspaces] aliases: i, in, ins, inst, insta, instal, isnt, isnta, isntal, add @@ -595,6 +603,8 @@ All commands: [--strict-peer-deps] [--package-lock] [--omit [--omit ...]] [--ignore-scripts] [--audit] [--bin-links] [--fund] [--dry-run] + [-w|--workspace [-w|--workspace ...]] + [-ws|--workspaces] alias: it @@ -783,7 +793,8 @@ All commands: Options: [--omit [--omit ...]] [--dry-run] - [--json] + [--json] [-w|--workspace [-w|--workspace ...]] + [-ws|--workspaces] Run "npm help prune" for more info @@ -810,6 +821,8 @@ All commands: Options: [-g|--global] [--bin-links] [--ignore-scripts] + [-w|--workspace [-w|--workspace ...]] + [-ws|--workspaces] alias: rb @@ -1018,6 +1031,8 @@ All commands: Options: [-S|--save|--no-save|--save-prod|--save-dev|--save-optional|--save-peer] + [-w|--workspace [-w|--workspace ...]] + [-ws|--workspaces] aliases: un, unlink, remove, rm, r @@ -1058,6 +1073,8 @@ All commands: [-g|--global] [--global-style] [--legacy-bundling] [--strict-peer-deps] [--package-lock] [--omit [--omit ...]] [--ignore-scripts] [--audit] [--bin-links] [--fund] [--dry-run] + [-w|--workspace [-w|--workspace ...]] + [-ws|--workspaces] aliases: up, upgrade, udpate diff --git a/test/lib/update.js b/test/lib/update.js index 5396397d520cf..411d07592a155 100644 --- a/test/lib/update.js +++ b/test/lib/update.js @@ -37,7 +37,12 @@ t.test('no args', t => { constructor (args) { t.same( args, - { ...npm.flatOptions, path: npm.prefix, log: noop }, + { + ...npm.flatOptions, + path: npm.prefix, + log: noop, + workspaces: null, + }, 'should call arborist contructor with expected args' ) } @@ -71,7 +76,12 @@ t.test('with args', t => { constructor (args) { t.same( args, - { ...npm.flatOptions, path: npm.prefix, log: noop }, + { + ...npm.flatOptions, + path: npm.prefix, + log: noop, + workspaces: null, + }, 'should call arborist contructor with expected args' ) } @@ -139,7 +149,7 @@ t.test('update --global', t => { const { path, ...opts } = args t.same( opts, - { ...npm.flatOptions, log: noop }, + { ...npm.flatOptions, log: noop, workspaces: undefined }, 'should call arborist contructor with expected options' ) diff --git a/test/lib/workspaces/arborist-cmd.js b/test/lib/workspaces/arborist-cmd.js index cceeb68dbd42a..740ddb1ff0dc5 100644 --- a/test/lib/workspaces/arborist-cmd.js +++ b/test/lib/workspaces/arborist-cmd.js @@ -107,3 +107,19 @@ t.test('arborist-cmd', async t => { cmd.execWorkspaces([], ['./group'], res) }) }) + +t.test('handle getWorkspaces raising an error', t => { + const ArboristCmd = t.mock('../../../lib/workspaces/arborist-cmd.js', { + '../../../lib/workspaces/get-workspaces.js': async () => { + throw new Error('oopsie') + }, + }) + class TestCmd extends ArboristCmd {} + const cmd = new TestCmd() + cmd.npm = {} + + cmd.execWorkspaces(['foo'], ['a'], er => { + t.match(er, { message: 'oopsie' }) + t.end() + }) +})