From 47ad448defab6e8082824899b802b5c04ab2c919 Mon Sep 17 00:00:00 2001 From: npm-robot Date: Mon, 31 May 2021 23:00:00 +0000 Subject: [PATCH] deps: upgrade npm to 7.15.1 PR-URL: https://github.com/nodejs/node/pull/38880 Reviewed-By: Myles Borins Reviewed-By: Rich Trott Reviewed-By: Ruy Adorno --- deps/npm/AUTHORS | 6 + deps/npm/CHANGELOG.md | 87 +++++++++ deps/npm/docs/content/commands/npm-link.md | 42 +++++ deps/npm/docs/content/commands/npm-pack.md | 9 + deps/npm/docs/content/commands/npm.md | 6 +- .../configuring-npm/package-lock-json.md | 4 +- deps/npm/docs/content/using-npm/scripts.md | 2 +- deps/npm/docs/output/commands/npm-link.html | 36 +++- deps/npm/docs/output/commands/npm-ls.html | 2 +- deps/npm/docs/output/commands/npm-pack.html | 9 +- deps/npm/docs/output/commands/npm.html | 8 +- .../configuring-npm/package-lock-json.html | 4 +- deps/npm/docs/output/using-npm/scripts.html | 2 +- deps/npm/lib/base-command.js | 1 + deps/npm/lib/diff.js | 8 +- deps/npm/lib/dist-tag.js | 14 +- deps/npm/lib/exec.js | 2 +- deps/npm/lib/init.js | 7 +- deps/npm/lib/link.js | 11 +- deps/npm/lib/ls.js | 12 +- deps/npm/lib/owner.js | 19 +- deps/npm/lib/publish.js | 22 ++- deps/npm/lib/utils/completion.sh | 17 +- ...-local-package.js => read-package-name.js} | 7 +- deps/npm/lib/utils/reify-output.js | 34 +++- deps/npm/lib/workspaces/arborist-cmd.js | 1 + deps/npm/man/man1/npm-link.1 | 52 ++++++ deps/npm/man/man1/npm-ls.1 | 2 +- deps/npm/man/man1/npm-pack.1 | 12 ++ deps/npm/man/man1/npm.1 | 8 +- deps/npm/man/man5/package-lock-json.5 | 4 +- deps/npm/man/man7/scripts.7 | 2 +- .../node_modules/@npmcli/arborist/lib/diff.js | 20 +- .../@npmcli/arborist/lib/shrinkwrap.js | 7 +- .../@npmcli/arborist/package.json | 2 +- deps/npm/node_modules/cacache/README.md | 17 +- deps/npm/node_modules/cacache/get.js | 56 +++--- .../node_modules/cacache/lib/content/read.js | 60 +++--- .../node_modules/cacache/lib/content/rm.js | 5 +- .../node_modules/cacache/lib/content/write.js | 33 ++-- .../node_modules/cacache/lib/entry-index.js | 122 ++++++++----- .../node_modules/cacache/lib/memoization.js | 11 +- .../node_modules/cacache/lib/util/disposer.js | 4 +- .../cacache/lib/util/fix-owner.js | 21 +-- .../cacache/lib/util/move-file.js | 8 +- deps/npm/node_modules/cacache/lib/verify.js | 34 ++-- deps/npm/node_modules/cacache/package.json | 38 ++-- deps/npm/node_modules/cacache/put.js | 19 +- deps/npm/node_modules/cacache/rm.js | 4 +- .../is-core-module/.github/FUNDING.yml | 12 -- .../.github/workflows/node-4+.yml | 54 ------ .../.github/workflows/node-iojs.yml | 58 ------ .../.github/workflows/node-pretest.yml | 26 --- .../.github/workflows/node-zero.yml | 58 ------ .../.github/workflows/rebase.yml | 15 -- .../.github/workflows/require-allow-edits.yml | 14 -- deps/npm/node_modules/is-core-module/.nycrc | 4 - .../node_modules/is-core-module/CHANGELOG.md | 25 +++ .../npm/node_modules/is-core-module/README.md | 9 +- .../npm/node_modules/is-core-module/core.json | 87 +++++++-- .../node_modules/is-core-module/package.json | 14 +- .../node_modules/is-core-module/test/index.js | 25 +++ deps/npm/node_modules/libnpmexec/CHANGELOG.md | 16 ++ deps/npm/node_modules/libnpmexec/README.md | 2 +- deps/npm/node_modules/libnpmexec/lib/index.js | 3 +- .../node_modules/libnpmexec/lib/is-windows.js | 1 + deps/npm/node_modules/libnpmexec/package.json | 2 +- .../{README.markdown => readme.markdown} | 0 .../npm-audit-report/CHANGELOG.md | 81 --------- .../npm-audit-report/lib/index.js | 4 +- .../npm-audit-report/package.json | 6 +- .../retry/{Readme.md => README.md} | 2 +- deps/npm/package.json | 12 +- .../test/lib/dist-tag.js.test.cjs | 57 +++++- .../tap-snapshots/test/lib/init.js.test.cjs | 19 +- .../tap-snapshots/test/lib/link.js.test.cjs | 15 ++ .../test/lib/load-all-commands.js.test.cjs | 2 + .../npm/tap-snapshots/test/lib/ls.js.test.cjs | 46 ++--- .../test/lib/publish.js.test.cjs | 34 ++++ .../test/lib/utils/npm-usage.js.test.cjs | 2 + deps/npm/test/fixtures/mock-npm.js | 65 ++++--- deps/npm/test/lib/diff.js | 62 ++++--- deps/npm/test/lib/dist-tag.js | 14 ++ deps/npm/test/lib/exec.js | 24 ++- deps/npm/test/lib/init.js | 20 +- deps/npm/test/lib/link.js | 172 ++++++++++++++++++ deps/npm/test/lib/ls.js | 7 +- deps/npm/test/lib/owner.js | 100 +++++++--- deps/npm/test/lib/publish.js | 145 +++++++++++++++ ...-local-package.js => read-package-name.js} | 25 +-- deps/npm/test/lib/utils/reify-output.js | 165 ++++++++++++++--- 91 files changed, 1604 insertions(+), 813 deletions(-) rename deps/npm/lib/utils/{read-local-package.js => read-package-name.js} (56%) delete mode 100644 deps/npm/node_modules/is-core-module/.github/FUNDING.yml delete mode 100644 deps/npm/node_modules/is-core-module/.github/workflows/node-4+.yml delete mode 100644 deps/npm/node_modules/is-core-module/.github/workflows/node-iojs.yml delete mode 100644 deps/npm/node_modules/is-core-module/.github/workflows/node-pretest.yml delete mode 100644 deps/npm/node_modules/is-core-module/.github/workflows/node-zero.yml delete mode 100644 deps/npm/node_modules/is-core-module/.github/workflows/rebase.yml delete mode 100644 deps/npm/node_modules/is-core-module/.github/workflows/require-allow-edits.yml create mode 100644 deps/npm/node_modules/libnpmexec/CHANGELOG.md create mode 100644 deps/npm/node_modules/libnpmexec/lib/is-windows.js rename deps/npm/node_modules/mkdirp/{README.markdown => readme.markdown} (100%) delete mode 100644 deps/npm/node_modules/npm-audit-report/CHANGELOG.md rename deps/npm/node_modules/retry/{Readme.md => README.md} (99%) rename deps/npm/test/lib/utils/{read-local-package.js => read-package-name.js} (55%) diff --git a/deps/npm/AUTHORS b/deps/npm/AUTHORS index 723042e7799046..a8dfd8b6be682a 100644 --- a/deps/npm/AUTHORS +++ b/deps/npm/AUTHORS @@ -777,3 +777,9 @@ wangsai Luke Hefson mrmlnc Juan Picado +Kevin Cormier +Nariyasu Heseri +rethab +Spencer Wilson <5624115+spencerwilson@users.noreply.github.com> +Daniel Park +Daniel Park diff --git a/deps/npm/CHANGELOG.md b/deps/npm/CHANGELOG.md index 6f9c2d48d3e397..c86373bcde2b84 100644 --- a/deps/npm/CHANGELOG.md +++ b/deps/npm/CHANGELOG.md @@ -1,3 +1,90 @@ +## v7.15.1 (2021-05-31) + +### BUG FIXES + +* [`598a17a26`](https://github.com/npm/cli/commit/598a17a2671c9e3bc204dddd6488169c9a72c6a1) + [#3329](https://github.com/npm/cli/issues/3329) + fix(libnpmexec): don't detach output from npm + ([@wraithgar](https://github.com/wraithgar)) + +### DEPENDENCIES + +* [`c4fc03e9e`](https://github.com/npm/cli/commit/c4fc03e9eb3a6386e8feacb67c19f0a1578dfe38) + `@npmcli/arborist@2.6.1` + * fixes reifying deps with mismatching version ranges between + actual and virtual trees +* [`9159fa62a`](https://github.com/npm/cli/commit/9159fa62a10dee09daef178fc7be161a02824004) + `libnpmexec@1.2.0` + +## v7.15.0 (2021-05-27) + +### FEATURES + +* [`399ff8cbc`](https://github.com/npm/cli/commit/399ff8cbccd5198f637518ccafa86c43bab47a4a) + [#3312](https://github.com/npm/cli/issues/3312) + feat(link): add workspace support + ([@isaacs](https://github.com/isaacs)) + +### BUG FIXES + +* [`46a9bcbcb`](https://github.com/npm/cli/commit/46a9bcbcb0bb2435dca6f45a61b8631f580c7f06) + [#3282](https://github.com/npm/cli/issues/3282) + fix(docs): proper postinstall script file name + ([@KevinFCormier](https://github.com/KevinFCormier)) +* [`83590d40f`](https://github.com/npm/cli/commit/83590d40f94347f21714dbd158b9ddcad9c82de9) + [#3272](https://github.com/npm/cli/issues/3272) + fix(ls): show relative paths from root + ([@isaacs](https://github.com/isaacs)) +* [`a574b518a`](https://github.com/npm/cli/commit/a574b518ae5b8f0664ed388cf1be6288d8c2e68d) + [#3304](https://github.com/npm/cli/issues/3304) + fix(completion): restore IFS even if `npm completion` returns error + ([@NariyasuHeseri](https://github.com/NariyasuHeseri)) +* [`554e8a5cd`](https://github.com/npm/cli/commit/554e8a5cd7034052a59a9ada31e4b8f73712211a) + [#3311](https://github.com/npm/cli/issues/3311) + set audit exit code properly + ([@isaacs](https://github.com/isaacs)) +* [`4a4fbe33c`](https://github.com/npm/cli/commit/4a4fbe33c51413adcd558b4af6f1e204b1b87e41) + [#3268](https://github.com/npm/cli/issues/3268) + [#3285](https://github.com/npm/cli/issues/3285) + fix(publish): skip private workspaces + ([@ruyadorno](https://github.com/ruyadorno)) + +### DOCUMENTATION + +* [`3c53d631f`](https://github.com/npm/cli/commit/3c53d631f557cf2484e2f6a6172c44e36aea4817) + [#3307](https://github.com/npm/cli/issues/3307) + fix(docs): typo in package-lock.json docs + ([@rethab](https://github.com/rethab)) +* [`96367f93f`](https://github.com/npm/cli/commit/96367f93f46c24494d084c8b8d34e4de9cd375da) + rebuild npm-pack doc + ([@isaacs](https://github.com/isaacs)) +* [`64b13dd10`](https://github.com/npm/cli/commit/64b13dd1082b6ca7eac4e8e329bfdd8cd8daf157) + [#3313](https://github.com/npm/cli/issues/3313) + Drop stale Python 3<->node-gyp remark + ([@spencerwilson](https://github.com/spencerwilson)) + +### DEPENDENCIES + +* [`7b56bfdf3`](https://github.com/npm/cli/commit/7b56bfdf3f2ac67a926fc7893b883a16b46eb3fd) + `cacache@15.2.0`: + * feat: allow fully deleting indices + * feat: add a validateEntry option to compact + * chore: lint + * chore: use standard npm style release scripts +* [`dbbc151a3`](https://github.com/npm/cli/commit/dbbc151a3bcf89e2627dc267063edd185ead1cb8) + `npm-audit-report@2.1.5`: + * fix(exit-code): account for null auditLevel default (#46) +* [`5b2604507`](https://github.com/npm/cli/commit/5b26045076477d3d350f539e60adf48a80376fda) + chore(package-lock): update devDependencies + ([@Gar](https://github.com/Gar)) + +### AUTOMATION + +* [`3d5df0082`](https://github.com/npm/cli/commit/3d5df0082ae904dacdea8644286e8362d4a2ed50) + [#3294](https://github.com/npm/cli/issues/3294) + chore(ci): move node release PR workflow to cli repo + ([@gimli01](https://github.com/gimli01)) + ## v7.14.0 (2021-05-20) ### FEATURES diff --git a/deps/npm/docs/content/commands/npm-link.md b/deps/npm/docs/content/commands/npm-link.md index e48be396ade1b1..b1c6066768a99e 100644 --- a/deps/npm/docs/content/commands/npm-link.md +++ b/deps/npm/docs/content/commands/npm-link.md @@ -99,6 +99,16 @@ relevant metadata by running `npm install --package-lock-only`. If you _want_ to save the `file:` reference in your `package.json` and `package-lock.json` files, you can use `npm link --save` to do so. +### Workspace Usage + +`npm link --workspace ` will link the relevant package as a +dependency of the specified workspace(s). Note that It may actually be +linked into the parent project's `node_modules` folder, if there are no +conflicting dependencies. + +`npm link --workspace ` will create a global link to the specified +workspace(s). + ### Configuration @@ -261,6 +271,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/deps/npm/docs/content/commands/npm-pack.md b/deps/npm/docs/content/commands/npm-pack.md index ff90bd74472b41..04a22a5d854b45 100644 --- a/deps/npm/docs/content/commands/npm-pack.md +++ b/deps/npm/docs/content/commands/npm-pack.md @@ -27,6 +27,15 @@ commands that modify your local installation, eg, `install`, `update`, Note: This is NOT honored by other network related commands, eg `dist-tags`, `owner`, etc. +#### `json` + +* Default: false +* Type: Boolean + +Whether or not to output JSON data, rather than the normal output. + +Not supported by all npm commands. + #### `workspace` * Default: diff --git a/deps/npm/docs/content/commands/npm.md b/deps/npm/docs/content/commands/npm.md index 2d86aa62c00807..7ff1cc490707ee 100644 --- a/deps/npm/docs/content/commands/npm.md +++ b/deps/npm/docs/content/commands/npm.md @@ -62,10 +62,8 @@ requires compiling of C++ Code, npm will use [node-gyp](https://github.com/nodejs/node-gyp) for that task. For a Unix system, [node-gyp](https://github.com/nodejs/node-gyp) needs Python, make and a buildchain like GCC. On Windows, -Python and Microsoft Visual Studio C++ are needed. Python 3 is -not supported by [node-gyp](https://github.com/nodejs/node-gyp). -For more information visit -[the node-gyp repository](https://github.com/nodejs/node-gyp) and +Python and Microsoft Visual Studio C++ are needed. For more information +visit [the node-gyp repository](https://github.com/nodejs/node-gyp) and the [node-gyp Wiki](https://github.com/nodejs/node-gyp/wiki). ### Directories diff --git a/deps/npm/docs/content/configuring-npm/package-lock-json.md b/deps/npm/docs/content/configuring-npm/package-lock-json.md index 4d994bbc8c0a28..9b126867b80fad 100644 --- a/deps/npm/docs/content/configuring-npm/package-lock-json.md +++ b/deps/npm/docs/content/configuring-npm/package-lock-json.md @@ -36,8 +36,8 @@ various purposes: Both of these files have the same format, and perform similar functions in the root of a project. -The difference is that `package-lock.json` is that it cannot be published, -and it will be ignored if found in any place other than the root project. +The difference is that `package-lock.json` cannot be published, and it will +be ignored if found in any place other than the root project. In contrast, [npm-shrinkwrap.json](/configuring-npm/npm-shrinkwrap-json) allows publication, and defines the dependency tree from the point encountered. diff --git a/deps/npm/docs/content/using-npm/scripts.md b/deps/npm/docs/content/using-npm/scripts.md index 82cde7d79094d4..3869334f6cc5ae 100644 --- a/deps/npm/docs/content/using-npm/scripts.md +++ b/deps/npm/docs/content/using-npm/scripts.md @@ -304,7 +304,7 @@ For example, if your package.json contains this: { "scripts" : { "install" : "scripts/install.js", - "postinstall" : "scripts/postinstall.js", + "postinstall" : "scripts/install.js", "uninstall" : "scripts/uninstall.js" } } diff --git a/deps/npm/docs/output/commands/npm-link.html b/deps/npm/docs/output/commands/npm-link.html index b897405030256c..d558cb9d0a535b 100644 --- a/deps/npm/docs/output/commands/npm-link.html +++ b/deps/npm/docs/output/commands/npm-link.html @@ -141,7 +141,7 @@

npm-link

Table of contents

- +

Synopsis

@@ -209,6 +209,13 @@

Caveat

relevant metadata by running npm install <dep> --package-lock-only.

If you want to save the file: reference in your package.json and package-lock.json files, you can use npm link <dep> --save to do so.

+

Workspace Usage

+

npm link <pkg> --workspace <name> will link the relevant package as a +dependency of the specified workspace(s). Note that It may actually be +linked into the parent project’s node_modules folder, if there are no +conflicting dependencies.

+

npm link --workspace <name> will create a global link to the specified +workspace(s).

Configuration

@@ -347,6 +354,33 @@

dry-run

dedupe, uninstall, as well as pack and publish.

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/deps/npm/docs/output/commands/npm-ls.html b/deps/npm/docs/output/commands/npm-ls.html index 29530b05d1f2df..f87185539dd6f7 100644 --- a/deps/npm/docs/output/commands/npm-ls.html +++ b/deps/npm/docs/output/commands/npm-ls.html @@ -159,7 +159,7 @@

    Description

    the results to only the paths to the packages named. Note that nested packages will also show the paths to the specified packages. For example, running npm ls promzard in npm’s source tree will show:

    -
    npm@7.14.0 /path/to/npm
    +
    npm@7.15.1 /path/to/npm
     └─┬ init-package-json@0.0.4
       └── promzard@0.1.5
     
    diff --git a/deps/npm/docs/output/commands/npm-pack.html b/deps/npm/docs/output/commands/npm-pack.html index 77535523cdb755..4380ff99b415c9 100644 --- a/deps/npm/docs/output/commands/npm-pack.html +++ b/deps/npm/docs/output/commands/npm-pack.html @@ -141,7 +141,7 @@

    npm-pack

    Table of contents

    - +

    Synopsis

    @@ -161,6 +161,13 @@

    dry-run

    dedupe, uninstall, as well as pack and publish.

    Note: This is NOT honored by other network related commands, eg dist-tags, owner, etc.

    +

    json

    +
      +
    • Default: false
    • +
    • Type: Boolean
    • +
    +

    Whether or not to output JSON data, rather than the normal output.

    +

    Not supported by all npm commands.

    workspace

    • Default:
    • diff --git a/deps/npm/docs/output/commands/npm.html b/deps/npm/docs/output/commands/npm.html index 454fabf303f62c..6469e96933a08e 100644 --- a/deps/npm/docs/output/commands/npm.html +++ b/deps/npm/docs/output/commands/npm.html @@ -148,7 +148,7 @@

      Table of contents

      npm <command> [args]
       

      Version

      -

      7.14.0

      +

      7.15.1

      Description

      npm is the package manager for the Node JavaScript platform. It puts modules in place so that node can find them, and manages dependency @@ -183,10 +183,8 @@

      Dependencies

      node-gyp for that task. For a Unix system, node-gyp needs Python, make and a buildchain like GCC. On Windows, -Python and Microsoft Visual Studio C++ are needed. Python 3 is -not supported by node-gyp. -For more information visit -the node-gyp repository and +Python and Microsoft Visual Studio C++ are needed. For more information +visit the node-gyp repository and the node-gyp Wiki.

      Directories

      See folders to learn about where npm puts diff --git a/deps/npm/docs/output/configuring-npm/package-lock-json.html b/deps/npm/docs/output/configuring-npm/package-lock-json.html index ce5e6525d9aab8..1e14f242bd6ee4 100644 --- a/deps/npm/docs/output/configuring-npm/package-lock-json.html +++ b/deps/npm/docs/output/configuring-npm/package-lock-json.html @@ -178,8 +178,8 @@

      Table of contents

      package-lock.json vs npm-shrinkwrap.json

      Both of these files have the same format, and perform similar functions in the root of a project.

      -

      The difference is that package-lock.json is that it cannot be published, -and it will be ignored if found in any place other than the root project.

      +

      The difference is that package-lock.json cannot be published, and it will +be ignored if found in any place other than the root project.

      In contrast, npm-shrinkwrap.json allows publication, and defines the dependency tree from the point encountered. This is not recommended unless deploying a CLI tool or otherwise using the diff --git a/deps/npm/docs/output/using-npm/scripts.html b/deps/npm/docs/output/using-npm/scripts.html index dde9b1b75d7194..2c3bb9460fea44 100644 --- a/deps/npm/docs/output/using-npm/scripts.html +++ b/deps/npm/docs/output/using-npm/scripts.html @@ -406,7 +406,7 @@

      Examples

      {
         "scripts" : {
           "install" : "scripts/install.js",
      -    "postinstall" : "scripts/postinstall.js",
      +    "postinstall" : "scripts/install.js",
           "uninstall" : "scripts/uninstall.js"
         }
       }
      diff --git a/deps/npm/lib/base-command.js b/deps/npm/lib/base-command.js
      index e1efcff5832b3c..843fb2d4b13586 100644
      --- a/deps/npm/lib/base-command.js
      +++ b/deps/npm/lib/base-command.js
      @@ -7,6 +7,7 @@ class BaseCommand {
           this.wrapWidth = 80
           this.npm = npm
           this.workspaces = null
      +    this.workspacePaths = null
         }
       
         get name () {
      diff --git a/deps/npm/lib/diff.js b/deps/npm/lib/diff.js
      index 1eaceb4f2f61f5..58834ca9c26746 100644
      --- a/deps/npm/lib/diff.js
      +++ b/deps/npm/lib/diff.js
      @@ -8,7 +8,7 @@ const npmlog = require('npmlog')
       const pacote = require('pacote')
       const pickManifest = require('npm-pick-manifest')
       
      -const readLocalPkg = require('./utils/read-local-package.js')
      +const readPackageName = require('./utils/read-package-name.js')
       const BaseCommand = require('./base-command.js')
       
       class Diff extends BaseCommand {
      @@ -97,7 +97,7 @@ class Diff extends BaseCommand {
           let noPackageJson
           let pkgName
           try {
      -      pkgName = await readLocalPkg(this.npm)
      +      pkgName = await readPackageName(this.npm.prefix)
           } catch (e) {
             npmlog.verbose('diff', 'could not read project dir package.json')
             noPackageJson = true
      @@ -120,7 +120,7 @@ class Diff extends BaseCommand {
           let noPackageJson
           let pkgName
           try {
      -      pkgName = await readLocalPkg(this.npm)
      +      pkgName = await readPackageName(this.npm.prefix)
           } catch (e) {
             npmlog.verbose('diff', 'could not read project dir package.json')
             noPackageJson = true
      @@ -238,7 +238,7 @@ class Diff extends BaseCommand {
           if (semverA && semverB) {
             let pkgName
             try {
      -        pkgName = await readLocalPkg(this.npm)
      +        pkgName = await readPackageName(this.npm.prefix)
             } catch (e) {
               npmlog.verbose('diff', 'could not read project dir package.json')
             }
      diff --git a/deps/npm/lib/dist-tag.js b/deps/npm/lib/dist-tag.js
      index 64e8abc0137454..11b1ad931e18b9 100644
      --- a/deps/npm/lib/dist-tag.js
      +++ b/deps/npm/lib/dist-tag.js
      @@ -4,7 +4,7 @@ const regFetch = require('npm-registry-fetch')
       const semver = require('semver')
       
       const otplease = require('./utils/otplease.js')
      -const readLocalPkgName = require('./utils/read-local-package.js')
      +const readPackageName = require('./utils/read-package-name.js')
       const getWorkspaces = require('./workspaces/get-workspaces.js')
       const BaseCommand = require('./base-command.js')
       
      @@ -64,7 +64,7 @@ class DistTag extends BaseCommand {
             // should be listing the existing tags
             return this.list(cmdName, opts)
           } else
      -      throw this.usage
      +      throw this.usageError()
         }
       
         execWorkspaces (args, filters, cb) {
      @@ -102,7 +102,7 @@ class DistTag extends BaseCommand {
           log.verbose('dist-tag add', defaultTag, 'to', spec.name + '@' + version)
       
           if (!spec.name || !version || !defaultTag)
      -      throw this.usage
      +      throw this.usageError()
       
           const t = defaultTag.trim()
       
      @@ -135,7 +135,7 @@ class DistTag extends BaseCommand {
           log.verbose('dist-tag del', tag, 'from', spec.name)
       
           if (!spec.name)
      -      throw this.usage
      +      throw this.usageError()
       
           const tags = await this.fetchTags(spec, opts)
           if (!tags[tag]) {
      @@ -157,9 +157,11 @@ class DistTag extends BaseCommand {
       
         async list (spec, opts) {
           if (!spec) {
      -      const pkg = await readLocalPkgName(this.npm)
      +      if (this.npm.config.get('global'))
      +        throw this.usageError()
      +      const pkg = await readPackageName(this.npm.prefix)
             if (!pkg)
      -        throw this.usage
      +        throw this.usageError()
       
             return this.list(pkg, opts)
           }
      diff --git a/deps/npm/lib/exec.js b/deps/npm/lib/exec.js
      index f30746b8c50eda..8a87615d9749ee 100644
      --- a/deps/npm/lib/exec.js
      +++ b/deps/npm/lib/exec.js
      @@ -76,8 +76,8 @@ class Exec extends BaseCommand {
             localBin,
             log,
             globalBin,
      -      output,
           } = this.npm
      +    const output = (...outputArgs) => this.npm.output(...outputArgs)
           const scriptShell = this.npm.config.get('script-shell') || undefined
           const packages = this.npm.config.get('package')
           const yes = this.npm.config.get('yes')
      diff --git a/deps/npm/lib/init.js b/deps/npm/lib/init.js
      index bc809a15e49a9f..4dd091601e1915 100644
      --- a/deps/npm/lib/init.js
      +++ b/deps/npm/lib/init.js
      @@ -113,8 +113,13 @@ class Init extends BaseCommand {
             localBin,
             log,
             globalBin,
      -      output,
           } = this.npm
      +    // this function is definitely called.  But because of coverage map stuff
      +    // it ends up both uncovered, and the coverage report doesn't even mention.
      +    // the tests do assert that some output happens, so we know this line is
      +    // being hit.
      +    /* istanbul ignore next */
      +    const output = (...outputArgs) => this.npm.output(...outputArgs)
           const locationMsg = await getLocationMsg({ color, path })
           const runPath = path
           const scriptShell = this.npm.config.get('script-shell') || undefined
      diff --git a/deps/npm/lib/link.js b/deps/npm/lib/link.js
      index 60665a9964fab4..47fe4b17a272b9 100644
      --- a/deps/npm/lib/link.js
      +++ b/deps/npm/lib/link.js
      @@ -10,8 +10,8 @@ const semver = require('semver')
       
       const reifyFinish = require('./utils/reify-finish.js')
       
      -const BaseCommand = require('./base-command.js')
      -class Link extends BaseCommand {
      +const ArboristWorkspaceCmd = require('./workspaces/arborist-cmd.js')
      +class Link extends ArboristWorkspaceCmd {
         /* istanbul ignore next - see test/lib/load-all-commands.js */
         static get description () {
           return 'Symlink a package folder'
      @@ -46,6 +46,7 @@ class Link extends BaseCommand {
             'bin-links',
             'fund',
             'dry-run',
      +      ...super.params,
           ]
         }
       
      @@ -143,12 +144,16 @@ class Link extends BaseCommand {
             log: this.npm.log,
             add: names.map(l => `file:${resolve(globalTop, 'node_modules', l)}`),
             save,
      +      workspaces: this.workspaces,
           })
       
           await reifyFinish(this.npm, localArb)
         }
       
         async linkPkg () {
      +    const wsp = this.workspacePaths
      +    const paths = wsp && wsp.length ? wsp : [this.npm.prefix]
      +    const add = paths.map(path => `file:${path}`)
           const globalTop = resolve(this.npm.globalDir, '..')
           const arb = new Arborist({
             ...this.npm.flatOptions,
      @@ -157,7 +162,7 @@ class Link extends BaseCommand {
             global: true,
           })
           await arb.reify({
      -      add: [`file:${this.npm.prefix}`],
      +      add,
             log: this.npm.log,
           })
           await reifyFinish(this.npm, arb)
      diff --git a/deps/npm/lib/ls.js b/deps/npm/lib/ls.js
      index 4e504912a01751..d92b73ddfcdbb1 100644
      --- a/deps/npm/lib/ls.js
      +++ b/deps/npm/lib/ls.js
      @@ -1,4 +1,5 @@
      -const { resolve } = require('path')
      +const { resolve, relative, sep } = require('path')
      +const relativePrefix = `.${sep}`
       const { EOL } = require('os')
       
       const archy = require('archy')
      @@ -298,6 +299,9 @@ const getHumanOutputItem = (node, { args, color, global, long }) => {
           ? chalk.yellow.bgBlack
           : chalk.red.bgBlack
         const missingMsg = `UNMET ${isOptional(node) ? 'OPTIONAL ' : ''}DEPENDENCY`
      +  const targetLocation = node.root
      +    ? relative(node.root.realpath, node.realpath)
      +    : node.targetLocation
         const label =
           (
             node[_missing]
      @@ -321,7 +325,7 @@ const getHumanOutputItem = (node, { args, color, global, long }) => {
               : ''
           ) +
           (isGitNode(node) ? ` (${node.resolved})` : '') +
      -    (node.isLink ? ` -> ${node.realpath}` : '') +
      +    (node.isLink ? ` -> ${relativePrefix}${targetLocation}` : '') +
           (long ? `${EOL}${node.package.description || ''}` : '')
       
         return augmentItemWithIncludeMetadata(node, { label, nodes: [] })
      @@ -445,6 +449,9 @@ const augmentNodesWithMetadata = ({
         // revisit that node in tree traversal logic, so we make it so that
         // we have a diff obj for deduped nodes:
         if (seenNodes.has(node.path)) {
      +    const { realpath, root } = node
      +    const targetLocation = root ? relative(root.realpath, realpath)
      +      : node.targetLocation
           node = {
             name: node.name,
             version: node.version,
      @@ -453,6 +460,7 @@ const augmentNodesWithMetadata = ({
             path: node.path,
             isLink: node.isLink,
             realpath: node.realpath,
      +      targetLocation,
             [_type]: node[_type],
             [_invalid]: node[_invalid],
             [_missing]: node[_missing],
      diff --git a/deps/npm/lib/owner.js b/deps/npm/lib/owner.js
      index e57d2268d2619f..311b25064e6383 100644
      --- a/deps/npm/lib/owner.js
      +++ b/deps/npm/lib/owner.js
      @@ -4,7 +4,7 @@ const npmFetch = require('npm-registry-fetch')
       const pacote = require('pacote')
       
       const otplease = require('./utils/otplease.js')
      -const readLocalPkg = require('./utils/read-local-package.js')
      +const readLocalPkgName = require('./utils/read-package-name.js')
       const BaseCommand = require('./base-command.js')
       
       class Owner extends BaseCommand {
      @@ -47,7 +47,9 @@ class Owner extends BaseCommand {
       
           // reaches registry in order to autocomplete rm
           if (argv[2] === 'rm') {
      -      const pkgName = await readLocalPkg(this.npm)
      +      if (this.npm.config.get('global'))
      +        return []
      +      const pkgName = await readLocalPkgName(this.npm.prefix)
             if (!pkgName)
               return []
       
      @@ -84,7 +86,10 @@ class Owner extends BaseCommand {
       
         async ls (pkg, opts) {
           if (!pkg) {
      -      const pkgName = await readLocalPkg(this.npm)
      +      if (this.npm.config.get('global'))
      +        throw this.usageError()
      +
      +      const pkgName = await readLocalPkgName(this.npm.prefix)
             if (!pkgName)
               throw this.usageError()
       
      @@ -113,7 +118,9 @@ class Owner extends BaseCommand {
             throw this.usageError()
       
           if (!pkg) {
      -      const pkgName = await readLocalPkg(this.npm)
      +      if (this.npm.config.get('global'))
      +        throw this.usageError()
      +      const pkgName = await readLocalPkgName(this.npm.prefix)
             if (!pkgName)
               throw this.usageError()
       
      @@ -131,7 +138,9 @@ class Owner extends BaseCommand {
             throw this.usageError()
       
           if (!pkg) {
      -      const pkgName = await readLocalPkg(this.npm)
      +      if (this.npm.config.get('global'))
      +        throw this.usageError()
      +      const pkgName = await readLocalPkgName(this.npm.prefix)
             if (!pkgName)
               throw this.usageError()
       
      diff --git a/deps/npm/lib/publish.js b/deps/npm/lib/publish.js
      index 1693ea7d97c2a3..3cb8b0627e974b 100644
      --- a/deps/npm/lib/publish.js
      +++ b/deps/npm/lib/publish.js
      @@ -7,6 +7,7 @@ const runScript = require('@npmcli/run-script')
       const pacote = require('pacote')
       const npa = require('npm-package-arg')
       const npmFetch = require('npm-registry-fetch')
      +const chalk = require('chalk')
       
       const otplease = require('./utils/otplease.js')
       const { getContents, logTar } = require('./utils/tar.js')
      @@ -154,10 +155,29 @@ class Publish extends BaseCommand {
           const results = {}
           const json = this.npm.config.get('json')
           const silent = log.level === 'silent'
      +    const noop = a => a
      +    const color = this.npm.color ? chalk : { green: noop, bold: noop }
           const workspaces =
             await getWorkspaces(filters, { path: this.npm.localPrefix })
      +
           for (const [name, workspace] of workspaces.entries()) {
      -      const pkgContents = await this.publish([workspace])
      +      let pkgContents
      +      try {
      +        pkgContents = await this.publish([workspace])
      +      } catch (err) {
      +        if (err.code === 'EPRIVATE') {
      +          log.warn(
      +            'publish',
      +            `Skipping workspace ${
      +              color.green(name)
      +            }, marked as ${
      +              color.bold('private')
      +            }`
      +          )
      +          continue
      +        }
      +        throw err
      +      }
             // This needs to be in-line w/ the rest of the output that non-JSON
             // publish generates
             if (!silent && !json)
      diff --git a/deps/npm/lib/utils/completion.sh b/deps/npm/lib/utils/completion.sh
      index c549b31c964931..a3e5143991edd0 100755
      --- a/deps/npm/lib/utils/completion.sh
      +++ b/deps/npm/lib/utils/completion.sh
      @@ -18,11 +18,15 @@ if type complete &>/dev/null; then
           fi
       
           local si="$IFS"
      -    IFS=$'\n' COMPREPLY=($(COMP_CWORD="$cword" \
      +    if ! IFS=$'\n' COMPREPLY=($(COMP_CWORD="$cword" \
                                  COMP_LINE="$COMP_LINE" \
                                  COMP_POINT="$COMP_POINT" \
                                  npm completion -- "${words[@]}" \
      -                           2>/dev/null)) || return $?
      +                           2>/dev/null)); then
      +      local ret=$?
      +      IFS="$si"
      +      return $ret
      +    fi
           IFS="$si"
           if type __ltrim_colon_completions &>/dev/null; then
             __ltrim_colon_completions "${words[cword]}"
      @@ -49,11 +53,16 @@ elif type compctl &>/dev/null; then
           read -l line
           read -ln point
           si="$IFS"
      -    IFS=$'\n' reply=($(COMP_CWORD="$cword" \
      +    if ! IFS=$'\n' reply=($(COMP_CWORD="$cword" \
                              COMP_LINE="$line" \
                              COMP_POINT="$point" \
                              npm completion -- "${words[@]}" \
      -                       2>/dev/null)) || return $?
      +                       2>/dev/null)); then
      +
      +      local ret=$?
      +      IFS="$si"
      +      return $ret
      +    fi
           IFS="$si"
         }
         compctl -K _npm_completion npm
      diff --git a/deps/npm/lib/utils/read-local-package.js b/deps/npm/lib/utils/read-package-name.js
      similarity index 56%
      rename from deps/npm/lib/utils/read-local-package.js
      rename to deps/npm/lib/utils/read-package-name.js
      index 21506ca180a0f3..7ed15987767bb4 100644
      --- a/deps/npm/lib/utils/read-local-package.js
      +++ b/deps/npm/lib/utils/read-package-name.js
      @@ -1,10 +1,7 @@
       const { resolve } = require('path')
       const readJson = require('read-package-json-fast')
      -async function readLocalPackageName (npm) {
      -  if (npm.config.get('global'))
      -    return
      -
      -  const filepath = resolve(npm.prefix, 'package.json')
      +async function readLocalPackageName (prefix) {
      +  const filepath = resolve(prefix, 'package.json')
         const json = await readJson(filepath)
         return json.name
       }
      diff --git a/deps/npm/lib/utils/reify-output.js b/deps/npm/lib/utils/reify-output.js
      index ddad32121e8b45..bf3fa7fb2e13d8 100644
      --- a/deps/npm/lib/utils/reify-output.js
      +++ b/deps/npm/lib/utils/reify-output.js
      @@ -18,10 +18,6 @@ const auditError = require('./audit-error.js')
       
       // TODO: output JSON if flatOptions.json is true
       const reifyOutput = (npm, arb) => {
      -  // don't print any info in --silent mode
      -  if (log.levels[log.level] > log.levels.error)
      -    return
      -
         const { diff, actualTree } = arb
       
         // note: fails and crashes if we're running audit fix and there was an error
      @@ -29,6 +25,13 @@ const reifyOutput = (npm, arb) => {
         // stuff in that case!
         const auditReport = auditError(npm, arb.auditReport) ? null : arb.auditReport
       
      +  // don't print any info in --silent mode, but we still need to
      +  // set the exitCode properly from the audit report, if we have one.
      +  if (log.levels[log.level] > log.levels.error) {
      +    getAuditReport(npm, auditReport)
      +    return
      +  }
      +
         const summary = {
           added: 0,
           removed: 0,
      @@ -68,6 +71,8 @@ const reifyOutput = (npm, arb) => {
       
         if (npm.flatOptions.json) {
           if (auditReport) {
      +      // call this to set the exit code properly
      +      getAuditReport(npm, auditReport)
             summary.audit = npm.command === 'audit' ? auditReport
               : auditReport.toJSON().metadata
           }
      @@ -83,11 +88,25 @@ const reifyOutput = (npm, arb) => {
       // at the end if there's still stuff, because it's silly for `npm audit`
       // to tell you to run `npm audit` for details.  otherwise, use the summary
       // report.  if we get here, we know it's not quiet or json.
      +// If the loglevel is set higher than 'error', then we just run the report
      +// to get the exitCode set appropriately.
       const printAuditReport = (npm, report) => {
      +  const res = getAuditReport(npm, report)
      +  if (!res || !res.report)
      +    return
      +  npm.output(`\n${res.report}`)
      +}
      +
      +const getAuditReport = (npm, report) => {
         if (!report)
           return
       
      -  const reporter = npm.command !== 'audit' ? 'install' : 'detail'
      +  // when in silent mode, we print nothing.  the JSON output is
      +  // going to just JSON.stringify() the report object.
      +  const reporter = log.levels[log.level] > log.levels.error ? 'quiet'
      +    : npm.flatOptions.json ? 'quiet'
      +    : npm.command !== 'audit' ? 'install'
      +    : 'detail'
         const defaultAuditLevel = npm.command !== 'audit' ? 'none' : 'low'
         const auditLevel = npm.flatOptions.auditLevel || defaultAuditLevel
       
      @@ -96,8 +115,9 @@ const printAuditReport = (npm, report) => {
           ...npm.flatOptions,
           auditLevel,
         })
      -  process.exitCode = process.exitCode || res.exitCode
      -  npm.output('\n' + res.report)
      +  if (npm.command === 'audit')
      +    process.exitCode = process.exitCode || res.exitCode
      +  return res
       }
       
       const packagesChangedMessage = (npm, { added, removed, changed, audited }) => {
      diff --git a/deps/npm/lib/workspaces/arborist-cmd.js b/deps/npm/lib/workspaces/arborist-cmd.js
      index b12c0ee47b19f0..337e7f9d8f9321 100644
      --- a/deps/npm/lib/workspaces/arborist-cmd.js
      +++ b/deps/npm/lib/workspaces/arborist-cmd.js
      @@ -17,6 +17,7 @@ class ArboristCmd extends BaseCommand {
           getWorkspaces(filters, { path: this.npm.localPrefix })
             .then(workspaces => {
               this.workspaces = [...workspaces.keys()]
      +        this.workspacePaths = [...workspaces.values()]
               this.exec(args, cb)
             })
             .catch(er => cb(er))
      diff --git a/deps/npm/man/man1/npm-link.1 b/deps/npm/man/man1/npm-link.1
      index 18feec2632138b..822e8851633c9d 100644
      --- a/deps/npm/man/man1/npm-link.1
      +++ b/deps/npm/man/man1/npm-link.1
      @@ -103,6 +103,15 @@ relevant metadata by running \fBnpm install  \-\-package\-lock\-only\fP\|\.
       .P
       If you \fIwant\fR to save the \fBfile:\fP reference in your \fBpackage\.json\fP and
       \fBpackage\-lock\.json\fP files, you can use \fBnpm link  \-\-save\fP to do so\.
      +.SS Workspace Usage
      +.P
      +\fBnpm link  \-\-workspace \fP will link the relevant package as a
      +dependency of the specified workspace(s)\.  Note that It may actually be
      +linked into the parent project's \fBnode_modules\fP folder, if there are no
      +conflicting dependencies\.
      +.P
      +\fBnpm link \-\-workspace \fP will create a global link to the specified
      +workspace(s)\.
       .SS Configuration
       
       
      @@ -308,6 +317,49 @@ commands that modify your local installation, eg, \fBinstall\fP, \fBupdate\fP,
       .P
       Note: This is NOT honored by other network related commands, eg \fBdist\-tags\fP,
       \fBowner\fP, etc\.
      +.SS \fBworkspace\fP
      +.RS 0
      +.IP \(bu 2
      +Default:
      +.IP \(bu 2
      +Type: String (can be set multiple times)
      +
      +.RE
      +.P
      +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\.
      +.P
      +Valid values for the \fBworkspace\fP config are either:
      +.RS 0
      +.IP \(bu 2
      +Workspace names
      +.IP \(bu 2
      +Path to a workspace directory
      +.IP \(bu 2
      +Path to a parent workspace directory (will result to selecting all of the
      +nested workspaces)
      +
      +.RE
      +.P
      +When set for the \fBnpm init\fP 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\.
      +.P
      +This value is not exported to the environment for child processes\.
      +.SS \fBworkspaces\fP
      +.RS 0
      +.IP \(bu 2
      +Default: false
      +.IP \(bu 2
      +Type: Boolean
      +
      +.RE
      +.P
      +Enable running a command in the context of \fBall\fR the configured
      +workspaces\.
      +.P
      +This value is not exported to the environment for child processes\.
       
       
       .SS See Also
      diff --git a/deps/npm/man/man1/npm-ls.1 b/deps/npm/man/man1/npm-ls.1
      index a0098530c3fffa..4821c0d9779078 100644
      --- a/deps/npm/man/man1/npm-ls.1
      +++ b/deps/npm/man/man1/npm-ls.1
      @@ -26,7 +26,7 @@ example, running \fBnpm ls promzard\fP in npm's source tree will show:
       .P
       .RS 2
       .nf
      -npm@7\.14\.0 /path/to/npm
      +npm@7\.15\.1 /path/to/npm
       └─┬ init\-package\-json@0\.0\.4
         └── promzard@0\.1\.5
       .fi
      diff --git a/deps/npm/man/man1/npm-pack.1 b/deps/npm/man/man1/npm-pack.1
      index f120e865729782..f94c0482390b95 100644
      --- a/deps/npm/man/man1/npm-pack.1
      +++ b/deps/npm/man/man1/npm-pack.1
      @@ -27,6 +27,18 @@ commands that modify your local installation, eg, \fBinstall\fP, \fBupdate\fP,
       .P
       Note: This is NOT honored by other network related commands, eg \fBdist\-tags\fP,
       \fBowner\fP, etc\.
      +.SS \fBjson\fP
      +.RS 0
      +.IP \(bu 2
      +Default: false
      +.IP \(bu 2
      +Type: Boolean
      +
      +.RE
      +.P
      +Whether or not to output JSON data, rather than the normal output\.
      +.P
      +Not supported by all npm commands\.
       .SS \fBworkspace\fP
       .RS 0
       .IP \(bu 2
      diff --git a/deps/npm/man/man1/npm.1 b/deps/npm/man/man1/npm.1
      index ab9917f1d68947..17b8d38663c14e 100644
      --- a/deps/npm/man/man1/npm.1
      +++ b/deps/npm/man/man1/npm.1
      @@ -10,7 +10,7 @@ npm  [args]
       .RE
       .SS Version
       .P
      -7\.14\.0
      +7\.15\.1
       .SS Description
       .P
       npm is the package manager for the Node JavaScript platform\.  It puts
      @@ -56,10 +56,8 @@ requires compiling of C++ Code, npm will use
       node\-gyp \fIhttps://github\.com/nodejs/node\-gyp\fR for that task\.
       For a Unix system, node\-gyp \fIhttps://github\.com/nodejs/node\-gyp\fR
       needs Python, make and a buildchain like GCC\. On Windows,
      -Python and Microsoft Visual Studio C++ are needed\. Python 3 is
      -not supported by node\-gyp \fIhttps://github\.com/nodejs/node\-gyp\fR\|\.
      -For more information visit
      -the node\-gyp repository \fIhttps://github\.com/nodejs/node\-gyp\fR and
      +Python and Microsoft Visual Studio C++ are needed\. For more information
      +visit the node\-gyp repository \fIhttps://github\.com/nodejs/node\-gyp\fR and
       the node\-gyp Wiki \fIhttps://github\.com/nodejs/node\-gyp/wiki\fR\|\.
       .SS Directories
       .P
      diff --git a/deps/npm/man/man5/package-lock-json.5 b/deps/npm/man/man5/package-lock-json.5
      index 20bedd30009757..610c0aa5fd36cd 100644
      --- a/deps/npm/man/man5/package-lock-json.5
      +++ b/deps/npm/man/man5/package-lock-json.5
      @@ -35,8 +35,8 @@ files, and allowing for significant performance improvements\.
       Both of these files have the same format, and perform similar functions in
       the root of a project\.
       .P
      -The difference is that \fBpackage\-lock\.json\fP is that it cannot be published,
      -and it will be ignored if found in any place other than the root project\.
      +The difference is that \fBpackage\-lock\.json\fP cannot be published, and it will
      +be ignored if found in any place other than the root project\.
       .P
       In contrast, npm help npm\-shrinkwrap\.json allows
       publication, and defines the dependency tree from the point encountered\.
      diff --git a/deps/npm/man/man7/scripts.7 b/deps/npm/man/man7/scripts.7
      index 63ebce805b4d8f..c514b2979d122e 100644
      --- a/deps/npm/man/man7/scripts.7
      +++ b/deps/npm/man/man7/scripts.7
      @@ -394,7 +394,7 @@ For example, if your package\.json contains this:
       {
         "scripts" : {
           "install" : "scripts/install\.js",
      -    "postinstall" : "scripts/postinstall\.js",
      +    "postinstall" : "scripts/install\.js",
           "uninstall" : "scripts/uninstall\.js"
         }
       }
      diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/diff.js b/deps/npm/node_modules/@npmcli/arborist/lib/diff.js
      index 842996ba486690..dac7c81f8ecfbf 100644
      --- a/deps/npm/node_modules/@npmcli/arborist/lib/diff.js
      +++ b/deps/npm/node_modules/@npmcli/arborist/lib/diff.js
      @@ -110,16 +110,32 @@ const getAction = ({actual, ideal}) => {
         if (ideal.isRoot && actual.isRoot)
           return null
       
      +  // if the versions don't match, it's a change no matter what
      +  if (ideal.version !== actual.version)
      +    return 'CHANGE'
      +
         const binsExist = ideal.binPaths.every((path) => existsSync(path))
       
         // top nodes, links, and git deps won't have integrity, but do have resolved
      -  if (!ideal.integrity && !actual.integrity && ideal.resolved === actual.resolved && binsExist)
      +  // if neither node has integrity, the bins exist, and either (a) neither
      +  // node has a resolved value or (b) they both do and match, then we can
      +  // leave this one alone since we already know the versions match due to
      +  // the condition above.  The "neither has resolved" case (a) cannot be
      +  // treated as a 'mark CHANGE and refetch', because shrinkwraps, bundles,
      +  // and link deps may lack this information, and we don't want to try to
      +  // go to the registry for something that isn't there.
      +  const noIntegrity = !ideal.integrity && !actual.integrity
      +  const noResolved = !ideal.resolved && !actual.resolved
      +  const resolvedMatch = ideal.resolved && ideal.resolved === actual.resolved
      +  if (noIntegrity && binsExist && (resolvedMatch || noResolved))
           return null
       
         // otherwise, verify that it's the same bits
         // note that if ideal has integrity, and resolved doesn't, we treat
         // that as a 'change', so that it gets re-fetched and locked down.
      -  if (!ideal.integrity || !actual.integrity || !ssri.parse(ideal.integrity).match(actual.integrity) || !binsExist)
      +  const integrityMismatch = !ideal.integrity || !actual.integrity ||
      +    !ssri.parse(ideal.integrity).match(actual.integrity)
      +  if (integrityMismatch || !binsExist)
           return 'CHANGE'
       
         return null
      diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/shrinkwrap.js b/deps/npm/node_modules/@npmcli/arborist/lib/shrinkwrap.js
      index cff9f09633dfce..0a19ef93005add 100644
      --- a/deps/npm/node_modules/@npmcli/arborist/lib/shrinkwrap.js
      +++ b/deps/npm/node_modules/@npmcli/arborist/lib/shrinkwrap.js
      @@ -714,6 +714,7 @@ class Shrinkwrap {
               resolved,
               integrity,
               hasShrinkwrap,
      +        version,
             } = this.get(node.path)
       
             const pathFixed = !resolved ? null
      @@ -727,8 +728,12 @@ class Shrinkwrap {
               node.resolved === pathFixed
             const integrityOk = !integrity || !node.integrity ||
               node.integrity === integrity
      +      const versionOk = !version || !node.version || version === node.version
       
      -      if ((resolved || integrity) && resolvedOk && integrityOk) {
      +      const allOk = (resolved || integrity || version) &&
      +        resolvedOk && integrityOk && versionOk
      +
      +      if (allOk) {
               node.resolved = node.resolved || pathFixed || null
               node.integrity = node.integrity || integrity || null
               node.hasShrinkwrap = node.hasShrinkwrap || hasShrinkwrap || false
      diff --git a/deps/npm/node_modules/@npmcli/arborist/package.json b/deps/npm/node_modules/@npmcli/arborist/package.json
      index 8500eaadf6752e..8aaa8ecdb7a4e2 100644
      --- a/deps/npm/node_modules/@npmcli/arborist/package.json
      +++ b/deps/npm/node_modules/@npmcli/arborist/package.json
      @@ -1,6 +1,6 @@
       {
         "name": "@npmcli/arborist",
      -  "version": "2.6.0",
      +  "version": "2.6.1",
         "description": "Manage node_modules trees",
         "dependencies": {
           "@npmcli/installed-package-contents": "^1.0.7",
      diff --git a/deps/npm/node_modules/cacache/README.md b/deps/npm/node_modules/cacache/README.md
      index 0c315595abd343..6dc11babfa62ab 100644
      --- a/deps/npm/node_modules/cacache/README.md
      +++ b/deps/npm/node_modules/cacache/README.md
      @@ -458,13 +458,17 @@ cacache.rm.all(cachePath).then(() => {
       })
       ```
       
      -####  `> cacache.rm.entry(cache, key) -> Promise`
      +####  `> cacache.rm.entry(cache, key, [opts]) -> Promise`
       
       Alias: `cacache.rm`
       
       Removes the index entry for `key`. Content will still be accessible if
       requested directly by content address ([`get.stream.byDigest`](#get-stream)).
       
      +By default, this appends a new entry to the index with an integrity of `null`.
      +If `opts.removeFully` is set to `true` then the index file itself will be
      +physically deleted rather than appending a `null`.
      +
       To remove the content itself (which might still be used by other entries), use
       [`rm.content`](#rm-content). Or, to safely vacuum any unused content, use
       [`verify`](#verify).
      @@ -491,12 +495,21 @@ cacache.rm.content(cachePath, 'sha512-SoMeDIGest/IN+BaSE64==').then(() => {
       })
       ```
       
      -####  `> cacache.index.compact(cache, key, matchFn) -> Promise`
      +####  `> cacache.index.compact(cache, key, matchFn, [opts]) -> Promise`
       
       Uses `matchFn`, which must be a synchronous function that accepts two entries
       and returns a boolean indicating whether or not the two entries match, to
       deduplicate all entries in the cache for the given `key`.
       
      +If `opts.validateEntry` is provided, it will be called as a function with the
      +only parameter being a single index entry. The function must return a Boolean,
      +if it returns `true` the entry is considered valid and will be kept in the index,
      +if it returns `false` the entry will be removed from the index.
      +
      +If `opts.validateEntry` is not provided, however, every entry in the index will
      +be deduplicated and kept until the first `null` integrity is reached, removing
      +all entries that were written before the `null`.
      +
       The deduplicated list of entries is both written to the index, replacing the
       existing content, and returned in the Promise.
       
      diff --git a/deps/npm/node_modules/cacache/get.js b/deps/npm/node_modules/cacache/get.js
      index b6bae1e504eba2..fe710bbd68def3 100644
      --- a/deps/npm/node_modules/cacache/get.js
      +++ b/deps/npm/node_modules/cacache/get.js
      @@ -32,18 +32,18 @@ function getData (byDigest, cache, key, opts = {}) {
                 metadata: memoized.entry.metadata,
                 data: memoized.data,
                 integrity: memoized.entry.integrity,
      -          size: memoized.entry.size
      +          size: memoized.entry.size,
               }
           )
         }
         return (byDigest ? Promise.resolve(null) : index.find(cache, key, opts)).then(
           (entry) => {
      -      if (!entry && !byDigest) {
      +      if (!entry && !byDigest)
               throw new index.NotFoundError(cache, key)
      -      }
      +
             return read(cache, byDigest ? key : entry.integrity, {
               integrity,
      -        size
      +        size,
             })
               .then((data) =>
                 byDigest
      @@ -52,15 +52,15 @@ function getData (byDigest, cache, key, opts = {}) {
                     data,
                     metadata: entry.metadata,
                     size: entry.size,
      -              integrity: entry.integrity
      +              integrity: entry.integrity,
                   }
               )
               .then((res) => {
      -          if (memoize && byDigest) {
      +          if (memoize && byDigest)
                   memo.put.byDigest(cache, key, res, opts)
      -          } else if (memoize) {
      +          else if (memoize)
                   memo.put(cache, entry, res.data, opts)
      -          }
      +
                 return res
               })
           }
      @@ -86,16 +86,16 @@ function getDataSync (byDigest, cache, key, opts = {}) {
               metadata: memoized.entry.metadata,
               data: memoized.data,
               integrity: memoized.entry.integrity,
      -        size: memoized.entry.size
      +        size: memoized.entry.size,
             }
         }
         const entry = !byDigest && index.find.sync(cache, key, opts)
      -  if (!entry && !byDigest) {
      +  if (!entry && !byDigest)
           throw new index.NotFoundError(cache, key)
      -  }
      +
         const data = read.sync(cache, byDigest ? key : entry.integrity, {
           integrity: integrity,
      -    size: size
      +    size: size,
         })
         const res = byDigest
           ? data
      @@ -103,13 +103,13 @@ function getDataSync (byDigest, cache, key, opts = {}) {
             metadata: entry.metadata,
             data: data,
             size: entry.size,
      -      integrity: entry.integrity
      +      integrity: entry.integrity,
           }
      -  if (memoize && byDigest) {
      +  if (memoize && byDigest)
           memo.put.byDigest(cache, key, res, opts)
      -  } else if (memoize) {
      +  else if (memoize)
           memo.put(cache, entry, res.data, opts)
      -  }
      +
         return res
       }
       
      @@ -129,17 +129,16 @@ const getMemoizedStream = (memoized) => {
       function getStream (cache, key, opts = {}) {
         const { memoize, size } = opts
         const memoized = memo.get(cache, key, opts)
      -  if (memoized && memoize !== false) {
      +  if (memoized && memoize !== false)
           return getMemoizedStream(memoized)
      -  }
       
         const stream = new Pipeline()
         index
           .find(cache, key)
           .then((entry) => {
      -      if (!entry) {
      +      if (!entry)
               throw new index.NotFoundError(cache, key)
      -      }
      +
             stream.emit('metadata', entry.metadata)
             stream.emit('integrity', entry.integrity)
             stream.emit('size', entry.size)
      @@ -178,9 +177,9 @@ function getStreamDigest (cache, integrity, opts = {}) {
           return stream
         } else {
           const stream = read.readStream(cache, integrity, opts)
      -    if (!memoize) {
      +    if (!memoize)
             return stream
      -    }
      +
           const memoStream = new Collect.PassThrough()
           memoStream.on('collect', data => memo.put.byDigest(
             cache,
      @@ -197,11 +196,10 @@ module.exports.info = info
       function info (cache, key, opts = {}) {
         const { memoize } = opts
         const memoized = memo.get(cache, key, opts)
      -  if (memoized && memoize !== false) {
      +  if (memoized && memoize !== false)
           return Promise.resolve(memoized.entry)
      -  } else {
      +  else
           return index.find(cache, key)
      -  }
       }
       
       module.exports.hasContent = read.hasContent
      @@ -224,9 +222,9 @@ function copy (byDigest, cache, key, dest, opts = {}) {
             ? Promise.resolve(null)
             : index.find(cache, key, opts)
           ).then((entry) => {
      -      if (!entry && !byDigest) {
      +      if (!entry && !byDigest)
               throw new index.NotFoundError(cache, key)
      -      }
      +
             return read
               .copy(cache, byDigest ? key : entry.integrity, dest, opts)
               .then(() => {
      @@ -235,7 +233,7 @@ function copy (byDigest, cache, key, dest, opts = {}) {
                   : {
                     metadata: entry.metadata,
                     size: entry.size,
      -              integrity: entry.integrity
      +              integrity: entry.integrity,
                   }
               })
           })
      @@ -248,7 +246,7 @@ function copy (byDigest, cache, key, dest, opts = {}) {
               : {
                 metadata: res.metadata,
                 size: res.size,
      -          integrity: res.integrity
      +          integrity: res.integrity,
               }
           })
         })
      diff --git a/deps/npm/node_modules/cacache/lib/content/read.js b/deps/npm/node_modules/cacache/lib/content/read.js
      index 7cc16482d44c8f..034e8eee05b101 100644
      --- a/deps/npm/node_modules/cacache/lib/content/read.js
      +++ b/deps/npm/node_modules/cacache/lib/content/read.js
      @@ -20,17 +20,16 @@ function read (cache, integrity, opts = {}) {
           // get size
           return lstat(cpath).then(stat => ({ stat, cpath, sri }))
         }).then(({ stat, cpath, sri }) => {
      -    if (typeof size === 'number' && stat.size !== size) {
      +    if (typeof size === 'number' && stat.size !== size)
             throw sizeError(size, stat.size)
      -    }
      -    if (stat.size > MAX_SINGLE_READ_SIZE) {
      +
      +    if (stat.size > MAX_SINGLE_READ_SIZE)
             return readPipeline(cpath, stat.size, sri, new Pipeline()).concat()
      -    }
       
           return readFile(cpath, null).then((data) => {
      -      if (!ssri.checkData(data, sri)) {
      +      if (!ssri.checkData(data, sri))
               throw integrityError(sri, cpath)
      -      }
      +
             return data
           })
         })
      @@ -40,11 +39,11 @@ const readPipeline = (cpath, size, sri, stream) => {
         stream.push(
           new fsm.ReadStream(cpath, {
             size,
      -      readSize: MAX_SINGLE_READ_SIZE
      +      readSize: MAX_SINGLE_READ_SIZE,
           }),
           ssri.integrityStream({
             integrity: sri,
      -      size
      +      size,
           })
         )
         return stream
      @@ -56,13 +55,11 @@ function readSync (cache, integrity, opts = {}) {
         const { size } = opts
         return withContentSriSync(cache, integrity, (cpath, sri) => {
           const data = fs.readFileSync(cpath)
      -    if (typeof size === 'number' && size !== data.length) {
      +    if (typeof size === 'number' && size !== data.length)
             throw sizeError(size, data.length)
      -    }
       
      -    if (ssri.checkData(data, sri)) {
      +    if (ssri.checkData(data, sri))
             return data
      -    }
       
           throw integrityError(sri, cpath)
         })
      @@ -78,9 +75,9 @@ function readStream (cache, integrity, opts = {}) {
           // just lstat to ensure it exists
           return lstat(cpath).then((stat) => ({ stat, cpath, sri }))
         }).then(({ stat, cpath, sri }) => {
      -    if (typeof size === 'number' && size !== stat.size) {
      +    if (typeof size === 'number' && size !== stat.size)
             return stream.emit('error', sizeError(size, stat.size))
      -    }
      +
           readPipeline(cpath, stat.size, sri, stream)
         }, er => stream.emit('error', er))
       
      @@ -109,22 +106,21 @@ function copySync (cache, integrity, dest) {
       module.exports.hasContent = hasContent
       
       function hasContent (cache, integrity) {
      -  if (!integrity) {
      +  if (!integrity)
           return Promise.resolve(false)
      -  }
      +
         return withContentSri(cache, integrity, (cpath, sri) => {
           return lstat(cpath).then((stat) => ({ size: stat.size, sri, stat }))
         }).catch((err) => {
      -    if (err.code === 'ENOENT') {
      +    if (err.code === 'ENOENT')
             return false
      -    }
      +
           if (err.code === 'EPERM') {
             /* istanbul ignore else */
      -      if (process.platform !== 'win32') {
      +      if (process.platform !== 'win32')
               throw err
      -      } else {
      +      else
               return false
      -      }
           }
         })
       }
      @@ -132,24 +128,23 @@ function hasContent (cache, integrity) {
       module.exports.hasContent.sync = hasContentSync
       
       function hasContentSync (cache, integrity) {
      -  if (!integrity) {
      +  if (!integrity)
           return false
      -  }
      +
         return withContentSriSync(cache, integrity, (cpath, sri) => {
           try {
             const stat = fs.lstatSync(cpath)
             return { size: stat.size, sri, stat }
           } catch (err) {
      -      if (err.code === 'ENOENT') {
      +      if (err.code === 'ENOENT')
               return false
      -      }
      +
             if (err.code === 'EPERM') {
               /* istanbul ignore else */
      -        if (process.platform !== 'win32') {
      +        if (process.platform !== 'win32')
                 throw err
      -        } else {
      +        else
                 return false
      -        }
             }
           }
         })
      @@ -167,7 +162,8 @@ function withContentSri (cache, integrity, fn) {
             const cpath = contentPath(cache, digests[0])
             return fn(cpath, digests[0])
           } else {
      -      // Can't use race here because a generic error can happen before a ENOENT error, and can happen before a valid result
      +      // Can't use race here because a generic error can happen before
      +      // a ENOENT error, and can happen before a valid result
             return Promise
               .all(digests.map((meta) => {
                 return withContentSri(cache, meta, fn)
      @@ -184,15 +180,13 @@ function withContentSri (cache, integrity, fn) {
               .then((results) => {
                 // Return the first non error if it is found
                 const result = results.find((r) => !(r instanceof Error))
      -          if (result) {
      +          if (result)
                   return result
      -          }
       
                 // Throw the No matching content found error
                 const enoentError = results.find((r) => r.code === 'ENOENT')
      -          if (enoentError) {
      +          if (enoentError)
                   throw enoentError
      -          }
       
                 // Throw generic error
                 throw results.find((r) => r instanceof Error)
      diff --git a/deps/npm/node_modules/cacache/lib/content/rm.js b/deps/npm/node_modules/cacache/lib/content/rm.js
      index 50612364e9b48a..6a3d1a3d023406 100644
      --- a/deps/npm/node_modules/cacache/lib/content/rm.js
      +++ b/deps/npm/node_modules/cacache/lib/content/rm.js
      @@ -11,10 +11,9 @@ module.exports = rm
       function rm (cache, integrity) {
         return hasContent(cache, integrity).then((content) => {
           // ~pretty~ sure we can't end up with a content lacking sri, but be safe
      -    if (content && content.sri) {
      +    if (content && content.sri)
             return rimraf(contentPath(cache, content.sri)).then(() => true)
      -    } else {
      +    else
             return false
      -    }
         })
       }
      diff --git a/deps/npm/node_modules/cacache/lib/content/write.js b/deps/npm/node_modules/cacache/lib/content/write.js
      index e8f3e3534940ca..dde1bd1dd5daef 100644
      --- a/deps/npm/node_modules/cacache/lib/content/write.js
      +++ b/deps/npm/node_modules/cacache/lib/content/write.js
      @@ -22,16 +22,15 @@ module.exports = write
       
       function write (cache, data, opts = {}) {
         const { algorithms, size, integrity } = opts
      -  if (algorithms && algorithms.length > 1) {
      +  if (algorithms && algorithms.length > 1)
           throw new Error('opts.algorithms only supports a single algorithm for now')
      -  }
      -  if (typeof size === 'number' && data.length !== size) {
      +
      +  if (typeof size === 'number' && data.length !== size)
           return Promise.reject(sizeError(size, data.length))
      -  }
      +
         const sri = ssri.fromData(data, algorithms ? { algorithms } : {})
      -  if (integrity && !ssri.checkData(data, integrity, opts)) {
      +  if (integrity && !ssri.checkData(data, integrity, opts))
           return Promise.reject(checksumError(integrity, sri))
      -  }
       
         return disposer(makeTmp(cache, opts), makeTmpDisposer,
           (tmp) => {
      @@ -112,13 +111,17 @@ function pipeToTmp (inputStream, cache, tmpTarget, opts) {
         const hashStream = ssri.integrityStream({
           integrity: opts.integrity,
           algorithms: opts.algorithms,
      -    size: opts.size
      +    size: opts.size,
      +  })
      +  hashStream.on('integrity', i => {
      +    integrity = i
      +  })
      +  hashStream.on('size', s => {
      +    size = s
         })
      -  hashStream.on('integrity', i => { integrity = i })
      -  hashStream.on('size', s => { size = s })
       
         const outStream = new fsm.WriteStream(tmpTarget, {
      -    flags: 'wx'
      +    flags: 'wx',
         })
       
         // NB: this can throw if the hashStream has a problem with
      @@ -132,21 +135,23 @@ function pipeToTmp (inputStream, cache, tmpTarget, opts) {
       
         return pipeline.promise()
           .then(() => ({ integrity, size }))
      -    .catch(er => rimraf(tmpTarget).then(() => { throw er }))
      +    .catch(er => rimraf(tmpTarget).then(() => {
      +      throw er
      +    }))
       }
       
       function makeTmp (cache, opts) {
         const tmpTarget = uniqueFilename(path.join(cache, 'tmp'), opts.tmpPrefix)
         return fixOwner.mkdirfix(cache, path.dirname(tmpTarget)).then(() => ({
           target: tmpTarget,
      -    moved: false
      +    moved: false,
         }))
       }
       
       function makeTmpDisposer (tmp) {
      -  if (tmp.moved) {
      +  if (tmp.moved)
           return Promise.resolve()
      -  }
      +
         return rimraf(tmp.target)
       }
       
      diff --git a/deps/npm/node_modules/cacache/lib/entry-index.js b/deps/npm/node_modules/cacache/lib/entry-index.js
      index 8827ebb541b2dc..71aac5ed75b146 100644
      --- a/deps/npm/node_modules/cacache/lib/entry-index.js
      +++ b/deps/npm/node_modules/cacache/lib/entry-index.js
      @@ -14,7 +14,9 @@ const fixOwner = require('./util/fix-owner')
       const hashToSegments = require('./util/hash-to-segments')
       const indexV = require('../package.json')['cache-version'].index
       const moveFile = require('@npmcli/move-file')
      -const rimraf = util.promisify(require('rimraf'))
      +const _rimraf = require('rimraf')
      +const rimraf = util.promisify(_rimraf)
      +rimraf.sync = _rimraf.sync
       
       const appendFile = util.promisify(fs.appendFile)
       const readFile = util.promisify(fs.readFile)
      @@ -35,15 +37,30 @@ module.exports.compact = compact
       async function compact (cache, key, matchFn, opts = {}) {
         const bucket = bucketPath(cache, key)
         const entries = await bucketEntries(bucket)
      -  // reduceRight because the bottom-most result is the newest
      +  const newEntries = []
      +  // we loop backwards because the bottom-most result is the newest
         // since we add new entries with appendFile
      -  const newEntries = entries.reduceRight((acc, newEntry) => {
      -    if (!acc.find((oldEntry) => matchFn(oldEntry, newEntry))) {
      -      acc.push(newEntry)
      -    }
      -
      -    return acc
      -  }, [])
      +  for (let i = entries.length - 1; i >= 0; --i) {
      +    const entry = entries[i]
      +    // a null integrity could mean either a delete was appended
      +    // or the user has simply stored an index that does not map
      +    // to any content. we determine if the user wants to keep the
      +    // null integrity based on the validateEntry function passed in options.
      +    // if the integrity is null and no validateEntry is provided, we break
      +    // as we consider the null integrity to be a deletion of everything
      +    // that came before it.
      +    if (entry.integrity === null && !opts.validateEntry)
      +      break
      +
      +    // if this entry is valid, and it is either the first entry or
      +    // the newEntries array doesn't already include an entry that
      +    // matches this one based on the provided matchFn, then we add
      +    // it to the beginning of our list
      +    if ((!opts.validateEntry || opts.validateEntry(entry) === true) &&
      +      (newEntries.length === 0 ||
      +        !newEntries.find((oldEntry) => matchFn(oldEntry, entry))))
      +      newEntries.unshift(entry)
      +  }
       
         const newIndex = '\n' + newEntries.map((entry) => {
           const stringified = JSON.stringify(entry)
      @@ -56,14 +73,13 @@ async function compact (cache, key, matchFn, opts = {}) {
           await fixOwner.mkdirfix(cache, path.dirname(target))
           return {
             target,
      -      moved: false
      +      moved: false,
           }
         }
       
         const teardown = async (tmp) => {
      -    if (!tmp.moved) {
      +    if (!tmp.moved)
             return rimraf(tmp.target)
      -    }
         }
       
         const write = async (tmp) => {
      @@ -76,16 +92,20 @@ async function compact (cache, key, matchFn, opts = {}) {
           try {
             await fixOwner.chownr(cache, bucket)
           } catch (err) {
      -      if (err.code !== 'ENOENT') {
      +      if (err.code !== 'ENOENT')
               throw err
      -      }
           }
         }
       
         // write the file atomically
         await disposer(setup(), teardown, write)
       
      -  return newEntries.map((entry) => formatEntry(cache, entry, true))
      +  // we reverse the list we generated such that the newest
      +  // entries come first in order to make looping through them easier
      +  // the true passed to formatEntry tells it to keep null
      +  // integrity values, if they made it this far it's because
      +  // validateEntry returned true, and as such we should return it
      +  return newEntries.reverse().map((entry) => formatEntry(cache, entry, true))
       }
       
       module.exports.insert = insert
      @@ -98,7 +118,7 @@ function insert (cache, key, integrity, opts = {}) {
           integrity: integrity && ssri.stringify(integrity),
           time: Date.now(),
           size,
      -    metadata
      +    metadata,
         }
         return fixOwner
           .mkdirfix(cache, path.dirname(bucket))
      @@ -110,14 +130,15 @@ function insert (cache, key, integrity, opts = {}) {
             // another while still preserving the string length of the JSON in
             // question. So, we just slap the length in there and verify it on read.
             //
      -      // Thanks to @isaacs for the whiteboarding session that ended up with this.
      +      // Thanks to @isaacs for the whiteboarding session that ended up with
      +      // this.
             return appendFile(bucket, `\n${hashEntry(stringified)}\t${stringified}`)
           })
           .then(() => fixOwner.chownr(cache, bucket))
           .catch((err) => {
      -      if (err.code === 'ENOENT') {
      +      if (err.code === 'ENOENT')
               return undefined
      -      }
      +
             throw err
             // There's a class of race conditions that happen when things get deleted
             // during fixOwner, or between the two mkdirfix/chownr calls.
      @@ -140,7 +161,7 @@ function insertSync (cache, key, integrity, opts = {}) {
           integrity: integrity && ssri.stringify(integrity),
           time: Date.now(),
           size,
      -    metadata
      +    metadata,
         }
         fixOwner.mkdirfix.sync(cache, path.dirname(bucket))
         const stringified = JSON.stringify(entry)
      @@ -148,9 +169,8 @@ function insertSync (cache, key, integrity, opts = {}) {
         try {
           fixOwner.chownr.sync(cache, bucket)
         } catch (err) {
      -    if (err.code !== 'ENOENT') {
      +    if (err.code !== 'ENOENT')
             throw err
      -    }
         }
         return formatEntry(cache, entry)
       }
      @@ -162,19 +182,17 @@ function find (cache, key) {
         return bucketEntries(bucket)
           .then((entries) => {
             return entries.reduce((latest, next) => {
      -        if (next && next.key === key) {
      +        if (next && next.key === key)
                 return formatEntry(cache, next)
      -        } else {
      +        else
                 return latest
      -        }
             }, null)
           })
           .catch((err) => {
      -      if (err.code === 'ENOENT') {
      +      if (err.code === 'ENOENT')
               return null
      -      } else {
      +      else
               throw err
      -      }
           })
       }
       
      @@ -184,31 +202,37 @@ function findSync (cache, key) {
         const bucket = bucketPath(cache, key)
         try {
           return bucketEntriesSync(bucket).reduce((latest, next) => {
      -      if (next && next.key === key) {
      +      if (next && next.key === key)
               return formatEntry(cache, next)
      -      } else {
      +      else
               return latest
      -      }
           }, null)
         } catch (err) {
      -    if (err.code === 'ENOENT') {
      +    if (err.code === 'ENOENT')
             return null
      -    } else {
      +    else
             throw err
      -    }
         }
       }
       
       module.exports.delete = del
       
      -function del (cache, key, opts) {
      -  return insert(cache, key, null, opts)
      +function del (cache, key, opts = {}) {
      +  if (!opts.removeFully)
      +    return insert(cache, key, null, opts)
      +
      +  const bucket = bucketPath(cache, key)
      +  return rimraf(bucket)
       }
       
       module.exports.delete.sync = delSync
       
      -function delSync (cache, key, opts) {
      -  return insertSync(cache, key, null, opts)
      +function delSync (cache, key, opts = {}) {
      +  if (!opts.removeFully)
      +    return insertSync(cache, key, null, opts)
      +
      +  const bucket = bucketPath(cache, key)
      +  return rimraf.sync(bucket)
       }
       
       module.exports.lsStream = lsStream
      @@ -239,12 +263,12 @@ function lsStream (cache) {
                       // reduced is a map of key => entry
                       for (const entry of reduced.values()) {
                         const formatted = formatEntry(cache, entry)
      -                  if (formatted) {
      +                  if (formatted)
                           stream.write(formatted)
      -                  }
                       }
                     }).catch(err => {
      -                if (err.code === 'ENOENT') { return undefined }
      +                if (err.code === 'ENOENT')
      +                  return undefined
                       throw err
                     })
                   })
      @@ -288,9 +312,9 @@ function bucketEntriesSync (bucket, filter) {
       function _bucketEntries (data, filter) {
         const entries = []
         data.split('\n').forEach((entry) => {
      -    if (!entry) {
      +    if (!entry)
             return
      -    }
      +
           const pieces = entry.split('\t')
           if (!pieces[1] || hashEntry(pieces[1]) !== pieces[0]) {
             // Hash is no good! Corruption or malice? Doesn't matter!
      @@ -304,9 +328,8 @@ function _bucketEntries (data, filter) {
             // Entry is corrupted!
             return
           }
      -    if (obj) {
      +    if (obj)
             entries.push(obj)
      -    }
         })
         return entries
       }
      @@ -348,24 +371,23 @@ function hash (str, digest) {
       
       function formatEntry (cache, entry, keepAll) {
         // Treat null digests as deletions. They'll shadow any previous entries.
      -  if (!entry.integrity && !keepAll) {
      +  if (!entry.integrity && !keepAll)
           return null
      -  }
      +
         return {
           key: entry.key,
           integrity: entry.integrity,
           path: entry.integrity ? contentPath(cache, entry.integrity) : undefined,
           size: entry.size,
           time: entry.time,
      -    metadata: entry.metadata
      +    metadata: entry.metadata,
         }
       }
       
       function readdirOrEmpty (dir) {
         return readdir(dir).catch((err) => {
      -    if (err.code === 'ENOENT' || err.code === 'ENOTDIR') {
      +    if (err.code === 'ENOENT' || err.code === 'ENOTDIR')
             return []
      -    }
       
           throw err
         })
      diff --git a/deps/npm/node_modules/cacache/lib/memoization.js b/deps/npm/node_modules/cacache/lib/memoization.js
      index 185141d8eadad8..d5465f39fc581e 100644
      --- a/deps/npm/node_modules/cacache/lib/memoization.js
      +++ b/deps/npm/node_modules/cacache/lib/memoization.js
      @@ -8,7 +8,7 @@ const MAX_AGE = 3 * 60 * 1000
       const MEMOIZED = new LRU({
         max: MAX_SIZE,
         maxAge: MAX_AGE,
      -  length: (entry, key) => key.startsWith('key:') ? entry.data.length : entry.length
      +  length: (entry, key) => key.startsWith('key:') ? entry.data.length : entry.length,
       })
       
       module.exports.clearMemoized = clearMemoized
      @@ -62,13 +62,12 @@ class ObjProxy {
       }
       
       function pickMem (opts) {
      -  if (!opts || !opts.memoize) {
      +  if (!opts || !opts.memoize)
           return MEMOIZED
      -  } else if (opts.memoize.get && opts.memoize.set) {
      +  else if (opts.memoize.get && opts.memoize.set)
           return opts.memoize
      -  } else if (typeof opts.memoize === 'object') {
      +  else if (typeof opts.memoize === 'object')
           return new ObjProxy(opts.memoize)
      -  } else {
      +  else
           return MEMOIZED
      -  }
       }
      diff --git a/deps/npm/node_modules/cacache/lib/util/disposer.js b/deps/npm/node_modules/cacache/lib/util/disposer.js
      index 8a24ad2f2a2a28..aa8aed54da551d 100644
      --- a/deps/npm/node_modules/cacache/lib/util/disposer.js
      +++ b/deps/npm/node_modules/cacache/lib/util/disposer.js
      @@ -8,9 +8,9 @@ function disposer (creatorFn, disposerFn, fn) {
             .then(
               // disposer resolved, do something with original fn's promise
               () => {
      -          if (shouldThrow) {
      +          if (shouldThrow)
                   throw result
      -          }
      +
                 return result
               },
               // Disposer fn failed, crash process
      diff --git a/deps/npm/node_modules/cacache/lib/util/fix-owner.js b/deps/npm/node_modules/cacache/lib/util/fix-owner.js
      index 9afa638a8c8393..90ffece524f54b 100644
      --- a/deps/npm/node_modules/cacache/lib/util/fix-owner.js
      +++ b/deps/npm/node_modules/cacache/lib/util/fix-owner.js
      @@ -49,9 +49,8 @@ function fixOwner (cache, filepath) {
           const { uid, gid } = owner
       
           // No need to override if it's already what we used.
      -    if (self.uid === uid && self.gid === gid) {
      +    if (self.uid === uid && self.gid === gid)
             return
      -    }
       
           return inflight('fixOwner: fixing ownership on ' + filepath, () =>
             chownr(
      @@ -59,9 +58,9 @@ function fixOwner (cache, filepath) {
               typeof uid === 'number' ? uid : self.uid,
               typeof gid === 'number' ? gid : self.gid
             ).catch((err) => {
      -        if (err.code === 'ENOENT') {
      +        if (err.code === 'ENOENT')
                 return null
      -        }
      +
               throw err
             })
           )
      @@ -94,9 +93,9 @@ function fixOwnerSync (cache, filepath) {
           )
         } catch (err) {
           // only catch ENOENT, any other error is a problem.
      -    if (err.code === 'ENOENT') {
      +    if (err.code === 'ENOENT')
             return null
      -    }
      +
           throw err
         }
       }
      @@ -111,14 +110,13 @@ function mkdirfix (cache, p, cb) {
         return Promise.resolve(inferOwner(cache)).then(() => {
           return mkdirp(p)
             .then((made) => {
      -        if (made) {
      +        if (made)
                 return fixOwner(cache, made).then(() => made)
      -        }
             })
             .catch((err) => {
      -        if (err.code === 'EEXIST') {
      +        if (err.code === 'EEXIST')
                 return fixOwner(cache, p).then(() => null)
      -        }
      +
               throw err
             })
         })
      @@ -138,8 +136,7 @@ function mkdirfixSync (cache, p) {
           if (err.code === 'EEXIST') {
             fixOwnerSync(cache, p)
             return null
      -    } else {
      +    } else
             throw err
      -    }
         }
       }
      diff --git a/deps/npm/node_modules/cacache/lib/util/move-file.js b/deps/npm/node_modules/cacache/lib/util/move-file.js
      index 84130b2e9ffb82..c3f9e35eb99c77 100644
      --- a/deps/npm/node_modules/cacache/lib/util/move-file.js
      +++ b/deps/npm/node_modules/cacache/lib/util/move-file.js
      @@ -38,19 +38,17 @@ function moveFile (src, dest) {
               } else if (err.code === 'EEXIST' || err.code === 'EBUSY') {
                 // file already exists, so whatever
                 return resolve()
      -        } else {
      +        } else
                 return reject(err)
      -        }
      -      } else {
      +      } else
               return resolve()
      -      }
           })
         })
           .then(() => {
             // content should never change for any reason, so make it read-only
             return Promise.all([
               unlink(src),
      -        !isWindows && chmod(dest, '0444')
      +        !isWindows && chmod(dest, '0444'),
             ])
           })
           .catch(() => {
      diff --git a/deps/npm/node_modules/cacache/lib/verify.js b/deps/npm/node_modules/cacache/lib/verify.js
      index 5a011a3f1d2cb1..e9d679eceaf51f 100644
      --- a/deps/npm/node_modules/cacache/lib/verify.js
      +++ b/deps/npm/node_modules/cacache/lib/verify.js
      @@ -24,7 +24,7 @@ const readFile = util.promisify(fs.readFile)
       const verifyOpts = (opts) => ({
         concurrency: 20,
         log: { silly () {} },
      -  ...opts
      +  ...opts,
       })
       
       module.exports = verify
      @@ -40,7 +40,7 @@ function verify (cache, opts) {
           rebuildIndex,
           cleanTmp,
           writeVerifile,
      -    markEndTime
      +    markEndTime,
         ]
       
         return steps
      @@ -54,9 +54,9 @@ function verify (cache, opts) {
                     stats[k] = s[k]
                   })
                 const end = new Date()
      -          if (!stats.runTime) {
      +          if (!stats.runTime)
                   stats.runTime = {}
      -          }
      +
                 stats.runTime[label] = end - start
                 return Promise.resolve(stats)
               })
      @@ -108,9 +108,9 @@ function garbageCollect (cache, opts) {
         const indexStream = index.lsStream(cache)
         const liveContent = new Set()
         indexStream.on('data', (entry) => {
      -    if (opts.filter && !opts.filter(entry)) {
      +    if (opts.filter && !opts.filter(entry))
             return
      -    }
      +
           liveContent.add(entry.integrity.toString())
         })
         return new Promise((resolve, reject) => {
      @@ -120,14 +120,14 @@ function garbageCollect (cache, opts) {
           return glob(path.join(contentDir, '**'), {
             follow: false,
             nodir: true,
      -      nosort: true
      +      nosort: true,
           }).then((files) => {
             return Promise.resolve({
               verifiedContent: 0,
               reclaimedCount: 0,
               reclaimedSize: 0,
               badContentCount: 0,
      -        keptSize: 0
      +        keptSize: 0,
             }).then((stats) =>
               pMap(
                 files,
      @@ -171,14 +171,14 @@ function verifyContent (filepath, sri) {
           .then((s) => {
             const contentInfo = {
               size: s.size,
      -        valid: true
      +        valid: true,
             }
             return ssri
               .checkStream(new fsm.ReadStream(filepath), sri)
               .catch((err) => {
      -          if (err.code !== 'EINTEGRITY') {
      +          if (err.code !== 'EINTEGRITY')
                   throw err
      -          }
      +
                 return rimraf(filepath).then(() => {
                   contentInfo.valid = false
                 })
      @@ -186,9 +186,9 @@ function verifyContent (filepath, sri) {
               .then(() => contentInfo)
           })
           .catch((err) => {
      -      if (err.code === 'ENOENT') {
      +      if (err.code === 'ENOENT')
               return { size: 0, valid: false }
      -      }
      +
             throw err
           })
       }
      @@ -199,7 +199,7 @@ function rebuildIndex (cache, opts) {
           const stats = {
             missingContent: 0,
             rejectedEntries: 0,
      -      totalEntries: 0
      +      totalEntries: 0,
           }
           const buckets = {}
           for (const k in entries) {
      @@ -209,9 +209,9 @@ function rebuildIndex (cache, opts) {
               const entry = entries[k]
               const excluded = opts.filter && !opts.filter(entry)
               excluded && stats.rejectedEntries++
      -        if (buckets[hashed] && !excluded) {
      +        if (buckets[hashed] && !excluded)
                 buckets[hashed].push(entry)
      -        } else if (buckets[hashed] && excluded) {
      +        else if (buckets[hashed] && excluded) {
                 // skip
               } else if (excluded) {
                 buckets[hashed] = []
      @@ -244,7 +244,7 @@ function rebuildBucket (cache, bucket, stats, opts) {
                   return index
                     .insert(cache, entry.key, entry.integrity, {
                       metadata: entry.metadata,
      -                size: entry.size
      +                size: entry.size,
                     })
                     .then(() => {
                       stats.totalEntries++
      diff --git a/deps/npm/node_modules/cacache/package.json b/deps/npm/node_modules/cacache/package.json
      index aefa5aae42585c..3c2e65c0404a0d 100644
      --- a/deps/npm/node_modules/cacache/package.json
      +++ b/deps/npm/node_modules/cacache/package.json
      @@ -1,6 +1,6 @@
       {
         "name": "cacache",
      -  "version": "15.1.0",
      +  "version": "15.2.0",
         "cache-version": {
           "content": "2",
           "index": "5"
      @@ -13,15 +13,17 @@
         ],
         "scripts": {
           "benchmarks": "node test/benchmarks",
      -    "lint": "standard",
      -    "postrelease": "npm publish",
      -    "posttest": "npm run lint",
      -    "prepublishOnly": "git push --follow-tags",
      -    "prerelease": "npm t",
      -    "release": "standard-version -s",
      +    "preversion": "npm test",
      +    "postversion": "npm publish",
      +    "prepublishOnly": "git push origin --follow-tags",
           "test": "tap",
      +    "snap": "tap",
           "coverage": "tap",
      -    "test-docker": "docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test"
      +    "test-docker": "docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test",
      +    "lint": "npm run npmclilint -- \"*.*js\" \"lib/**/*.*js\" \"test/**/*.*js\"",
      +    "npmclilint": "npmcli-lint",
      +    "lintfix": "npm run lint -- --fix",
      +    "postsnap": "npm run lintfix --"
         },
         "repository": "https://github.com/npm/cacache",
         "keywords": [
      @@ -39,23 +41,6 @@
           "disk cache",
           "disk storage"
         ],
      -  "author": {
      -    "name": "Kat Marchán",
      -    "email": "kzm@sykosomatic.org",
      -    "twitter": "maybekatz"
      -  },
      -  "contributors": [
      -    {
      -      "name": "Charlotte Spencer",
      -      "email": "charlottelaspencer@gmail.com",
      -      "twitter": "charlotteis"
      -    },
      -    {
      -      "name": "Rebecca Turner",
      -      "email": "me@re-becca.org",
      -      "twitter": "ReBeccaOrg"
      -    }
      -  ],
         "license": "ISC",
         "dependencies": {
           "@npmcli/move-file": "^1.0.1",
      @@ -77,11 +62,10 @@
           "unique-filename": "^1.1.1"
         },
         "devDependencies": {
      +    "@npmcli/lint": "^1.0.1",
           "benchmark": "^2.1.4",
           "chalk": "^4.0.0",
           "require-inject": "^1.4.4",
      -    "standard": "^14.3.1",
      -    "standard-version": "^7.1.0",
           "tacks": "^1.3.0",
           "tap": "^15.0.9"
         },
      diff --git a/deps/npm/node_modules/cacache/put.js b/deps/npm/node_modules/cacache/put.js
      index eb21aa867173f6..84e9562bc33abb 100644
      --- a/deps/npm/node_modules/cacache/put.js
      +++ b/deps/npm/node_modules/cacache/put.js
      @@ -9,7 +9,7 @@ const Pipeline = require('minipass-pipeline')
       
       const putOpts = (opts) => ({
         algorithms: ['sha512'],
      -  ...opts
      +  ...opts,
       })
       
       module.exports = putData
      @@ -21,9 +21,9 @@ function putData (cache, key, data, opts = {}) {
           return index
             .insert(cache, key, res.integrity, { ...opts, size: res.size })
             .then((entry) => {
      -        if (memoize) {
      +        if (memoize)
                 memo.put(cache, entry, data, opts)
      -        }
      +
               return res.integrity
             })
         })
      @@ -67,17 +67,16 @@ function putStream (cache, key, opts = {}) {
             return index
               .insert(cache, key, integrity, { ...opts, size })
               .then((entry) => {
      -          if (memoize && memoData) {
      +          if (memoize && memoData)
                   memo.put(cache, entry, memoData, opts)
      -          }
      -          if (integrity) {
      +
      +          if (integrity)
                   pipeline.emit('integrity', integrity)
      -          }
      -          if (size) {
      +
      +          if (size)
                   pipeline.emit('size', size)
      -          }
               })
      -    }
      +    },
         }))
       
         return pipeline
      diff --git a/deps/npm/node_modules/cacache/rm.js b/deps/npm/node_modules/cacache/rm.js
      index 7dd4e8c8b07f1c..f2ef6b190f4577 100644
      --- a/deps/npm/node_modules/cacache/rm.js
      +++ b/deps/npm/node_modules/cacache/rm.js
      @@ -11,9 +11,9 @@ const rmContent = require('./lib/content/rm')
       module.exports = entry
       module.exports.entry = entry
       
      -function entry (cache, key) {
      +function entry (cache, key, opts) {
         memo.clearMemoized()
      -  return index.delete(cache, key)
      +  return index.delete(cache, key, opts)
       }
       
       module.exports.content = content
      diff --git a/deps/npm/node_modules/is-core-module/.github/FUNDING.yml b/deps/npm/node_modules/is-core-module/.github/FUNDING.yml
      deleted file mode 100644
      index 422ce9b01a7f3b..00000000000000
      --- a/deps/npm/node_modules/is-core-module/.github/FUNDING.yml
      +++ /dev/null
      @@ -1,12 +0,0 @@
      -# These are supported funding model platforms
      -
      -github: [ljharb]
      -patreon: # Replace with a single Patreon username
      -open_collective: # Replace with a single Open Collective username
      -ko_fi: # Replace with a single Ko-fi username
      -tidelift: npm/is-core-module
      -community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
      -liberapay: # Replace with a single Liberapay username
      -issuehunt: # Replace with a single IssueHunt username
      -otechie: # Replace with a single Otechie username
      -custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
      diff --git a/deps/npm/node_modules/is-core-module/.github/workflows/node-4+.yml b/deps/npm/node_modules/is-core-module/.github/workflows/node-4+.yml
      deleted file mode 100644
      index ba174e1d6c28cd..00000000000000
      --- a/deps/npm/node_modules/is-core-module/.github/workflows/node-4+.yml
      +++ /dev/null
      @@ -1,54 +0,0 @@
      -name: 'Tests: node.js'
      -
      -on: [pull_request, push]
      -
      -jobs:
      -  matrix:
      -    runs-on: ubuntu-latest
      -    outputs:
      -      latest: ${{ steps.set-matrix.outputs.requireds }}
      -      minors: ${{ steps.set-matrix.outputs.optionals }}
      -    steps:
      -      - uses: ljharb/actions/node/matrix@main
      -        id: set-matrix
      -        with:
      -          preset: '>=4'
      -
      -  latest:
      -    needs: [matrix]
      -    name: 'latest minors'
      -    runs-on: ubuntu-latest
      -
      -    strategy:
      -      matrix: ${{ fromJson(needs.matrix.outputs.latest) }}
      -
      -    steps:
      -      - uses: actions/checkout@v2
      -      - uses: ljharb/actions/node/run@main
      -        name: 'npm install && npm run tests-only'
      -        with:
      -          node-version: ${{ matrix.node-version }}
      -          command: 'tests-only'
      -  minors:
      -    needs: [matrix, latest]
      -    name: 'non-latest minors'
      -    continue-on-error: true
      -    if: ${{ !github.head_ref || !startsWith(github.head_ref, 'renovate') }}
      -    runs-on: ubuntu-latest
      -
      -    strategy:
      -      matrix: ${{ fromJson(needs.matrix.outputs.minors) }}
      -
      -    steps:
      -      - uses: actions/checkout@v2
      -      - uses: ljharb/actions/node/run@main
      -        with:
      -          node-version: ${{ matrix.node-version }}
      -          command: 'tests-only'
      -
      -  node:
      -    name: 'node 4+'
      -    needs: [latest, minors]
      -    runs-on: ubuntu-latest
      -    steps:
      -      - run: 'echo tests completed'
      diff --git a/deps/npm/node_modules/is-core-module/.github/workflows/node-iojs.yml b/deps/npm/node_modules/is-core-module/.github/workflows/node-iojs.yml
      deleted file mode 100644
      index f707c3cfc308ec..00000000000000
      --- a/deps/npm/node_modules/is-core-module/.github/workflows/node-iojs.yml
      +++ /dev/null
      @@ -1,58 +0,0 @@
      -name: 'Tests: node.js (io.js)'
      -
      -on: [pull_request, push]
      -
      -jobs:
      -  matrix:
      -    runs-on: ubuntu-latest
      -    outputs:
      -      latest: ${{ steps.set-matrix.outputs.requireds }}
      -      minors: ${{ steps.set-matrix.outputs.optionals }}
      -    steps:
      -      - uses: ljharb/actions/node/matrix@main
      -        id: set-matrix
      -        with:
      -          preset: 'iojs'
      -
      -  latest:
      -    needs: [matrix]
      -    name: 'latest minors'
      -    runs-on: ubuntu-latest
      -
      -    strategy:
      -      matrix: ${{ fromJson(needs.matrix.outputs.latest) }}
      -
      -    steps:
      -      - uses: actions/checkout@v2
      -      - uses: ljharb/actions/node/run@main
      -        name: 'npm install && npm run tests-only'
      -        with:
      -          node-version: ${{ matrix.node-version }}
      -          command: 'tests-only'
      -          skip-ls-check: true
      -
      -  minors:
      -    needs: [matrix, latest]
      -    name: 'non-latest minors'
      -    continue-on-error: true
      -    if: ${{ !github.head_ref || !startsWith(github.head_ref, 'renovate') }}
      -    runs-on: ubuntu-latest
      -
      -    strategy:
      -      matrix: ${{ fromJson(needs.matrix.outputs.minors) }}
      -
      -    steps:
      -      - uses: actions/checkout@v2
      -      - uses: ljharb/actions/node/run@main
      -        name: 'npm install && npm run tests-only'
      -        with:
      -          node-version: ${{ matrix.node-version }}
      -          command: 'tests-only'
      -          skip-ls-check: true
      -
      -  node:
      -    name: 'io.js'
      -    needs: [latest, minors]
      -    runs-on: ubuntu-latest
      -    steps:
      -      - run: 'echo tests completed'
      diff --git a/deps/npm/node_modules/is-core-module/.github/workflows/node-pretest.yml b/deps/npm/node_modules/is-core-module/.github/workflows/node-pretest.yml
      deleted file mode 100644
      index 3921e0ae6cd6ba..00000000000000
      --- a/deps/npm/node_modules/is-core-module/.github/workflows/node-pretest.yml
      +++ /dev/null
      @@ -1,26 +0,0 @@
      -name: 'Tests: pretest/posttest'
      -
      -on: [pull_request, push]
      -
      -jobs:
      -  pretest:
      -    runs-on: ubuntu-latest
      -
      -    steps:
      -      - uses: actions/checkout@v2
      -      - uses: ljharb/actions/node/run@main
      -        name: 'npm install && npm run pretest'
      -        with:
      -          node-version: 'lts/*'
      -          command: 'pretest'
      -
      -  posttest:
      -    runs-on: ubuntu-latest
      -
      -    steps:
      -      - uses: actions/checkout@v2
      -      - uses: ljharb/actions/node/run@main
      -        name: 'npm install && npm run posttest'
      -        with:
      -          node-version: 'lts/*'
      -          command: 'posttest'
      diff --git a/deps/npm/node_modules/is-core-module/.github/workflows/node-zero.yml b/deps/npm/node_modules/is-core-module/.github/workflows/node-zero.yml
      deleted file mode 100644
      index d044c6031d5b3a..00000000000000
      --- a/deps/npm/node_modules/is-core-module/.github/workflows/node-zero.yml
      +++ /dev/null
      @@ -1,58 +0,0 @@
      -name: 'Tests: node.js (0.x)'
      -
      -on: [pull_request, push]
      -
      -jobs:
      -  matrix:
      -    runs-on: ubuntu-latest
      -    outputs:
      -      stable: ${{ steps.set-matrix.outputs.requireds }}
      -      unstable: ${{ steps.set-matrix.outputs.optionals }}
      -    steps:
      -      - uses: ljharb/actions/node/matrix@main
      -        id: set-matrix
      -        with:
      -          preset: '0.x'
      -
      -  stable:
      -    needs: [matrix]
      -    name: 'stable minors'
      -    runs-on: ubuntu-latest
      -
      -    strategy:
      -      matrix: ${{ fromJson(needs.matrix.outputs.stable) }}
      -
      -    steps:
      -      - uses: actions/checkout@v2
      -      - uses: ljharb/actions/node/run@main
      -        with:
      -          node-version: ${{ matrix.node-version }}
      -          command: 'tests-only'
      -          cache-node-modules-key: node_modules-${{ github.workflow }}-${{ github.action }}-${{ github.run_id }}
      -          skip-ls-check: true
      -
      -  unstable:
      -    needs: [matrix, stable]
      -    name: 'unstable minors'
      -    continue-on-error: true
      -    if: ${{ !github.head_ref || !startsWith(github.head_ref, 'renovate') }}
      -    runs-on: ubuntu-latest
      -
      -    strategy:
      -      matrix: ${{ fromJson(needs.matrix.outputs.unstable) }}
      -
      -    steps:
      -      - uses: actions/checkout@v2
      -      - uses: ljharb/actions/node/run@main
      -        with:
      -          node-version: ${{ matrix.node-version }}
      -          command: 'tests-only'
      -          cache-node-modules-key: node_modules-${{ github.workflow }}-${{ github.action }}-${{ github.run_id }}
      -          skip-ls-check: true
      -
      -  node:
      -    name: 'node 0.x'
      -    needs: [stable, unstable]
      -    runs-on: ubuntu-latest
      -    steps:
      -      - run: 'echo tests completed'
      diff --git a/deps/npm/node_modules/is-core-module/.github/workflows/rebase.yml b/deps/npm/node_modules/is-core-module/.github/workflows/rebase.yml
      deleted file mode 100644
      index 0c2ad39b5f7b82..00000000000000
      --- a/deps/npm/node_modules/is-core-module/.github/workflows/rebase.yml
      +++ /dev/null
      @@ -1,15 +0,0 @@
      -name: Automatic Rebase
      -
      -on: [pull_request_target]
      -
      -jobs:
      -  _:
      -    name: "Automatic Rebase"
      -
      -    runs-on: ubuntu-latest
      -
      -    steps:
      -    - uses: actions/checkout@v1
      -    - uses: ljharb/rebase@master
      -      env:
      -        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      diff --git a/deps/npm/node_modules/is-core-module/.github/workflows/require-allow-edits.yml b/deps/npm/node_modules/is-core-module/.github/workflows/require-allow-edits.yml
      deleted file mode 100644
      index aac42d3e29c7af..00000000000000
      --- a/deps/npm/node_modules/is-core-module/.github/workflows/require-allow-edits.yml
      +++ /dev/null
      @@ -1,14 +0,0 @@
      -name: Require “Allow Edits”
      -
      -on: [pull_request_target]
      -
      -jobs:
      -  _:
      -    name: "Require “Allow Edits”"
      -
      -    runs-on: ubuntu-latest
      -
      -    steps:
      -    - uses: ljharb/require-allow-edits@main
      -      env:
      -        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      diff --git a/deps/npm/node_modules/is-core-module/.nycrc b/deps/npm/node_modules/is-core-module/.nycrc
      index 1826526e091b89..bdd626ce91477a 100644
      --- a/deps/npm/node_modules/is-core-module/.nycrc
      +++ b/deps/npm/node_modules/is-core-module/.nycrc
      @@ -2,10 +2,6 @@
       	"all": true,
       	"check-coverage": false,
       	"reporter": ["text-summary", "text", "html", "json"],
      -	"lines": 86,
      -	"statements": 85.93,
      -	"functions": 82.43,
      -	"branches": 76.06,
       	"exclude": [
       		"coverage",
       		"test"
      diff --git a/deps/npm/node_modules/is-core-module/CHANGELOG.md b/deps/npm/node_modules/is-core-module/CHANGELOG.md
      index 4cdb33d005960d..f2148ddde438a8 100644
      --- a/deps/npm/node_modules/is-core-module/CHANGELOG.md
      +++ b/deps/npm/node_modules/is-core-module/CHANGELOG.md
      @@ -5,6 +5,31 @@ All notable changes to this project will be documented in this file.
       The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
       and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
       
      +## [v2.4.0](https://github.com/inspect-js/is-core-module/compare/v2.3.0...v2.4.0) - 2021-05-09
      +
      +### Commits
      +
      +- [readme] add actions and codecov badges [`82b7faa`](https://github.com/inspect-js/is-core-module/commit/82b7faa12b56dbe47fbea67e1a5b9e447027ba40)
      +- [Dev Deps] update `@ljharb/eslint-config`, `aud` [`8096868`](https://github.com/inspect-js/is-core-module/commit/8096868c024a161ccd4d44110b136763e92eace8)
      +- [Dev Deps] update `eslint` [`6726824`](https://github.com/inspect-js/is-core-module/commit/67268249b88230018c510f6532a8046d7326346f)
      +- [New] add `diagnostics_channel` to node `^14.17` [`86c6563`](https://github.com/inspect-js/is-core-module/commit/86c65634201b8ff9b3e48a9a782594579c7f5c3c)
      +- [meta] fix prepublish script [`697a01e`](https://github.com/inspect-js/is-core-module/commit/697a01e3c9c0be074066520954f30fb28532ec57)
      +
      +## [v2.3.0](https://github.com/inspect-js/is-core-module/compare/v2.2.0...v2.3.0) - 2021-04-24
      +
      +### Commits
      +
      +- [meta] do not publish github action workflow files [`060d4bb`](https://github.com/inspect-js/is-core-module/commit/060d4bb971a29451c19ff336eb56bee27f9fa95a)
      +- [New] add support for `node:` prefix, in node 16+ [`7341223`](https://github.com/inspect-js/is-core-module/commit/73412230a769f6e81c05eea50b6520cebf54ed2f)
      +- [actions] use `node/install` instead of `node/run`; use `codecov` action [`016269a`](https://github.com/inspect-js/is-core-module/commit/016269abae9f6657a5254adfbb813f09a05067f9)
      +- [patch] remove unneeded `.0` in version ranges [`cb466a6`](https://github.com/inspect-js/is-core-module/commit/cb466a6d89e52b8389e5c12715efcd550c41cea3)
      +- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud`, `tape` [`c9f9c39`](https://github.com/inspect-js/is-core-module/commit/c9f9c396ace60ef81906f98059c064e6452473ed)
      +- [actions] update workflows [`3ee4a89`](https://github.com/inspect-js/is-core-module/commit/3ee4a89fd5a02fccd43882d905448ea6a98e9a3c)
      +- [Dev Deps] update `eslint`, `@ljharb/eslint-config` [`dee4fed`](https://github.com/inspect-js/is-core-module/commit/dee4fed79690c1d43a22f7fa9426abebdc6d727f)
      +- [Dev Deps] update `eslint`, `@ljharb/eslint-config` [`7d046ba`](https://github.com/inspect-js/is-core-module/commit/7d046ba07ae8c9292e43652694ca808d7b309de8)
      +- [meta] use `prepublishOnly` script for npm 7+ [`149e677`](https://github.com/inspect-js/is-core-module/commit/149e6771a5ede6d097e71785b467a9c4b4977cc7)
      +- [readme] remove travis badge [`903b51d`](https://github.com/inspect-js/is-core-module/commit/903b51d6b69b98abeabfbc3695c345b02646f19c)
      +
       ## [v2.2.0](https://github.com/inspect-js/is-core-module/compare/v2.1.0...v2.2.0) - 2020-11-26
       
       ### Commits
      diff --git a/deps/npm/node_modules/is-core-module/README.md b/deps/npm/node_modules/is-core-module/README.md
      index 479d6d24c0f041..062d9068eb57e8 100644
      --- a/deps/npm/node_modules/is-core-module/README.md
      +++ b/deps/npm/node_modules/is-core-module/README.md
      @@ -1,6 +1,7 @@
       # is-core-module [![Version Badge][2]][1]
       
      -[![Build Status][3]][4]
      +[![github actions][actions-image]][actions-url]
      +[![coverage][codecov-image]][codecov-url]
       [![dependency status][5]][6]
       [![dev dependency status][7]][8]
       [![License][license-image]][license-url]
      @@ -24,8 +25,6 @@ Clone the repo, `npm install`, and run `npm test`
       
       [1]: https://npmjs.org/package/is-core-module
       [2]: https://versionbadg.es/inspect-js/is-core-module.svg
      -[3]: https://travis-ci.com/inspect-js/is-core-module.svg
      -[4]: https://travis-ci.com/inspect-js/is-core-module
       [5]: https://david-dm.org/inspect-js/is-core-module.svg
       [6]: https://david-dm.org/inspect-js/is-core-module
       [7]: https://david-dm.org/inspect-js/is-core-module/dev-status.svg
      @@ -35,3 +34,7 @@ Clone the repo, `npm install`, and run `npm test`
       [license-url]: LICENSE
       [downloads-image]: https://img.shields.io/npm/dm/is-core-module.svg
       [downloads-url]: https://npm-stat.com/charts.html?package=is-core-module
      +[codecov-image]: https://codecov.io/gh/inspect-js/is-core-module/branch/main/graphs/badge.svg
      +[codecov-url]: https://app.codecov.io/gh/inspect-js/is-core-module/
      +[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/inspect-js/is-core-module
      +[actions-url]: https://github.com/inspect-js/is-core-module/actions
      diff --git a/deps/npm/node_modules/is-core-module/core.json b/deps/npm/node_modules/is-core-module/core.json
      index 0238b61a4c71e4..44a92a1a414b97 100644
      --- a/deps/npm/node_modules/is-core-module/core.json
      +++ b/deps/npm/node_modules/is-core-module/core.json
      @@ -1,83 +1,146 @@
       {
       	"assert": true,
      +	"node:assert": ">= 16",
       	"assert/strict": ">= 15",
      +	"node:assert/strict": ">= 16",
       	"async_hooks": ">= 8",
      +	"node:async_hooks": ">= 16",
       	"buffer_ieee754": "< 0.9.7",
       	"buffer": true,
      +	"node:buffer": ">= 16",
       	"child_process": true,
      +	"node:child_process": ">= 16",
       	"cluster": true,
      +	"node:cluster": ">= 16",
       	"console": true,
      +	"node:console": ">= 16",
       	"constants": true,
      +	"node:constants": ">= 16",
       	"crypto": true,
      +	"node:crypto": ">= 16",
       	"_debug_agent": ">= 1 && < 8",
       	"_debugger": "< 8",
       	"dgram": true,
      -	"diagnostics_channel": ">= 15.1",
      +	"node:dgram": ">= 16",
      +	"diagnostics_channel": [">= 14.17 && < 15", ">= 15.1"],
      +	"node:diagnostics_channel": ">= 16",
       	"dns": true,
      +	"node:dns": ">= 16",
       	"dns/promises": ">= 15",
      +	"node:dns/promises": ">= 16",
       	"domain": ">= 0.7.12",
      +	"node:domain": ">= 16",
       	"events": true,
      +	"node:events": ">= 16",
       	"freelist": "< 6",
       	"fs": true,
      +	"node:fs": ">= 16",
       	"fs/promises": [">= 10 && < 10.1", ">= 14"],
      +	"node:fs/promises": ">= 16",
       	"_http_agent": ">= 0.11.1",
      +	"node:_http_agent": ">= 16",
       	"_http_client": ">= 0.11.1",
      +	"node:_http_client": ">= 16",
       	"_http_common": ">= 0.11.1",
      +	"node:_http_common": ">= 16",
       	"_http_incoming": ">= 0.11.1",
      +	"node:_http_incoming": ">= 16",
       	"_http_outgoing": ">= 0.11.1",
      +	"node:_http_outgoing": ">= 16",
       	"_http_server": ">= 0.11.1",
      +	"node:_http_server": ">= 16",
       	"http": true,
      +	"node:http": ">= 16",
       	"http2": ">= 8.8",
      +	"node:http2": ">= 16",
       	"https": true,
      -	"inspector": ">= 8.0.0",
      +	"node:https": ">= 16",
      +	"inspector": ">= 8",
      +	"node:inspector": ">= 16",
       	"_linklist": "< 8",
       	"module": true,
      +	"node:module": ">= 16",
       	"net": true,
      -	"node-inspect/lib/_inspect": ">= 7.6.0 && < 12",
      -	"node-inspect/lib/internal/inspect_client": ">= 7.6.0 && < 12",
      -	"node-inspect/lib/internal/inspect_repl": ">= 7.6.0 && < 12",
      +	"node:net": ">= 16",
      +	"node-inspect/lib/_inspect": ">= 7.6 && < 12",
      +	"node-inspect/lib/internal/inspect_client": ">= 7.6 && < 12",
      +	"node-inspect/lib/internal/inspect_repl": ">= 7.6 && < 12",
       	"os": true,
      +	"node:os": ">= 16",
       	"path": true,
      +	"node:path": ">= 16",
       	"path/posix": ">= 15.3",
      +	"node:path/posix": ">= 16",
       	"path/win32": ">= 15.3",
      +	"node:path/win32": ">= 16",
       	"perf_hooks": ">= 8.5",
      +	"node:perf_hooks": ">= 16",
       	"process": ">= 1",
      +	"node:process": ">= 16",
       	"punycode": true,
      +	"node:punycode": ">= 16",
       	"querystring": true,
      +	"node:querystring": ">= 16",
       	"readline": true,
      +	"node:readline": ">= 16",
       	"repl": true,
      +	"node:repl": ">= 16",
       	"smalloc": ">= 0.11.5 && < 3",
       	"_stream_duplex": ">= 0.9.4",
      +	"node:_stream_duplex": ">= 16",
       	"_stream_transform": ">= 0.9.4",
      +	"node:_stream_transform": ">= 16",
       	"_stream_wrap": ">= 1.4.1",
      +	"node:_stream_wrap": ">= 16",
       	"_stream_passthrough": ">= 0.9.4",
      +	"node:_stream_passthrough": ">= 16",
       	"_stream_readable": ">= 0.9.4",
      +	"node:_stream_readable": ">= 16",
       	"_stream_writable": ">= 0.9.4",
      +	"node:_stream_writable": ">= 16",
       	"stream": true,
      +	"node:stream": ">= 16",
       	"stream/promises": ">= 15",
      +	"node:stream/promises": ">= 16",
       	"string_decoder": true,
      +	"node:string_decoder": ">= 16",
       	"sys": [">= 0.6 && < 0.7", ">= 0.8"],
      +	"node:sys": ">= 16",
       	"timers": true,
      +	"node:timers": ">= 16",
       	"timers/promises": ">= 15",
      +	"node:timers/promises": ">= 16",
       	"_tls_common": ">= 0.11.13",
      +	"node:_tls_common": ">= 16",
       	"_tls_legacy": ">= 0.11.3 && < 10",
       	"_tls_wrap": ">= 0.11.3",
      +	"node:_tls_wrap": ">= 16",
       	"tls": true,
      +	"node:tls": ">= 16",
       	"trace_events": ">= 10",
      +	"node:trace_events": ">= 16",
       	"tty": true,
      +	"node:tty": ">= 16",
       	"url": true,
      +	"node:url": ">= 16",
       	"util": true,
      +	"node:util": ">= 16",
       	"util/types": ">= 15.3",
      +	"node:util/types": ">= 16",
       	"v8/tools/arguments": ">= 10 && < 12",
      -	"v8/tools/codemap": [">= 4.4.0 && < 5", ">= 5.2.0 && < 12"],
      -	"v8/tools/consarray": [">= 4.4.0 && < 5", ">= 5.2.0 && < 12"],
      -	"v8/tools/csvparser": [">= 4.4.0 && < 5", ">= 5.2.0 && < 12"],
      -	"v8/tools/logreader": [">= 4.4.0 && < 5", ">= 5.2.0 && < 12"],
      -	"v8/tools/profile_view": [">= 4.4.0 && < 5", ">= 5.2.0 && < 12"],
      -	"v8/tools/splaytree": [">= 4.4.0 && < 5", ">= 5.2.0 && < 12"],
      +	"v8/tools/codemap": [">= 4.4 && < 5", ">= 5.2 && < 12"],
      +	"v8/tools/consarray": [">= 4.4 && < 5", ">= 5.2 && < 12"],
      +	"v8/tools/csvparser": [">= 4.4 && < 5", ">= 5.2 && < 12"],
      +	"v8/tools/logreader": [">= 4.4 && < 5", ">= 5.2 && < 12"],
      +	"v8/tools/profile_view": [">= 4.4 && < 5", ">= 5.2 && < 12"],
      +	"v8/tools/splaytree": [">= 4.4 && < 5", ">= 5.2 && < 12"],
       	"v8": ">= 1",
      +	"node:v8": ">= 16",
       	"vm": true,
      +	"node:vm": ">= 16",
       	"wasi": ">= 13.4 && < 13.5",
       	"worker_threads": ">= 11.7",
      -	"zlib": true
      +	"node:worker_threads": ">= 16",
      +	"zlib": true,
      +	"node:zlib": ">= 16"
       }
      diff --git a/deps/npm/node_modules/is-core-module/package.json b/deps/npm/node_modules/is-core-module/package.json
      index 21341cc431a505..0442e92cd2065a 100644
      --- a/deps/npm/node_modules/is-core-module/package.json
      +++ b/deps/npm/node_modules/is-core-module/package.json
      @@ -1,6 +1,6 @@
       {
       	"name": "is-core-module",
      -	"version": "2.2.0",
      +	"version": "2.4.0",
       	"description": "Is this specifier a node.js core module?",
       	"main": "index.js",
       	"exports": {
      @@ -13,7 +13,8 @@
       		"./package.json": "./package.json"
       	},
       	"scripts": {
      -		"prepublish": "safe-publish-latest",
      +		"prepublish": "not-in-publish || npm run prepublishOnly",
      +		"prepublishOnly": "safe-publish-latest",
       		"lint": "eslint .",
       		"pretest": "npm run lint",
       		"tests-only": "tape 'test/**/*.js'",
      @@ -47,13 +48,14 @@
       		"has": "^1.0.3"
       	},
       	"devDependencies": {
      -		"@ljharb/eslint-config": "^17.3.0",
      -		"aud": "^1.1.3",
      +		"@ljharb/eslint-config": "^17.6.0",
      +		"aud": "^1.1.5",
       		"auto-changelog": "^2.2.1",
      -		"eslint": "^7.14.0",
      +		"eslint": "^7.26.0",
       		"nyc": "^10.3.2",
       		"safe-publish-latest": "^1.1.4",
      -		"tape": "^5.0.1"
      +		"semver": "^6.3.0",
      +		"tape": "^5.2.2"
       	},
       	"auto-changelog": {
       		"output": "CHANGELOG.md",
      diff --git a/deps/npm/node_modules/is-core-module/test/index.js b/deps/npm/node_modules/is-core-module/test/index.js
      index 99659bcf113f78..281c7e9a4b1340 100644
      --- a/deps/npm/node_modules/is-core-module/test/index.js
      +++ b/deps/npm/node_modules/is-core-module/test/index.js
      @@ -2,9 +2,12 @@
       
       var test = require('tape');
       var keys = require('object-keys');
      +var semver = require('semver');
       var isCore = require('../');
       var data = require('../core.json');
       
      +var supportsNodePrefix = semver.satisfies(process.versions.node, '>= 16');
      +
       test('core modules', function (t) {
       	t.test('isCore()', function (st) {
       		st.ok(isCore('fs'));
      @@ -48,6 +51,17 @@ test('core modules', function (t) {
       					function () { require(mod); }, // eslint-disable-line no-loop-func
       					'requiring ' + mod + ' does not throw'
       				);
      +				if (supportsNodePrefix) {
      +					st.doesNotThrow(
      +						function () { require('node:' + mod); }, // eslint-disable-line no-loop-func
      +						'requiring node:' + mod + ' does not throw'
      +					);
      +				} else {
      +					st['throws'](
      +						function () { require('node:' + mod); }, // eslint-disable-line no-loop-func
      +						'requiring node:' + mod + ' throws'
      +					);
      +				}
       			}
       		}
       		st.end();
      @@ -73,6 +87,17 @@ test('core modules', function (t) {
       						function () { require(mod); }, // eslint-disable-line no-loop-func
       						'requiring ' + mod + ' does not throw'
       					);
      +					if (supportsNodePrefix) {
      +						st.doesNotThrow(
      +							function () { require('node:' + mod); }, // eslint-disable-line no-loop-func
      +							'requiring node:' + mod + ' does not throw'
      +						);
      +					} else {
      +						st['throws'](
      +							function () { require('node:' + mod); }, // eslint-disable-line no-loop-func
      +							'requiring node:' + mod + ' throws'
      +						);
      +					}
       				}
       			}
       		}
      diff --git a/deps/npm/node_modules/libnpmexec/CHANGELOG.md b/deps/npm/node_modules/libnpmexec/CHANGELOG.md
      new file mode 100644
      index 00000000000000..81a0e1a0327c38
      --- /dev/null
      +++ b/deps/npm/node_modules/libnpmexec/CHANGELOG.md
      @@ -0,0 +1,16 @@
      +# Changelog
      +
      +## v1.1.0
      +
      +- Add add walk up dir lookup logic to satisfy local bins,
      +similar to `@npmcli/run-script`
      +
      +## v1.0.1
      +
      +- Fix `scriptShell` option name.
      +
      +## v1.0.0
      +
      +- Initial implementation, moves the code that used to live in the **npm cli**,
      +ref: https://github.com/npm/cli/blob/release/v7.10.0/lib/exec.js into this
      +separate module, providing a programmatic API to the **npm exec** functionality.
      diff --git a/deps/npm/node_modules/libnpmexec/README.md b/deps/npm/node_modules/libnpmexec/README.md
      index fb7a7717600197..18a26011adc769 100644
      --- a/deps/npm/node_modules/libnpmexec/README.md
      +++ b/deps/npm/node_modules/libnpmexec/README.md
      @@ -39,7 +39,7 @@ await libexec({
         - `packages`: A list of packages to be used (possibly fetch from the registry) **Array**, defaults to `[]`
         - `path`: Location to where to read local project info (`package.json`) **String**, defaults to `.`
         - `runPath`: Location to where to execute the script **String**, defaults to `.`
      -  - `scriptShell`: Default shell to be used **String**
      +  - `scriptShell`: Default shell to be used **String**, defaults to `sh` on POSIX systems, `process.env.ComSpec` OR `cmd` on Windows
         - `yes`: Should skip download confirmation prompt when fetching missing packages from the registry? **Boolean**
         - `registry`, `cache`, and more options that are forwarded to [@npmcli/arborist](https://github.com/npm/arborist/) and [pacote](https://github.com/npm/pacote/#options) **Object**
       
      diff --git a/deps/npm/node_modules/libnpmexec/lib/index.js b/deps/npm/node_modules/libnpmexec/lib/index.js
      index a48c654bf6a4f8..8c5181f3975197 100644
      --- a/deps/npm/node_modules/libnpmexec/lib/index.js
      +++ b/deps/npm/node_modules/libnpmexec/lib/index.js
      @@ -16,6 +16,7 @@ const getBinFromManifest = require('./get-bin-from-manifest.js')
       const manifestMissing = require('./manifest-missing.js')
       const noTTY = require('./no-tty.js')
       const runScript = require('./run-script.js')
      +const isWindows = require('./is-windows.js')
       
       /* istanbul ignore next */
       const PATH = (
      @@ -34,7 +35,7 @@ const exec = async (opts) => {
           packages: _packages = [],
           path = '.',
           runPath = '.',
      -    scriptShell = undefined,
      +    scriptShell = isWindows ? process.env.ComSpec || 'cmd' : 'sh',
           yes = undefined,
           ...flatOptions
         } = opts
      diff --git a/deps/npm/node_modules/libnpmexec/lib/is-windows.js b/deps/npm/node_modules/libnpmexec/lib/is-windows.js
      new file mode 100644
      index 00000000000000..fbece90ad74964
      --- /dev/null
      +++ b/deps/npm/node_modules/libnpmexec/lib/is-windows.js
      @@ -0,0 +1 @@
      +module.exports = process.platform === 'win32'
      diff --git a/deps/npm/node_modules/libnpmexec/package.json b/deps/npm/node_modules/libnpmexec/package.json
      index c113ac6d0a6076..2b3b488cf079f3 100644
      --- a/deps/npm/node_modules/libnpmexec/package.json
      +++ b/deps/npm/node_modules/libnpmexec/package.json
      @@ -1,6 +1,6 @@
       {
         "name": "libnpmexec",
      -  "version": "1.1.1",
      +  "version": "1.2.0",
         "files": [
           "lib"
         ],
      diff --git a/deps/npm/node_modules/mkdirp/README.markdown b/deps/npm/node_modules/mkdirp/readme.markdown
      similarity index 100%
      rename from deps/npm/node_modules/mkdirp/README.markdown
      rename to deps/npm/node_modules/mkdirp/readme.markdown
      diff --git a/deps/npm/node_modules/npm-audit-report/CHANGELOG.md b/deps/npm/node_modules/npm-audit-report/CHANGELOG.md
      deleted file mode 100644
      index 58819a43b4d110..00000000000000
      --- a/deps/npm/node_modules/npm-audit-report/CHANGELOG.md
      +++ /dev/null
      @@ -1,81 +0,0 @@
      -# Change Log
      -
      -All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
      -
      -
      -## [1.3.3](https://github.com/npm/npm-audit-report/compare/v1.3.2...v1.3.3) (2020-03-26)
      -
      -
      -
      -
      -## [1.3.2](https://github.com/npm/npm-audit-report/compare/v1.3.1...v1.3.2) (2018-12-18)
      -
      -
      -### Bug Fixes
      -
      -* **parseable:** add support for critical vulns and more resolves on update/install action ([#28](https://github.com/npm/npm-audit-report/issues/28)) ([5e27893](https://github.com/npm/npm-audit-report/commit/5e27893))
      -* **security:** audit fix ([ff9faf3](https://github.com/npm/npm-audit-report/commit/ff9faf3))
      -* **urls:** Replace hardcoded URL to advisory with a URL from audit response ([#34](https://github.com/npm/npm-audit-report/issues/34)) ([e2fe95b](https://github.com/npm/npm-audit-report/commit/e2fe95b))
      -
      -
      -
      -
      -## [1.3.1](https://github.com/npm/npm-audit-report/compare/v1.3.0...v1.3.1) (2018-07-10)
      -
      -
      -
      -
      -# [1.3.0](https://github.com/npm/npm-audit-report/compare/v1.2.1...v1.3.0) (2018-07-09)
      -
      -
      -### Bug Fixes
      -
      -* **deps:** remove object.values dependency ([2c5374a](https://github.com/npm/npm-audit-report/commit/2c5374a))
      -* **detail:** Fix info-level severity ([#18](https://github.com/npm/npm-audit-report/issues/18)) ([807db5a](https://github.com/npm/npm-audit-report/commit/807db5a))
      -* **tests:** a test should not cause side-effects in other tests ([#23](https://github.com/npm/npm-audit-report/issues/23)) ([a94449f](https://github.com/npm/npm-audit-report/commit/a94449f))
      -
      -
      -### Features
      -
      -* **output:** add `parseable` tabular output format support ([#21](https://github.com/npm/npm-audit-report/issues/21)) ([1c9aaf4](https://github.com/npm/npm-audit-report/commit/1c9aaf4))
      -
      -
      -
      -
      -## [1.2.1](https://github.com/npm/npm-audit-report/compare/v1.2.0...v1.2.1) (2018-05-17)
      -
      -
      -### Bug Fixes
      -
      -* **detail:** count id+path instead of just id ([99880fd](https://github.com/npm/npm-audit-report/commit/99880fd))
      -
      -
      -
      -
      -# [1.2.0](https://github.com/npm/npm-audit-report/compare/v1.1.0...v1.2.0) (2018-05-16)
      -
      -
      -### Bug Fixes
      -
      -* **full-report:** Fix install flag for devDependencies ([#14](https://github.com/npm/npm-audit-report/issues/14)) ([30e5f30](https://github.com/npm/npm-audit-report/commit/30e5f30))
      -
      -
      -### Features
      -
      -* **detail:** consistified full report with install report ([#15](https://github.com/npm/npm-audit-report/issues/15)) ([6df6810](https://github.com/npm/npm-audit-report/commit/6df6810))
      -* **install:** include `npm audit` recommendation too ([32fb153](https://github.com/npm/npm-audit-report/commit/32fb153))
      -
      -
      -
      -
      -# [1.1.0](https://github.com/npm/npm-audit-report/compare/v1.0.9...v1.1.0) (2018-05-10)
      -
      -
      -### Bug Fixes
      -
      -* **install:** not enough data for this conditional ([6ddc30c](https://github.com/npm/npm-audit-report/commit/6ddc30c))
      -
      -
      -### Features
      -
      -* **report:** compress and reformat human-readable install report ([74d5203](https://github.com/npm/npm-audit-report/commit/74d5203))
      diff --git a/deps/npm/node_modules/npm-audit-report/lib/index.js b/deps/npm/node_modules/npm-audit-report/lib/index.js
      index 464004c17518a9..9ee86be7915d8d 100644
      --- a/deps/npm/node_modules/npm-audit-report/lib/index.js
      +++ b/deps/npm/node_modules/npm-audit-report/lib/index.js
      @@ -15,9 +15,11 @@ module.exports = Object.assign((data, options = {}) => {
           color = true,
           unicode = true,
           indent = 2,
      -    auditLevel = 'low'
         } = options
       
      +  // CLI defaults this to `null` so the defaulting method above doesn't work
      +  const auditLevel = options.auditLevel || 'low'
      +
         if (!data)
           throw Object.assign(
             new TypeError('ENOAUDITDATA'),
      diff --git a/deps/npm/node_modules/npm-audit-report/package.json b/deps/npm/node_modules/npm-audit-report/package.json
      index 66b4a6aa74b2c1..c819b9608412ac 100644
      --- a/deps/npm/node_modules/npm-audit-report/package.json
      +++ b/deps/npm/node_modules/npm-audit-report/package.json
      @@ -1,6 +1,6 @@
       {
         "name": "npm-audit-report",
      -  "version": "2.1.4",
      +  "version": "2.1.5",
         "description": "Given a response from the npm security api, render it into a variety of security reports",
         "main": "lib/index.js",
         "scripts": {
      @@ -26,8 +26,8 @@
           "chalk": "^4.0.0"
         },
         "devDependencies": {
      -    "tap": "^14.10.7",
      -    "require-inject": "^1.4.4"
      +    "require-inject": "^1.4.4",
      +    "tap": "^14.10.7"
         },
         "directories": {
           "lib": "lib",
      diff --git a/deps/npm/node_modules/retry/Readme.md b/deps/npm/node_modules/retry/README.md
      similarity index 99%
      rename from deps/npm/node_modules/retry/Readme.md
      rename to deps/npm/node_modules/retry/README.md
      index 16e28ec267d6da..1c888deee9c9d4 100644
      --- a/deps/npm/node_modules/retry/Readme.md
      +++ b/deps/npm/node_modules/retry/README.md
      @@ -66,7 +66,7 @@ Creates a new `RetryOperation` object. `options` is the same as `retry.timeouts(
       
       * `forever`: Whether to retry forever, defaults to `false`.
       * `unref`: Whether to [unref](https://nodejs.org/api/timers.html#timers_unref) the setTimeout's, defaults to `false`.
      -* `maxRetryTime`: The maximum time (in milliseconds) that the retried operation is allowed to run. Default is `Infinity`.  
      +* `maxRetryTime`: The maximum time (in milliseconds) that the retried operation is allowed to run. Default is `Infinity`.
       
       ### retry.timeouts([options])
       
      diff --git a/deps/npm/package.json b/deps/npm/package.json
      index d7f46589a4d2b7..7df43589334ef5 100644
      --- a/deps/npm/package.json
      +++ b/deps/npm/package.json
      @@ -1,5 +1,5 @@
       {
      -  "version": "7.14.0",
      +  "version": "7.15.1",
         "name": "npm",
         "description": "a package manager for JavaScript",
         "keywords": [
      @@ -42,7 +42,7 @@
           "./package.json": "./package.json"
         },
         "dependencies": {
      -    "@npmcli/arborist": "^2.6.0",
      +    "@npmcli/arborist": "^2.6.1",
           "@npmcli/ci-detect": "^1.2.0",
           "@npmcli/config": "^2.2.0",
           "@npmcli/run-script": "^1.8.5",
      @@ -51,7 +51,7 @@
           "ansistyles": "~0.1.3",
           "archy": "~1.0.0",
           "byte-size": "^7.0.1",
      -    "cacache": "^15.1.0",
      +    "cacache": "^15.2.0",
           "chalk": "^4.1.0",
           "chownr": "^2.0.0",
           "cli-columns": "^3.1.2",
      @@ -67,7 +67,7 @@
           "leven": "^3.1.0",
           "libnpmaccess": "^4.0.2",
           "libnpmdiff": "^2.0.4",
      -    "libnpmexec": "^1.1.1",
      +    "libnpmexec": "^1.2.0",
           "libnpmfund": "^1.1.0",
           "libnpmhook": "^6.0.2",
           "libnpmorg": "^2.0.2",
      @@ -84,7 +84,7 @@
           "ms": "^2.1.2",
           "node-gyp": "^7.1.2",
           "nopt": "^5.0.0",
      -    "npm-audit-report": "^2.1.4",
      +    "npm-audit-report": "^2.1.5",
           "npm-package-arg": "^8.1.2",
           "npm-pick-manifest": "^6.1.1",
           "npm-profile": "^5.0.3",
      @@ -183,7 +183,7 @@
           "@mdx-js/mdx": "^1.6.22",
           "cmark-gfm": "^0.8.5",
           "eslint": "^7.26.0",
      -    "eslint-plugin-import": "^2.22.1",
      +    "eslint-plugin-import": "^2.23.4",
           "eslint-plugin-node": "^11.1.0",
           "eslint-plugin-promise": "^5.1.0",
           "eslint-plugin-standard": "^5.0.0",
      diff --git a/deps/npm/tap-snapshots/test/lib/dist-tag.js.test.cjs b/deps/npm/tap-snapshots/test/lib/dist-tag.js.test.cjs
      index 86a9c84eb1eb63..7eceb0250d926b 100644
      --- a/deps/npm/tap-snapshots/test/lib/dist-tag.js.test.cjs
      +++ b/deps/npm/tap-snapshots/test/lib/dist-tag.js.test.cjs
      @@ -6,7 +6,8 @@
        */
       'use strict'
       exports[`test/lib/dist-tag.js TAP add missing args > should exit usage error message 1`] = `
      -npm dist-tag
      +Error:
      +Usage: npm dist-tag
       
       Modify package distribution tags
       
      @@ -21,11 +22,14 @@ Options:
       
       alias: dist-tags
       
      -Run "npm help dist-tag" for more info
      +Run "npm help dist-tag" for more info {
      +  "code": "EUSAGE",
      +}
       `
       
       exports[`test/lib/dist-tag.js TAP add missing pkg name > should exit usage error message 1`] = `
      -npm dist-tag
      +Error:
      +Usage: npm dist-tag
       
       Modify package distribution tags
       
      @@ -40,7 +44,9 @@ Options:
       
       alias: dist-tags
       
      -Run "npm help dist-tag" for more info
      +Run "npm help dist-tag" for more info {
      +  "code": "EUSAGE",
      +}
       `
       
       exports[`test/lib/dist-tag.js TAP add new tag > should return success msg 1`] = `
      @@ -53,7 +59,8 @@ dist-tag add 1.0.0 to @scoped/another@7.7.7
       `
       
       exports[`test/lib/dist-tag.js TAP borked cmd usage > should show usage error 1`] = `
      -npm dist-tag
      +Error:
      +Usage: npm dist-tag
       
       Modify package distribution tags
       
      @@ -68,7 +75,31 @@ Options:
       
       alias: dist-tags
       
      -Run "npm help dist-tag" for more info
      +Run "npm help dist-tag" for more info {
      +  "code": "EUSAGE",
      +}
      +`
      +
      +exports[`test/lib/dist-tag.js TAP ls global > should throw basic usage 1`] = `
      +Error:
      +Usage: npm dist-tag
      +
      +Modify package distribution tags
      +
      +Usage:
      +npm dist-tag add @ []
      +npm dist-tag rm  
      +npm dist-tag ls []
      +
      +Options:
      +[-w|--workspace  [-w|--workspace  ...]]
      +[-ws|--workspaces]
      +
      +alias: dist-tags
      +
      +Run "npm help dist-tag" for more info {
      +  "code": "EUSAGE",
      +}
       `
       
       exports[`test/lib/dist-tag.js TAP ls in current package > should list available tags for current package 1`] = `
      @@ -78,7 +109,8 @@ latest: 1.0.0
       `
       
       exports[`test/lib/dist-tag.js TAP ls on missing name in current package > should throw usage error message 1`] = `
      -npm dist-tag
      +Error:
      +Usage: npm dist-tag
       
       Modify package distribution tags
       
      @@ -93,7 +125,9 @@ Options:
       
       alias: dist-tags
       
      -Run "npm help dist-tag" for more info
      +Run "npm help dist-tag" for more info {
      +  "code": "EUSAGE",
      +}
       `
       
       exports[`test/lib/dist-tag.js TAP ls on missing package > should log no dist-tag found msg 1`] = `
      @@ -133,7 +167,8 @@ exports[`test/lib/dist-tag.js TAP remove existing tag > should return success ms
       `
       
       exports[`test/lib/dist-tag.js TAP remove missing pkg name > should exit usage error message 1`] = `
      -npm dist-tag
      +Error:
      +Usage: npm dist-tag
       
       Modify package distribution tags
       
      @@ -148,7 +183,9 @@ Options:
       
       alias: dist-tags
       
      -Run "npm help dist-tag" for more info
      +Run "npm help dist-tag" for more info {
      +  "code": "EUSAGE",
      +}
       `
       
       exports[`test/lib/dist-tag.js TAP remove non-existing tag > should log error msg 1`] = `
      diff --git a/deps/npm/tap-snapshots/test/lib/init.js.test.cjs b/deps/npm/tap-snapshots/test/lib/init.js.test.cjs
      index 043d8b641dcce1..a7b007ac423005 100644
      --- a/deps/npm/tap-snapshots/test/lib/init.js.test.cjs
      +++ b/deps/npm/tap-snapshots/test/lib/init.js.test.cjs
      @@ -6,13 +6,28 @@
        */
       'use strict'
       exports[`test/lib/init.js TAP workspaces no args > should print helper info 1`] = `
      +Array [
      +  Array [
      +    String(
      +      This utility will walk you through creating a package.json file.
      +      It only covers the most common items, and tries to guess sensible defaults.
       
      +      See \`npm help init\` for definitive documentation on these fields
      +      and exactly what they do.
      +
      +      Use \`npm install \` afterwards to install a package and
      +      save it as a dependency in the package.json file.
      +
      +      Press ^C at any time to quit.
      +    ),
      +  ],
      +]
       `
       
       exports[`test/lib/init.js TAP workspaces no args, existing folder > should print helper info 1`] = `
      -
      +Array []
       `
       
       exports[`test/lib/init.js TAP workspaces with arg but missing workspace folder > should print helper info 1`] = `
      -
      +Array []
       `
      diff --git a/deps/npm/tap-snapshots/test/lib/link.js.test.cjs b/deps/npm/tap-snapshots/test/lib/link.js.test.cjs
      index d6dd376593b4df..0e20bcd994e3ab 100644
      --- a/deps/npm/tap-snapshots/test/lib/link.js.test.cjs
      +++ b/deps/npm/tap-snapshots/test/lib/link.js.test.cjs
      @@ -14,6 +14,16 @@ exports[`test/lib/link.js TAP link global linked pkg to local nm when using args
       
       `
       
      +exports[`test/lib/link.js TAP link global linked pkg to local workspace using args > should create a local symlink to global pkg 1`] = `
      +{CWD}/test/lib/tap-testdir-link-link-global-linked-pkg-to-local-workspace-using-args/my-project/node_modules/@myscope/bar -> {CWD}/test/lib/tap-testdir-link-link-global-linked-pkg-to-local-workspace-using-args/global-prefix/lib/node_modules/@myscope/bar
      +{CWD}/test/lib/tap-testdir-link-link-global-linked-pkg-to-local-workspace-using-args/my-project/node_modules/@myscope/linked -> {CWD}/test/lib/tap-testdir-link-link-global-linked-pkg-to-local-workspace-using-args/scoped-linked
      +{CWD}/test/lib/tap-testdir-link-link-global-linked-pkg-to-local-workspace-using-args/my-project/node_modules/a -> {CWD}/test/lib/tap-testdir-link-link-global-linked-pkg-to-local-workspace-using-args/global-prefix/lib/node_modules/a
      +{CWD}/test/lib/tap-testdir-link-link-global-linked-pkg-to-local-workspace-using-args/my-project/node_modules/link-me-too -> {CWD}/test/lib/tap-testdir-link-link-global-linked-pkg-to-local-workspace-using-args/link-me-too
      +{CWD}/test/lib/tap-testdir-link-link-global-linked-pkg-to-local-workspace-using-args/my-project/node_modules/test-pkg-link -> {CWD}/test/lib/tap-testdir-link-link-global-linked-pkg-to-local-workspace-using-args/test-pkg-link
      +{CWD}/test/lib/tap-testdir-link-link-global-linked-pkg-to-local-workspace-using-args/my-project/node_modules/x -> {CWD}/test/lib/tap-testdir-link-link-global-linked-pkg-to-local-workspace-using-args/my-project/packages/x
      +
      +`
      +
       exports[`test/lib/link.js TAP link pkg already in global space > should create a local symlink to global pkg 1`] = `
       {CWD}/test/lib/tap-testdir-link-link-pkg-already-in-global-space/my-project/node_modules/@myscope/linked -> {CWD}/test/lib/tap-testdir-link-link-pkg-already-in-global-space/scoped-linked
       
      @@ -28,3 +38,8 @@ exports[`test/lib/link.js TAP link to globalDir when in current working dir of p
       {CWD}/test/lib/tap-testdir-link-link-to-globalDir-when-in-current-working-dir-of-pkg-and-no-args/global-prefix/lib/node_modules/test-pkg-link -> {CWD}/test/lib/tap-testdir-link-link-to-globalDir-when-in-current-working-dir-of-pkg-and-no-args/test-pkg-link
       
       `
      +
      +exports[`test/lib/link.js TAP link ws to globalDir when workspace specified and no args > should create a global link to current pkg 1`] = `
      +{CWD}/test/lib/tap-testdir-link-link-ws-to-globalDir-when-workspace-specified-and-no-args/global-prefix/lib/node_modules/a -> {CWD}/test/lib/tap-testdir-link-link-ws-to-globalDir-when-workspace-specified-and-no-args/test-pkg-link/packages/a
      +
      +`
      diff --git a/deps/npm/tap-snapshots/test/lib/load-all-commands.js.test.cjs b/deps/npm/tap-snapshots/test/lib/load-all-commands.js.test.cjs
      index f2d40d41614946..d40be42868184c 100644
      --- a/deps/npm/tap-snapshots/test/lib/load-all-commands.js.test.cjs
      +++ b/deps/npm/tap-snapshots/test/lib/load-all-commands.js.test.cjs
      @@ -521,6 +521,8 @@ Options:
       [--strict-peer-deps] [--package-lock]
       [--omit  [--omit  ...]] [--ignore-scripts]
       [--audit] [--bin-links] [--fund] [--dry-run]
      +[-w|--workspace  [-w|--workspace  ...]]
      +[-ws|--workspaces]
       
       alias: ln
       
      diff --git a/deps/npm/tap-snapshots/test/lib/ls.js.test.cjs b/deps/npm/tap-snapshots/test/lib/ls.js.test.cjs
      index f443d9caba8954..2ed0b4b0013761 100644
      --- a/deps/npm/tap-snapshots/test/lib/ls.js.test.cjs
      +++ b/deps/npm/tap-snapshots/test/lib/ls.js.test.cjs
      @@ -70,7 +70,7 @@ test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls---dev
       
       exports[`test/lib/ls.js TAP ls --link > should output tree containing linked deps 1`] = `
       test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls---link
      -\`-- linked-dep@1.0.0 -> {CWD}/tap-testdir-ls-ls---link/linked-dep
      +\`-- linked-dep@1.0.0 -> ./linked-dep
       
       `
       
      @@ -480,24 +480,24 @@ exports[`test/lib/ls.js TAP ls json read problems > should print empty result 1`
       
       exports[`test/lib/ls.js TAP ls loading a tree containing workspaces > should filter by parent folder workspace config 1`] = `
       workspaces-tree@1.0.0 {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces
      -+-- e@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/group/e
      -\`-- f@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/group/f
      ++-- e@1.0.0 -> ./group/e
      +\`-- f@1.0.0 -> ./group/f
       
       `
       
       exports[`test/lib/ls.js TAP ls loading a tree containing workspaces > should filter single workspace 1`] = `
       workspaces-tree@1.0.0 {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces
      -+-- a@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/a
      -| \`-- d@1.0.0 deduped -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/d
      -\`-- d@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/d
      ++-- a@1.0.0 -> ./a
      +| \`-- d@1.0.0 deduped -> ./d
      +\`-- d@1.0.0 -> ./d
       
       `
       
       exports[`test/lib/ls.js TAP ls loading a tree containing workspaces > should filter using workspace config 1`] = `
       workspaces-tree@1.0.0 {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces
      -\`-- a@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/a
      +\`-- a@1.0.0 -> ./a
         +-- c@1.0.0
      -  \`-- d@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/d
      +  \`-- d@1.0.0 -> ./d
           \`-- foo@1.1.1
             \`-- bar@1.0.0
       
      @@ -505,34 +505,34 @@ workspaces-tree@1.0.0 {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspac
       
       exports[`test/lib/ls.js TAP ls loading a tree containing workspaces > should list --all workspaces properly 1`] = `
       workspaces-tree@1.0.0 {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces
      -+-- a@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/a
      ++-- a@1.0.0 -> ./a
       | +-- c@1.0.0
      -| \`-- d@1.0.0 deduped -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/d
      -+-- b@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/b
      -+-- d@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/d
      +| \`-- d@1.0.0 deduped -> ./d
      ++-- b@1.0.0 -> ./b
      ++-- d@1.0.0 -> ./d
       | \`-- foo@1.1.1
       |   \`-- bar@1.0.0
      -+-- e@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/group/e
      -\`-- f@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/group/f
      ++-- e@1.0.0 -> ./group/e
      +\`-- f@1.0.0 -> ./group/f
       
       `
       
       exports[`test/lib/ls.js TAP ls loading a tree containing workspaces > should list workspaces properly with default configs 1`] = `
       workspaces-tree@1.0.0 {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces
      -+-- a@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/a
      ++-- a@1.0.0 -> ./a
       | +-- c@1.0.0
      -| \`-- d@1.0.0 deduped -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/d
      -+-- b@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/b
      -+-- d@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/d
      +| \`-- d@1.0.0 deduped -> ./d
      ++-- b@1.0.0 -> ./b
      ++-- d@1.0.0 -> ./d
       | \`-- foo@1.1.1
      -+-- e@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/group/e
      -\`-- f@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/group/f
      ++-- e@1.0.0 -> ./group/e
      +\`-- f@1.0.0 -> ./group/f
       
       `
       
       exports[`test/lib/ls.js TAP ls loading a tree containing workspaces > should print all tree and filter by dep within only the ws subtree 1`] = `
       workspaces-tree@1.0.0 {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces
      -\`-- d@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/d
      +\`-- d@1.0.0 -> ./d
         \`-- foo@1.1.1
           \`-- bar@1.0.0
       
      @@ -567,8 +567,8 @@ test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls-no-args
       exports[`test/lib/ls.js TAP ls print deduped symlinks > should output tree containing linked deps 1`] = `
       print-deduped-symlinks@1.0.0 {CWD}/tap-testdir-ls-ls-print-deduped-symlinks
       +-- a@1.0.0
      -| \`-- b@1.0.0 deduped -> {CWD}/tap-testdir-ls-ls-print-deduped-symlinks/b
      -\`-- b@1.0.0 -> {CWD}/tap-testdir-ls-ls-print-deduped-symlinks/b
      +| \`-- b@1.0.0 deduped -> ./b
      +\`-- b@1.0.0 -> ./b
       
       `
       
      diff --git a/deps/npm/tap-snapshots/test/lib/publish.js.test.cjs b/deps/npm/tap-snapshots/test/lib/publish.js.test.cjs
      index 05f0e6580ab5ac..7a7502e02e338a 100644
      --- a/deps/npm/tap-snapshots/test/lib/publish.js.test.cjs
      +++ b/deps/npm/tap-snapshots/test/lib/publish.js.test.cjs
      @@ -5,6 +5,40 @@
        * Make sure to inspect the output below.  Do not ignore changes!
        */
       'use strict'
      +exports[`test/lib/publish.js TAP private workspaces colorless > should output all publishes 1`] = `
      +Array [
      +  "+ @npmcli/b@1.0.0",
      +]
      +`
      +
      +exports[`test/lib/publish.js TAP private workspaces colorless > should publish all non-private workspaces 1`] = `
      +Array [
      +  Object {
      +    "_id": "@npmcli/b@1.0.0",
      +    "name": "@npmcli/b",
      +    "readme": "ERROR: No README data found!",
      +    "version": "1.0.0",
      +  },
      +]
      +`
      +
      +exports[`test/lib/publish.js TAP private workspaces with color > should output all publishes 1`] = `
      +Array [
      +  "+ @npmcli/b@1.0.0",
      +]
      +`
      +
      +exports[`test/lib/publish.js TAP private workspaces with color > should publish all non-private workspaces 1`] = `
      +Array [
      +  Object {
      +    "_id": "@npmcli/b@1.0.0",
      +    "name": "@npmcli/b",
      +    "readme": "ERROR: No README data found!",
      +    "version": "1.0.0",
      +  },
      +]
      +`
      +
       exports[`test/lib/publish.js TAP shows usage with wrong set of arguments > should print usage 1`] = `
       Error: 
       Usage: npm publish
      diff --git a/deps/npm/tap-snapshots/test/lib/utils/npm-usage.js.test.cjs b/deps/npm/tap-snapshots/test/lib/utils/npm-usage.js.test.cjs
      index a81a8f44b30b90..7fdcf0c5d2dba2 100644
      --- a/deps/npm/tap-snapshots/test/lib/utils/npm-usage.js.test.cjs
      +++ b/deps/npm/tap-snapshots/test/lib/utils/npm-usage.js.test.cjs
      @@ -624,6 +624,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: ln
                           
      diff --git a/deps/npm/test/fixtures/mock-npm.js b/deps/npm/test/fixtures/mock-npm.js
      index aa8d44020ee361..c972c35b318611 100644
      --- a/deps/npm/test/fixtures/mock-npm.js
      +++ b/deps/npm/test/fixtures/mock-npm.js
      @@ -4,35 +4,54 @@
       
       const realConfig = require('../../lib/utils/config')
       
      -const mockLog = {
      -  clearProgress: () => {},
      -  disableProgress: () => {},
      -  enableProgress: () => {},
      -  http: () => {},
      -  info: () => {},
      -  levels: [],
      -  notice: () => {},
      -  pause: () => {},
      -  silly: () => {},
      -  verbose: () => {},
      -  warn: () => {},
      -}
      -const mockNpm = (base = {}) => {
      -  const config = base.config || {}
      -  const flatOptions = base.flatOptions || {}
      -  return {
      -    log: mockLog,
      -    ...base,
      -    flatOptions,
      -    config: {
      +class MockNpm {
      +  constructor (base = {}) {
      +    this._mockOutputs = []
      +    this.isMockNpm = true
      +    this.base = base
      +
      +    const config = base.config || {}
      +
      +    for (const attr in base) {
      +      if (attr !== 'config') {
      +        this[attr] = base[attr]
      +      }
      +    }
      +
      +    this.flatOptions = base.flatOptions || {}
      +    this.config = {
             // for now just set `find` to what config.find should return
             // this works cause `find` is not an existing config entry
             find: (k) => ({...realConfig.defaults, ...config})[k],
             get: (k) => ({...realConfig.defaults, ...config})[k],
             set: (k, v) => config[k] = v,
             list: [{ ...realConfig.defaults, ...config}]
      -    },
      +    }
      +    if (!this.log) {
      +      this.log = {
      +        clearProgress: () => {},
      +        disableProgress: () => {},
      +        enableProgress: () => {},
      +        http: () => {},
      +        info: () => {},
      +        levels: [],
      +        notice: () => {},
      +        pause: () => {},
      +        silly: () => {},
      +        verbose: () => {},
      +        warn: () => {},
      +      }
      +    }
      +  }
      +
      +  output(...msg) {
      +    if (this.base.output)
      +      return this.base.output(msg)
      +    this._mockOutputs.push(msg)
         }
       }
       
      -module.exports = mockNpm
      +// TODO export MockNpm, and change tests to use new MockNpm()
      +module.exports = (base = {}) => {
      +  return new MockNpm(base)
      +}
      diff --git a/deps/npm/test/lib/diff.js b/deps/npm/test/lib/diff.js
      index 355095c95786ec..7a52ea5ee0ae14 100644
      --- a/deps/npm/test/lib/diff.js
      +++ b/deps/npm/test/lib/diff.js
      @@ -4,7 +4,7 @@ const mockNpm = require('../fixtures/mock-npm')
       
       const noop = () => null
       let libnpmdiff = noop
      -let rlp = () => 'foo'
      +let rpn = () => 'foo'
       
       const config = {
         global: false,
      @@ -33,7 +33,7 @@ const mocks = {
         npmlog: { info: noop, verbose: noop },
         libnpmdiff: (...args) => libnpmdiff(...args),
         'npm-registry-fetch': async () => ({}),
      -  '../../lib/utils/read-local-package.js': async () => rlp(),
      +  '../../lib/utils/read-package-name.js': async (prefix) => rpn(prefix),
         '../../lib/utils/usage.js': () => 'usage instructions',
       }
       
      @@ -52,7 +52,7 @@ t.afterEach(() => {
         npm.globalDir = __dirname
         npm.prefix = '..'
         libnpmdiff = noop
      -  rlp = () => 'foo'
      +  rpn = () => 'foo'
       })
       
       const Diff = t.mock('../../lib/diff.js', mocks)
      @@ -77,7 +77,7 @@ t.test('no args', t => {
         })
       
         t.test('no args, missing package.json name in cwd', t => {
      -    rlp = () => undefined
      +    rpn = () => undefined
       
           diff.exec([], err => {
             t.match(
      @@ -90,7 +90,7 @@ t.test('no args', t => {
         })
       
         t.test('no args, missing package.json in cwd', t => {
      -    rlp = () => {
      +    rpn = () => {
             throw new Error('ERR')
           }
       
      @@ -109,14 +109,17 @@ t.test('no args', t => {
       
       t.test('single arg', t => {
         t.test('spec using cwd package name', t => {
      -    t.plan(3)
      +    t.plan(4)
       
      +    rpn = (prefix) => {
      +      t.equal(prefix, path, 'read-package-name gets proper prefix')
      +      return 'foo'
      +    }
           const path = t.testdir({})
           libnpmdiff = async ([a, b], opts) => {
             t.equal(a, 'foo@1.0.0', 'should forward single spec')
             t.equal(b, `file:${path}`, 'should compare to cwd')
             t.match(opts, npm.flatOptions, 'should forward flat options')
      -      t.end()
           }
       
           config.diff = ['foo@1.0.0']
      @@ -124,12 +127,13 @@ t.test('single arg', t => {
           diff.exec([], err => {
             if (err)
               throw err
      +      t.end()
           })
         })
       
         t.test('unknown spec, no package.json', t => {
           const path = t.testdir({})
      -    rlp = () => {
      +    rpn = () => {
             throw new Error('ERR')
           }
       
      @@ -182,7 +186,7 @@ t.test('single arg', t => {
         })
       
         t.test('version, no package.json', t => {
      -    rlp = () => {
      +    rpn = () => {
             throw new Error('ERR')
           }
       
      @@ -273,7 +277,7 @@ t.test('single arg', t => {
       
         t.test('unknown package name, no package.json', t => {
           const path = t.testdir({})
      -    rlp = () => {
      +    rpn = () => {
             throw new Error('ERR')
           }
       
      @@ -465,7 +469,7 @@ t.test('single arg', t => {
       
           const Diff = t.mock('../../lib/diff.js', {
             ...mocks,
      -      '../../lib/utils/read-local-package.js': async () => 'my-project',
      +      '../../lib/utils/read-package-name.js': async () => 'my-project',
             pacote: {
               packument: (spec) => {
                 t.equal(spec.name, 'lorem', 'should have expected spec name')
      @@ -502,7 +506,7 @@ t.test('single arg', t => {
       
           const Diff = t.mock('../../lib/diff.js', {
             ...mocks,
      -      '../../lib/utils/read-local-package.js': async () => 'my-project',
      +      '../../lib/utils/read-package-name.js': async () => 'my-project',
             '@npmcli/arborist': class {
               constructor () {
                 throw new Error('ERR')
      @@ -528,7 +532,7 @@ t.test('single arg', t => {
           t.plan(2)
       
           const path = t.testdir({})
      -    rlp = async () => undefined
      +    rpn = async () => undefined
           libnpmdiff = async ([a, b], opts) => {
             t.equal(a, 'bar@latest', 'should target latest tag of name')
             t.equal(b, `file:${path}`, 'should compare to cwd')
      @@ -547,7 +551,7 @@ t.test('single arg', t => {
           t.plan(2)
       
           const path = t.testdir({})
      -    rlp = async () => 'my-project'
      +    rpn = async () => 'my-project'
           libnpmdiff = async ([a, b], opts) => {
             t.equal(a, 'my-project@latest', 'should target latest tag of name')
             t.equal(b, `file:${path}`, 'should compare to cwd')
      @@ -565,7 +569,7 @@ t.test('single arg', t => {
           t.plan(2)
       
           const path = t.testdir({})
      -    rlp = async () => 'my-project'
      +    rpn = async () => 'my-project'
           libnpmdiff = async ([a, b], opts) => {
             t.equal(a, 'file:/path/to/other-dir', 'should target dir')
             t.equal(b, `file:${path}`, 'should compare to cwd')
      @@ -580,7 +584,7 @@ t.test('single arg', t => {
         })
       
         t.test('unsupported spec type', t => {
      -    rlp = async () => 'my-project'
      +    rpn = async () => 'my-project'
       
           config.diff = ['git+https://github.com/user/foo']
       
      @@ -634,7 +638,7 @@ t.test('first arg is a qualified spec', t => {
             }),
           })
       
      -    rlp = async () => 'my-project'
      +    rpn = async () => 'my-project'
           libnpmdiff = async ([a, b], opts) => {
             t.equal(a, 'bar@2.0.0', 'should set expected first spec')
             t.equal(b, `bar@file:${resolve(path, 'node_modules/bar')}`, 'should target local node_modules pkg')
      @@ -703,7 +707,7 @@ t.test('first arg is a known dependency name', t => {
             }),
           })
       
      -    rlp = async () => 'my-project'
      +    rpn = async () => 'my-project'
           libnpmdiff = async ([a, b], opts) => {
             t.equal(a, `bar@file:${resolve(path, 'node_modules/bar')}`, 'should target local node_modules pkg')
             t.equal(b, 'bar@2.0.0', 'should set expected second spec')
      @@ -743,7 +747,7 @@ t.test('first arg is a known dependency name', t => {
             }),
           })
       
      -    rlp = async () => 'my-project'
      +    rpn = async () => 'my-project'
           libnpmdiff = async ([a, b], opts) => {
             t.equal(a, `bar@file:${resolve(path, 'node_modules/bar')}`, 'should target local node_modules pkg')
             t.equal(b, `bar-fork@file:${resolve(path, 'node_modules/bar-fork')}`, 'should target fork local node_modules pkg')
      @@ -777,7 +781,7 @@ t.test('first arg is a known dependency name', t => {
             }),
           })
       
      -    rlp = async () => 'my-project'
      +    rpn = async () => 'my-project'
           libnpmdiff = async ([a, b], opts) => {
             t.equal(a, `bar@file:${resolve(path, 'node_modules/bar')}`, 'should target local node_modules pkg')
             t.equal(b, 'bar@2.0.0', 'should use package name from first arg')
      @@ -811,7 +815,7 @@ t.test('first arg is a known dependency name', t => {
             }),
           })
       
      -    rlp = async () => 'my-project'
      +    rpn = async () => 'my-project'
           libnpmdiff = async ([a, b], opts) => {
             t.equal(a, `bar@file:${resolve(path, 'node_modules/bar')}`, 'should target local node_modules pkg')
             t.equal(b, 'bar-fork@latest', 'should set expected second spec')
      @@ -865,7 +869,7 @@ t.test('first arg is a valid semver range', t => {
             }),
           })
       
      -    rlp = async () => 'my-project'
      +    rpn = async () => 'my-project'
           libnpmdiff = async ([a, b], opts) => {
             t.equal(a, 'bar@1.0.0', 'should use name from second arg')
             t.equal(b, `bar@file:${resolve(path, 'node_modules/bar')}`, 'should set expected second spec from nm')
      @@ -882,7 +886,7 @@ t.test('first arg is a valid semver range', t => {
         t.test('second arg is ALSO a semver version', t => {
           t.plan(2)
       
      -    rlp = async () => 'my-project'
      +    rpn = async () => 'my-project'
           libnpmdiff = async ([a, b], opts) => {
             t.equal(a, 'my-project@1.0.0', 'should use name from project dir')
             t.equal(b, 'my-project@2.0.0', 'should use name from project dir')
      @@ -897,7 +901,7 @@ t.test('first arg is a valid semver range', t => {
       
         t.test('second arg is ALSO a semver version BUT cwd not a project dir', t => {
           const path = t.testdir({})
      -    rlp = () => {
      +    rpn = () => {
             throw new Error('ERR')
           }
       
      @@ -916,7 +920,7 @@ t.test('first arg is a valid semver range', t => {
         t.test('second arg is an unknown dependency name', t => {
           t.plan(2)
       
      -    rlp = async () => 'my-project'
      +    rpn = async () => 'my-project'
           libnpmdiff = async ([a, b], opts) => {
             t.equal(a, 'bar@1.0.0', 'should use name from second arg')
             t.equal(b, 'bar@latest', 'should compare against latest tag')
      @@ -940,7 +944,7 @@ t.test('first arg is a valid semver range', t => {
       
           const Diff = t.mock('../../lib/diff.js', {
             ...mocks,
      -      '../../lib/utils/read-local-package.js': async () => 'my-project',
      +      '../../lib/utils/read-package-name.js': async () => 'my-project',
             '@npmcli/arborist': class {
               constructor () {
                 throw new Error('ERR')
      @@ -1003,7 +1007,7 @@ t.test('first arg is an unknown dependency name', t => {
             }),
           })
       
      -    rlp = async () => 'my-project'
      +    rpn = async () => 'my-project'
           libnpmdiff = async ([a, b], opts) => {
             t.equal(a, 'bar-fork@latest', 'should use latest tag')
             t.equal(b, `bar@file:${resolve(path, 'node_modules/bar')}`, 'should target local node_modules pkg')
      @@ -1051,7 +1055,7 @@ t.test('first arg is an unknown dependency name', t => {
           t.plan(2)
       
           const path = t.testdir({})
      -    rlp = () => {
      +    rpn = () => {
             throw new Error('ERR')
           }
           libnpmdiff = async ([a, b], opts) => {
      @@ -1117,7 +1121,7 @@ t.test('various options', t => {
           t.plan(3)
       
           const path = t.testdir({})
      -    rlp = async () => 'my-project'
      +    rpn = async () => 'my-project'
           libnpmdiff = async ([a, b], opts) => {
             t.equal(a, 'my-project@latest', 'should have default spec')
             t.equal(b, `file:${path}`, 'should compare to cwd')
      diff --git a/deps/npm/test/lib/dist-tag.js b/deps/npm/test/lib/dist-tag.js
      index 6bc17168cdce0f..9af90c309c77ca 100644
      --- a/deps/npm/test/lib/dist-tag.js
      +++ b/deps/npm/test/lib/dist-tag.js
      @@ -93,6 +93,20 @@ t.test('ls in current package', (t) => {
         })
       })
       
      +t.test('ls global', (t) => {
      +  t.teardown(() => {
      +    config.global = false
      +  })
      +  config.global = true
      +  distTag.exec(['ls'], (err) => {
      +    t.matchSnapshot(
      +      err,
      +      'should throw basic usage'
      +    )
      +    t.end()
      +  })
      +})
      +
       t.test('no args in current package', (t) => {
         npm.prefix = t.testdir({
           'package.json': JSON.stringify({
      diff --git a/deps/npm/test/lib/exec.js b/deps/npm/test/lib/exec.js
      index 33e30e24f84e0a..6924783239b49d 100644
      --- a/deps/npm/test/lib/exec.js
      +++ b/deps/npm/test/lib/exec.js
      @@ -1,8 +1,6 @@
       const t = require('tap')
       const mockNpm = require('../fixtures/mock-npm')
       const { resolve, delimiter } = require('path')
      -const OUTPUT = []
      -const output = (...msg) => OUTPUT.push(msg)
       
       const ARB_CTOR = []
       const ARB_ACTUAL_TREE = {}
      @@ -36,6 +34,7 @@ const config = {
         package: [],
         'script-shell': 'shell-cmd',
       }
      +
       const npm = mockNpm({
         flatOptions,
         config,
      @@ -53,7 +52,6 @@ const npm = mockNpm({
             LOG_WARN.push(args)
           },
         },
      -  output,
       })
       
       const RUN_SCRIPTS = []
      @@ -225,7 +223,7 @@ t.test('npm exec , run interactive shell', t => {
           ARB_CTOR.length = 0
           MKDIRPS.length = 0
           ARB_REIFY.length = 0
      -    OUTPUT.length = 0
      +    npm._mockOutputs.length = 0
           exec.exec([], er => {
             if (er)
               throw er
      @@ -256,7 +254,7 @@ t.test('npm exec , run interactive shell', t => {
           process.stdin.isTTY = true
           run(t, true, () => {
             t.strictSame(LOG_WARN, [])
      -      t.strictSame(OUTPUT, [
      +      t.strictSame(npm._mockOutputs, [
               [`\nEntering npm script environment at location:\n${process.cwd()}\nType 'exit' or ^D when finished\n`],
             ], 'printed message about interactive shell')
             t.end()
      @@ -270,7 +268,7 @@ t.test('npm exec , run interactive shell', t => {
       
           run(t, true, () => {
             t.strictSame(LOG_WARN, [])
      -      t.strictSame(OUTPUT, [
      +      t.strictSame(npm._mockOutputs, [
               [`\u001b[0m\u001b[0m\n\u001b[0mEntering npm script environment\u001b[0m\u001b[0m at location:\u001b[0m\n\u001b[0m\u001b[2m${process.cwd()}\u001b[22m\u001b[0m\u001b[1m\u001b[22m\n\u001b[1mType 'exit' or ^D when finished\u001b[22m\n\u001b[1m\u001b[22m`],
             ], 'printed message about interactive shell')
             t.end()
      @@ -282,7 +280,7 @@ t.test('npm exec , run interactive shell', t => {
           process.stdin.isTTY = false
           run(t, true, () => {
             t.strictSame(LOG_WARN, [])
      -      t.strictSame(OUTPUT, [], 'no message about interactive shell')
      +      t.strictSame(npm._mockOutputs, [], 'no message about interactive shell')
             t.end()
           })
         })
      @@ -294,7 +292,7 @@ t.test('npm exec , run interactive shell', t => {
             t.strictSame(LOG_WARN, [
               ['exec', 'Interactive mode disabled in CI environment'],
             ])
      -      t.strictSame(OUTPUT, [], 'no message about interactive shell')
      +      t.strictSame(npm._mockOutputs, [], 'no message about interactive shell')
             t.end()
           })
         })
      @@ -309,14 +307,14 @@ t.test('npm exec , run interactive shell', t => {
               throw er
       
             t.match(RUN_SCRIPTS, [{
      -        pkg: { scripts: { npx: undefined } },
      +        pkg: { scripts: { npx: /sh|cmd/ } },
             }])
       
             LOG_WARN.length = 0
             ARB_CTOR.length = 0
             MKDIRPS.length = 0
             ARB_REIFY.length = 0
      -      OUTPUT.length = 0
      +      npm._mockOutputs.length = 0
             RUN_SCRIPTS.length = 0
             t.end()
           })
      @@ -1195,7 +1193,7 @@ t.test('workspaces', t => {
                 return rej(er)
       
               t.strictSame(LOG_WARN, [])
      -        t.strictSame(OUTPUT, [
      +        t.strictSame(npm._mockOutputs, [
                 [`\nEntering npm script environment in workspace a@1.0.0 at location:\n${resolve(npm.localPrefix, 'packages/a')}\nType 'exit' or ^D when finished\n`],
               ], 'printed message about interactive shell')
               res()
      @@ -1203,14 +1201,14 @@ t.test('workspaces', t => {
           })
       
           config.color = true
      -    OUTPUT.length = 0
      +    npm._mockOutputs.length = 0
           await new Promise((res, rej) => {
             exec.execWorkspaces([], ['a'], er => {
               if (er)
                 return rej(er)
       
               t.strictSame(LOG_WARN, [])
      -        t.strictSame(OUTPUT, [
      +        t.strictSame(npm._mockOutputs, [
                 [`\u001b[0m\u001b[0m\n\u001b[0mEntering npm script environment\u001b[0m\u001b[0m in workspace \u001b[32ma@1.0.0\u001b[39m at location:\u001b[0m\n\u001b[0m\u001b[2m${resolve(npm.localPrefix, 'packages/a')}\u001b[22m\u001b[0m\u001b[1m\u001b[22m\n\u001b[1mType 'exit' or ^D when finished\u001b[22m\n\u001b[1m\u001b[22m`],
               ], 'printed message about interactive shell')
               res()
      diff --git a/deps/npm/test/lib/init.js b/deps/npm/test/lib/init.js
      index 0964bb5cedde69..268b170cb4839c 100644
      --- a/deps/npm/test/lib/init.js
      +++ b/deps/npm/test/lib/init.js
      @@ -3,7 +3,6 @@ const { resolve } = require('path')
       const t = require('tap')
       const mockNpm = require('../fixtures/mock-npm')
       
      -let result = ''
       const npmLog = {
         disableProgress: () => null,
         enableProgress: () => null,
      @@ -19,9 +18,6 @@ const config = {
       const npm = mockNpm({
         config,
         log: npmLog,
      -  output: (...msg) => {
      -    result += msg.join('\n')
      -  },
       })
       const mocks = {
         '../../lib/utils/usage.js': () => 'usage instructions',
      @@ -33,7 +29,6 @@ const _consolelog = console.log
       const noop = () => {}
       
       t.afterEach(() => {
      -  result = ''
         config.yes = true
         config.package = undefined
         npm.log = npmLog
      @@ -322,6 +317,9 @@ t.test('npm init error', t => {
       
       t.test('workspaces', t => {
         t.test('no args', t => {
      +    t.teardown(() => {
      +      npm._mockOutputs.length = 0
      +    })
           npm.localPrefix = t.testdir({
             'package.json': JSON.stringify({
               name: 'top-level',
      @@ -340,12 +338,15 @@ t.test('workspaces', t => {
             if (err)
               throw err
       
      -      t.matchSnapshot(result, 'should print helper info')
      +      t.matchSnapshot(npm._mockOutputs, 'should print helper info')
             t.end()
           })
         })
       
         t.test('no args, existing folder', t => {
      +    t.teardown(() => {
      +      npm._mockOutputs.length = 0
      +    })
           // init-package-json prints directly to console.log
           // this avoids poluting test output with those logs
           console.log = noop
      @@ -369,12 +370,15 @@ t.test('workspaces', t => {
             if (err)
               throw err
       
      -      t.matchSnapshot(result, 'should print helper info')
      +      t.matchSnapshot(npm._mockOutputs, 'should print helper info')
             t.end()
           })
         })
       
         t.test('with arg but missing workspace folder', t => {
      +    t.teardown(() => {
      +      npm._mockOutputs.length = 0
      +    })
           // init-package-json prints directly to console.log
           // this avoids poluting test output with those logs
           console.log = noop
      @@ -401,7 +405,7 @@ t.test('workspaces', t => {
             if (err)
               throw err
       
      -      t.matchSnapshot(result, 'should print helper info')
      +      t.matchSnapshot(npm._mockOutputs, 'should print helper info')
             t.end()
           })
         })
      diff --git a/deps/npm/test/lib/link.js b/deps/npm/test/lib/link.js
      index d3e66185280ae0..3cad0ff90362d8 100644
      --- a/deps/npm/test/lib/link.js
      +++ b/deps/npm/test/lib/link.js
      @@ -84,6 +84,60 @@ t.test('link to globalDir when in current working dir of pkg and no args', (t) =
         })
       })
       
      +t.test('link ws to globalDir when workspace specified and no args', (t) => {
      +  t.plan(2)
      +
      +  const testdir = t.testdir({
      +    'global-prefix': {
      +      lib: {
      +        node_modules: {
      +          a: {
      +            'package.json': JSON.stringify({
      +              name: 'a',
      +              version: '1.0.0',
      +            }),
      +          },
      +        },
      +      },
      +    },
      +    'test-pkg-link': {
      +      'package.json': JSON.stringify({
      +        name: 'test-pkg-link',
      +        version: '1.0.0',
      +        workspaces: ['packages/*'],
      +      }),
      +      packages: {
      +        a: {
      +          'package.json': JSON.stringify({
      +            name: 'a',
      +            version: '1.0.0',
      +          }),
      +        },
      +      },
      +    },
      +  })
      +  npm.globalDir = resolve(testdir, 'global-prefix', 'lib', 'node_modules')
      +  npm.prefix = resolve(testdir, 'test-pkg-link')
      +  npm.localPrefix = resolve(testdir, 'test-pkg-link')
      +
      +  reifyOutput = async () => {
      +    reifyOutput = undefined
      +
      +    const links = await printLinks({
      +      path: resolve(npm.globalDir, '..'),
      +      global: true,
      +    })
      +
      +    t.matchSnapshot(links, 'should create a global link to current pkg')
      +  }
      +
      +  // link.workspaces = ['a']
      +  // link.workspacePaths = [resolve(testdir, 'test-pkg-link/packages/a')]
      +  link.execWorkspaces([], ['a'], (err) => {
      +    t.error(err, 'should not error out')
      +  })
      +})
      +
       t.test('link global linked pkg to local nm when using args', (t) => {
         t.plan(2)
       
      @@ -192,6 +246,124 @@ t.test('link global linked pkg to local nm when using args', (t) => {
         })
       })
       
      +t.test('link global linked pkg to local workspace using args', (t) => {
      +  t.plan(2)
      +
      +  const testdir = t.testdir({
      +    'global-prefix': {
      +      lib: {
      +        node_modules: {
      +          '@myscope': {
      +            foo: {
      +              'package.json': JSON.stringify({
      +                name: '@myscope/foo',
      +                version: '1.0.0',
      +              }),
      +            },
      +            bar: {
      +              'package.json': JSON.stringify({
      +                name: '@myscope/bar',
      +                version: '1.0.0',
      +              }),
      +            },
      +            linked: t.fixture('symlink', '../../../../scoped-linked'),
      +          },
      +          a: {
      +            'package.json': JSON.stringify({
      +              name: 'a',
      +              version: '1.0.0',
      +            }),
      +          },
      +          b: {
      +            'package.json': JSON.stringify({
      +              name: 'b',
      +              version: '1.0.0',
      +            }),
      +          },
      +          'test-pkg-link': t.fixture('symlink', '../../../test-pkg-link'),
      +        },
      +      },
      +    },
      +    'test-pkg-link': {
      +      'package.json': JSON.stringify({
      +        name: 'test-pkg-link',
      +        version: '1.0.0',
      +      }),
      +    },
      +    'link-me-too': {
      +      'package.json': JSON.stringify({
      +        name: 'link-me-too',
      +        version: '1.0.0',
      +      }),
      +    },
      +    'scoped-linked': {
      +      'package.json': JSON.stringify({
      +        name: '@myscope/linked',
      +        version: '1.0.0',
      +      }),
      +    },
      +    'my-project': {
      +      'package.json': JSON.stringify({
      +        name: 'my-project',
      +        version: '1.0.0',
      +        workspaces: ['packages/*'],
      +      }),
      +      packages: {
      +        x: {
      +          'package.json': JSON.stringify({
      +            name: 'x',
      +            version: '1.0.0',
      +            dependencies: {
      +              foo: '^1.0.0',
      +            },
      +          }),
      +        },
      +      },
      +      node_modules: {
      +        foo: {
      +          'package.json': JSON.stringify({
      +            name: 'foo',
      +            version: '1.0.0',
      +          }),
      +        },
      +      },
      +    },
      +  })
      +  npm.globalDir = resolve(testdir, 'global-prefix', 'lib', 'node_modules')
      +  npm.prefix = resolve(testdir, 'my-project')
      +  npm.localPrefix = resolve(testdir, 'my-project')
      +
      +  const _cwd = process.cwd()
      +  process.chdir(npm.prefix)
      +
      +  reifyOutput = async () => {
      +    reifyOutput = undefined
      +    process.chdir(_cwd)
      +
      +    const links = await printLinks({
      +      path: npm.prefix,
      +    })
      +
      +    t.matchSnapshot(links, 'should create a local symlink to global pkg')
      +  }
      +
      +  // installs examples for:
      +  // - test-pkg-link: pkg linked to globalDir from local fs
      +  // - @myscope/linked: scoped pkg linked to globalDir from local fs
      +  // - @myscope/bar: prev installed scoped package available in globalDir
      +  // - a: prev installed package available in globalDir
      +  // - file:./link-me-too: pkg that needs to be reified in globalDir first
      +  link.execWorkspaces([
      +    'test-pkg-link',
      +    '@myscope/linked',
      +    '@myscope/bar',
      +    'a',
      +    'file:../link-me-too',
      +  ], ['x'], (err) => {
      +    t.error(err, 'should not error out')
      +  })
      +})
      +
       t.test('link pkg already in global space', (t) => {
         t.plan(3)
       
      diff --git a/deps/npm/test/lib/ls.js b/deps/npm/test/lib/ls.js
      index 2cde319463a9ea..ecdede809df207 100644
      --- a/deps/npm/test/lib/ls.js
      +++ b/deps/npm/test/lib/ls.js
      @@ -90,7 +90,12 @@ const diffDepTypesNmFixture = {
       }
       
       let result = ''
      -const LS = require('../../lib/ls.js')
      +const LS = t.mock('../../lib/ls.js', {
      +  path: {
      +    ...require('path'),
      +    sep: '/',
      +  },
      +})
       const config = {
         all: true,
         color: false,
      diff --git a/deps/npm/test/lib/owner.js b/deps/npm/test/lib/owner.js
      index 4af8d1ebbb8fa0..10ceb03030a5ac 100644
      --- a/deps/npm/test/lib/owner.js
      +++ b/deps/npm/test/lib/owner.js
      @@ -1,16 +1,18 @@
       const t = require('tap')
      +const mockNpm = require('../fixtures/mock-npm.js')
       
       let result = ''
      -let readLocalPkgResponse = null
      +let readPackageNamePrefix = null
      +let readPackageNameResponse = null
       
       const noop = () => null
       
      -const npm = {
      -  flatOptions: {},
      +const npm = mockNpm({
         output: (msg) => {
           result = result ? `${result}\n${msg}` : msg
         },
      -}
      +})
      +
       const npmFetch = { json: noop }
       const npmlog = { error: noop, info: noop, verbose: noop }
       const pacote = { packument: noop }
      @@ -20,7 +22,10 @@ const mocks = {
         'npm-registry-fetch': npmFetch,
         pacote,
         '../../lib/utils/otplease.js': async (opts, fn) => fn({ otp: '123456', opts }),
      -  '../../lib/utils/read-local-package.js': async () => readLocalPkgResponse,
      +  '../../lib/utils/read-package-name.js': async (prefix) => {
      +    readPackageNamePrefix = prefix
      +    return readPackageNameResponse
      +  },
         '../../lib/utils/usage.js': () => 'usage instructions',
       }
       
      @@ -47,11 +52,11 @@ t.test('owner no args', t => {
       })
       
       t.test('owner ls no args', t => {
      -  t.plan(4)
      +  t.plan(5)
       
         result = ''
       
      -  readLocalPkgResponse = '@npmcli/map-workspaces'
      +  readPackageNameResponse = '@npmcli/map-workspaces'
         pacote.packument = async (spec, opts) => {
           t.equal(spec.name, '@npmcli/map-workspaces', 'should use expect pkg name')
           t.match(
      @@ -65,14 +70,29 @@ t.test('owner ls no args', t => {
           return { maintainers: npmcliMaintainers }
         }
         t.teardown(() => {
      +    npm.prefix = null
           result = ''
           pacote.packument = noop
      -    readLocalPkgResponse = null
      +    readPackageNameResponse = null
         })
      +  npm.prefix = 'test-npm-prefix'
       
         owner.exec(['ls'], err => {
           t.error(err, 'npm owner ls no args')
           t.matchSnapshot(result, 'should output owners of cwd package')
      +    t.equal(readPackageNamePrefix, 'test-npm-prefix', 'read-package-name gets npm.prefix')
      +  })
      +})
      +
      +t.test('owner ls global', t => {
      +  t.teardown(() => {
      +    npm.config.set('global', false)
      +  })
      +  npm.config.set('global', true)
      +
      +  owner.exec(['ls'], err => {
      +    t.match(err, /usage instructions/, 'should throw usage instructions if no cwd package available')
      +    t.end()
         })
       })
       
      @@ -93,7 +113,7 @@ t.test('owner ls fails to retrieve packument', t => {
         t.plan(4)
       
         result = ''
      -  readLocalPkgResponse = '@npmcli/map-workspaces'
      +  readPackageNameResponse = '@npmcli/map-workspaces'
         pacote.packument = () => {
           throw new Error('ERR')
         }
      @@ -233,7 +253,7 @@ t.test('owner add  ', t => {
       
       t.test('owner add  cwd package', t => {
         result = ''
      -  readLocalPkgResponse = '@npmcli/map-workspaces'
      +  readPackageNameResponse = '@npmcli/map-workspaces'
         npmFetch.json = async (uri, opts) => {
           // retrieve user info from couchdb request
           if (uri === '/-/user/org.couchdb.user:foo') {
      @@ -253,7 +273,7 @@ t.test('owner add  cwd package', t => {
         })
         t.teardown(() => {
           result = ''
      -    readLocalPkgResponse = null
      +    readPackageNameResponse = null
           npmFetch.json = noop
           pacote.packument = noop
         })
      @@ -308,7 +328,7 @@ t.test('owner add   already an owner', t => {
       
       t.test('owner add   fails to retrieve user', t => {
         result = ''
      -  readLocalPkgResponse =
      +  readPackageNameResponse =
         npmFetch.json = async (uri, opts) => {
           // retrieve borked user info from couchdb request
           if (uri === '/-/user/org.couchdb.user:foo')
      @@ -324,7 +344,7 @@ t.test('owner add   fails to retrieve user', t => {
         })
         t.teardown(() => {
           result = ''
      -    readLocalPkgResponse = null
      +    readPackageNameResponse = null
           npmFetch.json = noop
           pacote.packument = noop
         })
      @@ -465,6 +485,18 @@ t.test('owner add no user', t => {
         })
       })
       
      +t.test('owner add no pkg global', t => {
      +  t.teardown(() => {
      +    npm.config.set('global', false)
      +  })
      +  npm.config.set('global', true)
      +
      +  owner.exec(['add', 'gar'], err => {
      +    t.match(err, /usage instructions/, 'should throw usage instructions if user provided')
      +    t.end()
      +  })
      +})
      +
       t.test('owner add  no cwd package', t => {
         result = ''
         t.teardown(() => {
      @@ -581,7 +613,7 @@ t.test('owner rm   not a current owner', t => {
       
       t.test('owner rm  cwd package', t => {
         result = ''
      -  readLocalPkgResponse = '@npmcli/map-workspaces'
      +  readPackageNameResponse = '@npmcli/map-workspaces'
         npmFetch.json = async (uri, opts) => {
           // retrieve user info from couchdb request
           if (uri === '/-/user/org.couchdb.user:ruyadorno') {
      @@ -601,7 +633,7 @@ t.test('owner rm  cwd package', t => {
         })
         t.teardown(() => {
           result = ''
      -    readLocalPkgResponse = null
      +    readPackageNameResponse = null
           npmFetch.json = noop
           pacote.packument = noop
         })
      @@ -615,7 +647,7 @@ t.test('owner rm  cwd package', t => {
       
       t.test('owner rm  only user', t => {
         result = ''
      -  readLocalPkgResponse = 'ipt'
      +  readPackageNameResponse = 'ipt'
         npmFetch.json = async (uri, opts) => {
           // retrieve user info from couchdb request
           if (uri === '/-/user/org.couchdb.user:ruyadorno') {
      @@ -636,7 +668,7 @@ t.test('owner rm  only user', t => {
         })
         t.teardown(() => {
           result = ''
      -    readLocalPkgResponse = null
      +    readPackageNameResponse = null
           npmFetch.json = noop
           pacote.packument = noop
         })
      @@ -664,6 +696,18 @@ t.test('owner rm no user', t => {
         })
       })
       
      +t.test('owner rm no pkg global', t => {
      +  t.teardown(() => {
      +    npm.config.set('global', false)
      +  })
      +  npm.config.set('global', true)
      +
      +  owner.exec(['rm', 'gar'], err => {
      +    t.match(err, /usage instructions/, 'should throw usage instructions if user provided')
      +    t.end()
      +  })
      +})
      +
       t.test('owner rm  no cwd package', t => {
         result = ''
         t.teardown(() => {
      @@ -693,15 +737,15 @@ t.test('completion', async t => {
         // npm owner rm completion is async
         t.test('completion npm owner rm', async t => {
           t.plan(2)
      -    readLocalPkgResponse = '@npmcli/map-workspaces'
      +    readPackageNameResponse = '@npmcli/map-workspaces'
           pacote.packument = async spec => {
      -      t.equal(spec.name, readLocalPkgResponse, 'should use package spec')
      +      t.equal(spec.name, readPackageNameResponse, 'should use package spec')
             return {
               maintainers: npmcliMaintainers,
             }
           }
           t.teardown(() => {
      -      readLocalPkgResponse = null
      +      readPackageNameResponse = null
             pacote.packument = noop
           })
       
      @@ -718,17 +762,27 @@ t.test('completion', async t => {
           t.end()
         })
       
      +  t.test('completion npm owner rm global', async t => {
      +    t.teardown(() => {
      +      npm.config.set('global', false)
      +    })
      +    npm.config.set('global', true)
      +    const res = await owner.completion({ conf: { argv: { remain: ['npm', 'owner', 'rm'] } } })
      +    t.strictSame(res, [], 'should have no owners to autocomplete if global')
      +    t.end()
      +  })
      +
         t.test('completion npm owner rm no owners found', async t => {
           t.plan(2)
      -    readLocalPkgResponse = '@npmcli/map-workspaces'
      +    readPackageNameResponse = '@npmcli/map-workspaces'
           pacote.packument = async spec => {
      -      t.equal(spec.name, readLocalPkgResponse, 'should use package spec')
      +      t.equal(spec.name, readPackageNameResponse, 'should use package spec')
             return {
               maintainers: [],
             }
           }
           t.teardown(() => {
      -      readLocalPkgResponse = null
      +      readPackageNameResponse = null
             pacote.packument = noop
           })
       
      diff --git a/deps/npm/test/lib/publish.js b/deps/npm/test/lib/publish.js
      index 80f3f7ccc639e3..e34f00b477ee13 100644
      --- a/deps/npm/test/lib/publish.js
      +++ b/deps/npm/test/lib/publish.js
      @@ -617,3 +617,148 @@ t.test('workspaces', (t) => {
         })
         t.end()
       })
      +
      +t.test('private workspaces', (t) => {
      +  const testDir = t.testdir({
      +    'package.json': JSON.stringify({
      +      name: 'workspaces-project',
      +      version: '1.0.0',
      +      workspaces: ['packages/*'],
      +    }),
      +    packages: {
      +      a: {
      +        'package.json': JSON.stringify({
      +          name: '@npmcli/a',
      +          version: '1.0.0',
      +          private: true,
      +        }),
      +      },
      +      b: {
      +        'package.json': JSON.stringify({
      +          name: '@npmcli/b',
      +          version: '1.0.0',
      +        }),
      +      },
      +    },
      +  })
      +
      +  const publishes = []
      +  const outputs = []
      +  t.beforeEach(() => {
      +    npm.config.set('json', false)
      +    outputs.length = 0
      +    publishes.length = 0
      +  })
      +  const mocks = {
      +    '../../lib/utils/tar.js': {
      +      getContents: (manifest) => ({
      +        id: manifest._id,
      +      }),
      +      logTar: () => {},
      +    },
      +    libnpmpublish: {
      +      publish: (manifest, tarballData, opts) => {
      +        if (manifest.private) {
      +          throw Object.assign(
      +            new Error('private pkg'),
      +            { code: 'EPRIVATE' }
      +          )
      +        }
      +        publishes.push(manifest)
      +      },
      +    },
      +  }
      +  const npm = mockNpm({
      +    output: (o) => {
      +      outputs.push(o)
      +    },
      +  })
      +  npm.localPrefix = testDir
      +  npm.config.getCredentialsByURI = (uri) => {
      +    return { token: 'some.registry.token' }
      +  }
      +
      +  t.test('with color', t => {
      +    const Publish = t.mock('../../lib/publish.js', {
      +      ...mocks,
      +      npmlog: {
      +        notice () {},
      +        verbose () {},
      +        warn (title, msg) {
      +          t.equal(title, 'publish', 'should use publish warn title')
      +          t.match(
      +            msg,
      +            'Skipping workspace \u001b[32m@npmcli/a\u001b[39m, marked as \u001b[1mprivate\u001b[22m',
      +            'should display skip private workspace warn msg'
      +          )
      +        },
      +      },
      +    })
      +    const publish = new Publish(npm)
      +
      +    npm.color = true
      +    publish.execWorkspaces([], [], (err) => {
      +      t.notOk(err)
      +      t.matchSnapshot(publishes, 'should publish all non-private workspaces')
      +      t.matchSnapshot(outputs, 'should output all publishes')
      +      npm.color = false
      +      t.end()
      +    })
      +  })
      +
      +  t.test('colorless', t => {
      +    const Publish = t.mock('../../lib/publish.js', {
      +      ...mocks,
      +      npmlog: {
      +        notice () {},
      +        verbose () {},
      +        warn (title, msg) {
      +          t.equal(title, 'publish', 'should use publish warn title')
      +          t.equal(
      +            msg,
      +            'Skipping workspace @npmcli/a, marked as private',
      +            'should display skip private workspace warn msg'
      +          )
      +        },
      +      },
      +    })
      +    const publish = new Publish(npm)
      +
      +    publish.execWorkspaces([], [], (err) => {
      +      t.notOk(err)
      +      t.matchSnapshot(publishes, 'should publish all non-private workspaces')
      +      t.matchSnapshot(outputs, 'should output all publishes')
      +      t.end()
      +    })
      +  })
      +
      +  t.test('unexpected error', t => {
      +    const Publish = t.mock('../../lib/publish.js', {
      +      ...mocks,
      +      libnpmpublish: {
      +        publish: (manifest, tarballData, opts) => {
      +          if (manifest.private)
      +            throw new Error('ERR')
      +
      +          publishes.push(manifest)
      +        },
      +      },
      +      npmlog: {
      +        notice () {},
      +        verbose () {},
      +      },
      +    })
      +    const publish = new Publish(npm)
      +
      +    publish.execWorkspaces([], [], (err) => {
      +      t.match(
      +        err,
      +        /ERR/,
      +        'should throw unexpected error'
      +      )
      +      t.end()
      +    })
      +  })
      +
      +  t.end()
      +})
      diff --git a/deps/npm/test/lib/utils/read-local-package.js b/deps/npm/test/lib/utils/read-package-name.js
      similarity index 55%
      rename from deps/npm/test/lib/utils/read-local-package.js
      rename to deps/npm/test/lib/utils/read-package-name.js
      index 966e74a7ab7f4c..c8f88bacd4b840 100644
      --- a/deps/npm/test/lib/utils/read-local-package.js
      +++ b/deps/npm/test/lib/utils/read-package-name.js
      @@ -1,13 +1,8 @@
       const t = require('tap')
       const mockNpm = require('../../fixtures/mock-npm')
      +const npm = mockNpm()
       
      -const config = {
      -  json: false,
      -  global: false,
      -}
      -const npm = mockNpm({ config })
      -
      -const readLocalPackageName = require('../../../lib/utils/read-local-package.js')
      +const readPackageName = require('../../../lib/utils/read-package-name.js')
       
       t.test('read local package.json', async (t) => {
         npm.prefix = t.testdir({
      @@ -16,7 +11,7 @@ t.test('read local package.json', async (t) => {
             version: '1.0.0',
           }),
         })
      -  const packageName = await readLocalPackageName(npm)
      +  const packageName = await readPackageName(npm.prefix)
         t.equal(
           packageName,
           'my-local-package',
      @@ -31,22 +26,10 @@ t.test('read local scoped-package.json', async (t) => {
             version: '1.0.0',
           }),
         })
      -  const packageName = await readLocalPackageName(npm)
      +  const packageName = await readPackageName(npm.prefix)
         t.equal(
           packageName,
           '@my-scope/my-local-package',
           'should retrieve scoped package name'
         )
       })
      -
      -t.test('read using --global', async (t) => {
      -  npm.prefix = t.testdir({})
      -  config.global = true
      -  const packageName = await readLocalPackageName(npm)
      -  t.equal(
      -    packageName,
      -    undefined,
      -    'should not retrieve a package name'
      -  )
      -  config.global = false
      -})
      diff --git a/deps/npm/test/lib/utils/reify-output.js b/deps/npm/test/lib/utils/reify-output.js
      index 2142566b90dea6..3ffbdf86a29896 100644
      --- a/deps/npm/test/lib/utils/reify-output.js
      +++ b/deps/npm/test/lib/utils/reify-output.js
      @@ -187,31 +187,154 @@ t.test('print appropriate message for many packages', (t) => {
         })
       })
       
      -t.test('no output when silent', t => {
      -  npm.output = out => {
      -    t.fail('should not get output when silent', { actual: out })
      -  }
      -  t.teardown(() => log.level = 'warn')
      -  log.level = 'silent'
      -  reifyOutput(npm, {
      -    actualTree: { inventory: { size: 999 }, children: [] },
      -    auditReport: {
      -      toJSON: () => {
      -        throw new Error('this should not get called')
      -      },
      -      vulnerabilities: {},
      -      metadata: {
      -        vulnerabilities: {
      -          total: 99,
      -        },
      +t.test('showing and not showing audit report', async t => {
      +  const auditReport = {
      +    toJSON: () => auditReport,
      +    auditReportVersion: 2,
      +    vulnerabilities: {
      +      minimist: {
      +        name: 'minimist',
      +        severity: 'low',
      +        via: [
      +          {
      +            id: 1179,
      +            url: 'https://npmjs.com/advisories/1179',
      +            title: 'Prototype Pollution',
      +            severity: 'low',
      +            vulnerable_versions: '<0.2.1 || >=1.0.0 <1.2.3',
      +          },
      +        ],
      +        effects: [],
      +        range: '<0.2.1 || >=1.0.0 <1.2.3',
      +        nodes: [
      +          'node_modules/minimist',
      +        ],
      +        fixAvailable: true,
             },
           },
      -    diff: {
      -      children: [
      -        { action: 'ADD', ideal: { location: 'loc' } },
      -      ],
      +    metadata: {
      +      vulnerabilities: {
      +        info: 0,
      +        low: 1,
      +        moderate: 0,
      +        high: 0,
      +        critical: 0,
      +        total: 1,
      +      },
      +      dependencies: {
      +        prod: 1,
      +        dev: 0,
      +        optional: 0,
      +        peer: 0,
      +        peerOptional: 0,
      +        total: 1,
      +      },
           },
      +  }
      +
      +  t.test('no output when silent', t => {
      +    npm.output = out => {
      +      t.fail('should not get output when silent', { actual: out })
      +    }
      +    t.teardown(() => log.level = 'warn')
      +    log.level = 'silent'
      +    reifyOutput(npm, {
      +      actualTree: { inventory: { size: 999 }, children: [] },
      +      auditReport,
      +      diff: {
      +        children: [
      +          { action: 'ADD', ideal: { location: 'loc' } },
      +        ],
      +      },
      +    })
      +    t.end()
         })
      +
      +  t.test('output when not silent', t => {
      +    const OUT = []
      +    npm.output = out => {
      +      OUT.push(out)
      +    }
      +    reifyOutput(npm, {
      +      actualTree: { inventory: new Map(), children: [] },
      +      auditReport,
      +      diff: {
      +        children: [
      +          { action: 'ADD', ideal: { location: 'loc' } },
      +        ],
      +      },
      +    })
      +    t.match(OUT.join('\n'), /Run `npm audit` for details\.$/, 'got audit report')
      +    t.end()
      +  })
      +
      +  for (const json of [true, false]) {
      +    t.test(`json=${json}`, t => {
      +      t.teardown(() => {
      +        delete npm.flatOptions.json
      +      })
      +      npm.flatOptions.json = json
      +      t.test('set exit code when cmd is audit', t => {
      +        npm.output = () => {}
      +        const { exitCode } = process
      +        const { command } = npm
      +        npm.flatOptions.auditLevel = 'low'
      +        t.teardown(() => {
      +          delete npm.flatOptions.auditLevel
      +          npm.command = command
      +          // only set exitCode back if we're passing tests
      +          if (t.passing())
      +            process.exitCode = exitCode
      +        })
      +
      +        process.exitCode = 0
      +        npm.command = 'audit'
      +        reifyOutput(npm, {
      +          actualTree: { inventory: new Map(), children: [] },
      +          auditReport,
      +          diff: {
      +            children: [
      +              { action: 'ADD', ideal: { location: 'loc' } },
      +            ],
      +          },
      +        })
      +
      +        t.equal(process.exitCode, 1, 'set exit code')
      +        t.end()
      +      })
      +
      +      t.test('do not set exit code when cmd is install', t => {
      +        npm.output = () => {}
      +        const { exitCode } = process
      +        const { command } = npm
      +        npm.flatOptions.auditLevel = 'low'
      +        t.teardown(() => {
      +          delete npm.flatOptions.auditLevel
      +          npm.command = command
      +          // only set exitCode back if we're passing tests
      +          if (t.passing())
      +            process.exitCode = exitCode
      +        })
      +
      +        process.exitCode = 0
      +        npm.command = 'install'
      +        reifyOutput(npm, {
      +          actualTree: { inventory: new Map(), children: [] },
      +          auditReport,
      +          diff: {
      +            children: [
      +              { action: 'ADD', ideal: { location: 'loc' } },
      +            ],
      +          },
      +        })
      +
      +        t.equal(process.exitCode, 0, 'did not set exit code')
      +        t.end()
      +      })
      +      t.end()
      +    })
      +  }
      +
         t.end()
       })