diff --git a/deps/npm/docs/content/commands/npm-audit.md b/deps/npm/docs/content/commands/npm-audit.md index 704d7a15fb8f19..94b16b27bd7ed9 100644 --- a/deps/npm/docs/content/commands/npm-audit.md +++ b/deps/npm/docs/content/commands/npm-audit.md @@ -232,6 +232,7 @@ mistakes, unnecessary performance degradation, and malicious input. * Allow unpublishing all versions of a published package. * Allow conflicting peerDependencies to be installed in the root project. * Implicitly set `--yes` during `npm init`. +* Allow clobbering existing values in `npm pkg` If you don't have a clear idea of what you want to do, it is strongly recommended that you do not use this option! @@ -243,6 +244,9 @@ recommended that you do not use this option! Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. #### `package-lock-only` diff --git a/deps/npm/docs/content/commands/npm-ci.md b/deps/npm/docs/content/commands/npm-ci.md index 9645bae7e2f43d..31c92b13c5cdd3 100644 --- a/deps/npm/docs/content/commands/npm-ci.md +++ b/deps/npm/docs/content/commands/npm-ci.md @@ -69,6 +69,16 @@ cache: +#### `audit` + +* Default: true +* Type: Boolean + +When "true" submit audit reports alongside the current npm command to the +default registry and all registries configured for scopes. See the +documentation for [`npm audit`](/commands/npm-audit) for details on what is +submitted. + #### `ignore-scripts` * Default: false diff --git a/deps/npm/docs/content/commands/npm-config.md b/deps/npm/docs/content/commands/npm-config.md index f2868cb8909a91..9e76a23671e861 100644 --- a/deps/npm/docs/content/commands/npm-config.md +++ b/deps/npm/docs/content/commands/npm-config.md @@ -104,6 +104,9 @@ global config. Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. #### `global` @@ -128,6 +131,14 @@ folder instead of the current working directory. See The command to run for `npm edit` and `npm config edit`. +#### `location` + +* Default: "user" unless `--global` is passed, which will also set this value + to "global" +* Type: "global", "user", or "project" + +When passed to `npm config` this refers to which config file to use. + #### `long` * Default: false diff --git a/deps/npm/docs/content/commands/npm-dedupe.md b/deps/npm/docs/content/commands/npm-dedupe.md index fbccc410532924..324e6a71b7a3eb 100644 --- a/deps/npm/docs/content/commands/npm-dedupe.md +++ b/deps/npm/docs/content/commands/npm-dedupe.md @@ -164,9 +164,10 @@ will *not* run any pre- or post-scripts. * Default: true * Type: Boolean -When "true" submit audit reports alongside `npm install` runs to the default -registry and all registries configured for scopes. See the documentation for -[`npm audit`](/commands/npm-audit) for details on what is submitted. +When "true" submit audit reports alongside the current npm command to the +default registry and all registries configured for scopes. See the +documentation for [`npm audit`](/commands/npm-audit) for details on what is +submitted. #### `bin-links` diff --git a/deps/npm/docs/content/commands/npm-explain.md b/deps/npm/docs/content/commands/npm-explain.md index 0e50d7ae43343b..3a87ee8e438bad 100644 --- a/deps/npm/docs/content/commands/npm-explain.md +++ b/deps/npm/docs/content/commands/npm-explain.md @@ -63,6 +63,9 @@ node_modules/nyc/node_modules/find-up Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. #### `workspace` diff --git a/deps/npm/docs/content/commands/npm-find-dupes.md b/deps/npm/docs/content/commands/npm-find-dupes.md index 28281d5678ab70..3b28f6443decda 100644 --- a/deps/npm/docs/content/commands/npm-find-dupes.md +++ b/deps/npm/docs/content/commands/npm-find-dupes.md @@ -107,9 +107,10 @@ will *not* run any pre- or post-scripts. * Default: true * Type: Boolean -When "true" submit audit reports alongside `npm install` runs to the default -registry and all registries configured for scopes. See the documentation for -[`npm audit`](/commands/npm-audit) for details on what is submitted. +When "true" submit audit reports alongside the current npm command to the +default registry and all registries configured for scopes. See the +documentation for [`npm audit`](/commands/npm-audit) for details on what is +submitted. #### `bin-links` diff --git a/deps/npm/docs/content/commands/npm-fund.md b/deps/npm/docs/content/commands/npm-fund.md index 3dc5292b490a17..ec5f5a37fdb716 100644 --- a/deps/npm/docs/content/commands/npm-fund.md +++ b/deps/npm/docs/content/commands/npm-fund.md @@ -73,6 +73,9 @@ test-workspaces-fund@1.0.0 Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. #### `browser` diff --git a/deps/npm/docs/content/commands/npm-init.md b/deps/npm/docs/content/commands/npm-init.md index 23e8e70d9e9132..54c3bdb4b74ab9 100644 --- a/deps/npm/docs/content/commands/npm-init.md +++ b/deps/npm/docs/content/commands/npm-init.md @@ -175,6 +175,7 @@ mistakes, unnecessary performance degradation, and malicious input. * Allow unpublishing all versions of a published package. * Allow conflicting peerDependencies to be installed in the root project. * Implicitly set `--yes` during `npm init`. +* Allow clobbering existing values in `npm pkg` If you don't have a clear idea of what you want to do, it is strongly recommended that you do not use this option! diff --git a/deps/npm/docs/content/commands/npm-install-ci-test.md b/deps/npm/docs/content/commands/npm-install-ci-test.md index c337905a0566e9..2640311cf94be7 100644 --- a/deps/npm/docs/content/commands/npm-install-ci-test.md +++ b/deps/npm/docs/content/commands/npm-install-ci-test.md @@ -20,6 +20,16 @@ This command runs `npm ci` followed immediately by `npm test`. +#### `audit` + +* Default: true +* Type: Boolean + +When "true" submit audit reports alongside the current npm command to the +default registry and all registries configured for scopes. See the +documentation for [`npm audit`](/commands/npm-audit) for details on what is +submitted. + #### `ignore-scripts` * Default: false diff --git a/deps/npm/docs/content/commands/npm-install-test.md b/deps/npm/docs/content/commands/npm-install-test.md index deefbd96b52fd1..c8533cafedd7a3 100644 --- a/deps/npm/docs/content/commands/npm-install-test.md +++ b/deps/npm/docs/content/commands/npm-install-test.md @@ -149,9 +149,10 @@ will *not* run any pre- or post-scripts. * Default: true * Type: Boolean -When "true" submit audit reports alongside `npm install` runs to the default -registry and all registries configured for scopes. See the documentation for -[`npm audit`](/commands/npm-audit) for details on what is submitted. +When "true" submit audit reports alongside the current npm command to the +default registry and all registries configured for scopes. See the +documentation for [`npm audit`](/commands/npm-audit) for details on what is +submitted. #### `bin-links` diff --git a/deps/npm/docs/content/commands/npm-install.md b/deps/npm/docs/content/commands/npm-install.md index e5091e6604c917..70d4c0d46ffeb2 100644 --- a/deps/npm/docs/content/commands/npm-install.md +++ b/deps/npm/docs/content/commands/npm-install.md @@ -533,9 +533,10 @@ will *not* run any pre- or post-scripts. * Default: true * Type: Boolean -When "true" submit audit reports alongside `npm install` runs to the default -registry and all registries configured for scopes. See the documentation for -[`npm audit`](/commands/npm-audit) for details on what is submitted. +When "true" submit audit reports alongside the current npm command to the +default registry and all registries configured for scopes. See the +documentation for [`npm audit`](/commands/npm-audit) for details on what is +submitted. #### `bin-links` diff --git a/deps/npm/docs/content/commands/npm-link.md b/deps/npm/docs/content/commands/npm-link.md index b1c6066768a99e..c7b385009519a0 100644 --- a/deps/npm/docs/content/commands/npm-link.md +++ b/deps/npm/docs/content/commands/npm-link.md @@ -233,9 +233,10 @@ will *not* run any pre- or post-scripts. * Default: true * Type: Boolean -When "true" submit audit reports alongside `npm install` runs to the default -registry and all registries configured for scopes. See the documentation for -[`npm audit`](/commands/npm-audit) for details on what is submitted. +When "true" submit audit reports alongside the current npm command to the +default registry and all registries configured for scopes. See the +documentation for [`npm audit`](/commands/npm-audit) for details on what is +submitted. #### `bin-links` diff --git a/deps/npm/docs/content/commands/npm-ls.md b/deps/npm/docs/content/commands/npm-ls.md index 1f401fa956ff8d..350f40a9991e52 100644 --- a/deps/npm/docs/content/commands/npm-ls.md +++ b/deps/npm/docs/content/commands/npm-ls.md @@ -91,6 +91,9 @@ upon by the current project. Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. #### `long` diff --git a/deps/npm/docs/content/commands/npm-org.md b/deps/npm/docs/content/commands/npm-org.md index e6df560acfba36..269f5cc3ee5b88 100644 --- a/deps/npm/docs/content/commands/npm-org.md +++ b/deps/npm/docs/content/commands/npm-org.md @@ -87,6 +87,9 @@ password, npm will prompt on the command line for one. Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. #### `parseable` diff --git a/deps/npm/docs/content/commands/npm-outdated.md b/deps/npm/docs/content/commands/npm-outdated.md index bc9263d7aeda73..40e5feafd4cc61 100644 --- a/deps/npm/docs/content/commands/npm-outdated.md +++ b/deps/npm/docs/content/commands/npm-outdated.md @@ -104,6 +104,9 @@ upon by the current project. Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. #### `long` diff --git a/deps/npm/docs/content/commands/npm-pack.md b/deps/npm/docs/content/commands/npm-pack.md index 95070262784378..cd4a175919e7eb 100644 --- a/deps/npm/docs/content/commands/npm-pack.md +++ b/deps/npm/docs/content/commands/npm-pack.md @@ -34,6 +34,9 @@ Note: This is NOT honored by other network related commands, eg `dist-tags`, Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. #### `pack-destination` diff --git a/deps/npm/docs/content/commands/npm-pkg.md b/deps/npm/docs/content/commands/npm-pkg.md new file mode 100644 index 00000000000000..78b13cf9e9a000 --- /dev/null +++ b/deps/npm/docs/content/commands/npm-pkg.md @@ -0,0 +1,245 @@ +--- +title: npm-pkg +section: 1 +description: Manages your package.json +--- + +### Synopsis + +```bash +npm pkg get [ [. ...]] +npm pkg set = [.= ...] +npm pkg delete [. ...] +``` + +### Description + +A command that automates the management of `package.json` files. +`npm pkg` provide 3 different sub commands that allow you to modify or retrieve +values for given object keys in your `packge.json`. + +The syntax to retrieve and set fields is a dot separated representation of +the nested object properties to be found within your `package.json`, it's the +same notation used in [`npm view`](/commands/npm-view) to retrieve information +from the registry manifest, below you can find more examples on how to use it. + +Returned values are always in **json** format. + +* `npm pkg get ` + + Retrieves a value `key`, defined in your `package.json` file. + + For example, in order to retrieve the name of the current package, you + can run: + + ```bash + npm pkg get name + ``` + + It's also possible to retrieve multiple values at once: + + ```bash + npm pkg get name version + ``` + + You can view child fields by separating them with a period. To retrieve + the value of a test `script` value, you would run the following command: + + ```bash + npm pkg get scripts.test + ``` + + For fields that are arrays, requesting a non-numeric field will return + all of the values from the objects in the list. For example, to get all + the contributor emails for a package, you would run: + + ```bash + npm pkg get contributors.email + ``` + + You may also use numeric indices in square braces to specifically select + an item in an array field. To just get the email address of the first + contributor in the list, you can run: + + ```bash + npm pkg get contributors[0].email + ``` + +* `npm pkg set =` + + Sets a `value` in your `package.json` based on the `field` value. When + saving to your `package.json` file the same set of rules used during + `npm install` and other cli commands that touches the `package.json` file + are used, making sure to respect the existing indentation and possibly + applying some validation prior to saving values to the file. + + The same syntax used to retrieve values from your package can also be used + to define new properties or overriding existing ones, below are some + examples of how the dot separated syntax can be used to edit your + `package.json` file. + + Defining a new bin named `mynewcommand` in your `package.json` that points + to a file `cli.js`: + + ```bash + npm pkg set bin.mynewcommand=cli.js + ``` + + Setting multiple fields at once is also possible: + + ```bash + npm pkg set description='Awesome package' engines.node='>=10' + ``` + + It's also possible to add to array values, for example to add a new + contributor entry: + + ```bash + npm pkg set contributors[0].name='Foo' contributors[0].email='foo@bar.ca' + ``` + + You may also append items to the end of an array using the special + empty bracket notation: + + ```bash + npm pkg set contributors[].name='Foo' contributors[].name='Bar' + ``` + + It's also possible to parse values as json prior to saving them to your + `package.json` file, for example in order to set a `"private": true` + property: + + ```bash + npm pkg set private=true --json + ``` + + It also enables saving values as numbers: + + ```bash + npm pkg set tap.timeout=60 --json + ``` + +* `npm pkg delete ` + + Deletes a `key` from your `package.json` + + The same syntax used to set values from your package can also be used + to remove existing ones. For example, in order to remove a script named + build: + + ```bash + npm pkg delete scripts.build + ``` + +### Workspaces support + +You can set/get/delete items across your configured workspaces by using the +`workspace` or `workspaces` config options. + +For example, setting a `funding` value across all configured workspaces +of a project: + +```bash +npm pkg set funding=https://example.com --ws +``` + +When using `npm pkg get` to retrieve info from your configured workspaces, the +returned result will be in a json format in which top level keys are the +names of each workspace, the values of these keys will be the result values +returned from each of the configured workspaces, e.g: + +``` +npm pkg get name version --ws +{ + "a": { + "name": "a", + "version": "1.0.0" + }, + "b": { + "name": "b", + "version": "1.0.0" + } +} +``` + +### Configuration + + + +#### `force` + +* Default: false +* Type: Boolean + +Removes various protections against unfortunate side effects, common +mistakes, unnecessary performance degradation, and malicious input. + +* Allow clobbering non-npm files in global installs. +* Allow the `npm version` command to work on an unclean git repository. +* Allow deleting the cache folder with `npm cache clean`. +* Allow installing packages that have an `engines` declaration requiring a + different version of npm. +* Allow installing packages that have an `engines` declaration requiring a + different version of `node`, even if `--engine-strict` is enabled. +* Allow `npm audit fix` to install modules outside your stated dependency + range (including SemVer-major changes). +* Allow unpublishing all versions of a published package. +* Allow conflicting peerDependencies to be installed in the root project. +* Implicitly set `--yes` during `npm init`. +* Allow clobbering existing values in `npm pkg` + +If you don't have a clear idea of what you want to do, it is strongly +recommended that you do not use this option! + +#### `json` + +* Default: false +* Type: Boolean + +Whether or not to output JSON data, rather than the normal output. + +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + +Not supported by all npm commands. + +#### `workspace` + +* Default: +* Type: String (can be set multiple times) + +Enable running a command in the context of the configured workspaces of the +current project while filtering by running only the workspaces defined by +this configuration option. + +Valid values for the `workspace` config are either: + +* Workspace names +* Path to a workspace directory +* Path to a parent workspace directory (will result to selecting all of the + nested workspaces) + +When set for the `npm init` command, this may be set to the folder of a +workspace which does not yet exist, to create the folder and set it up as a +brand new workspace within the project. + +This value is not exported to the environment for child processes. + +#### `workspaces` + +* Default: false +* Type: Boolean + +Enable running a command in the context of **all** the configured +workspaces. + +This value is not exported to the environment for child processes. + + +## See Also + +* [npm install](/commands/npm-install) +* [npm init](/commands/npm-init) +* [npm config](/commands/npm-config) +* [npm set-script](/commands/npm-set-script) +* [workspaces](/using-npm/workspaces) diff --git a/deps/npm/docs/content/commands/npm-profile.md b/deps/npm/docs/content/commands/npm-profile.md index 63aa46540d32d5..079440d7858153 100644 --- a/deps/npm/docs/content/commands/npm-profile.md +++ b/deps/npm/docs/content/commands/npm-profile.md @@ -91,6 +91,9 @@ The base URL of the npm registry. Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. #### `parseable` diff --git a/deps/npm/docs/content/commands/npm-prune.md b/deps/npm/docs/content/commands/npm-prune.md index ecb6bdcd6cb148..d9b5b068f7a4b3 100644 --- a/deps/npm/docs/content/commands/npm-prune.md +++ b/deps/npm/docs/content/commands/npm-prune.md @@ -75,6 +75,9 @@ Note: This is NOT honored by other network related commands, eg `dist-tags`, Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. #### `workspace` diff --git a/deps/npm/docs/content/commands/npm-search.md b/deps/npm/docs/content/commands/npm-search.md index 08c955e64b5554..e30287635b56f6 100644 --- a/deps/npm/docs/content/commands/npm-search.md +++ b/deps/npm/docs/content/commands/npm-search.md @@ -55,6 +55,9 @@ Show extended information in `ls`, `search`, and `help-search`. Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. #### `color` diff --git a/deps/npm/docs/content/commands/npm-team.md b/deps/npm/docs/content/commands/npm-team.md index 31b09c7ce22b75..c7d5defcc63c1d 100644 --- a/deps/npm/docs/content/commands/npm-team.md +++ b/deps/npm/docs/content/commands/npm-team.md @@ -138,6 +138,9 @@ Output parseable results from commands that write to standard output. For Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. diff --git a/deps/npm/docs/content/commands/npm-unpublish.md b/deps/npm/docs/content/commands/npm-unpublish.md index bc8fbc7a53b3d4..82779ab65938c9 100644 --- a/deps/npm/docs/content/commands/npm-unpublish.md +++ b/deps/npm/docs/content/commands/npm-unpublish.md @@ -82,6 +82,7 @@ mistakes, unnecessary performance degradation, and malicious input. * Allow unpublishing all versions of a published package. * Allow conflicting peerDependencies to be installed in the root project. * Implicitly set `--yes` during `npm init`. +* Allow clobbering existing values in `npm pkg` If you don't have a clear idea of what you want to do, it is strongly recommended that you do not use this option! diff --git a/deps/npm/docs/content/commands/npm-update.md b/deps/npm/docs/content/commands/npm-update.md index 4c9271c6633c3a..c4f7694e19a81d 100644 --- a/deps/npm/docs/content/commands/npm-update.md +++ b/deps/npm/docs/content/commands/npm-update.md @@ -15,7 +15,9 @@ aliases: up, upgrade ### Description This command will update all the packages listed to the latest version -(specified by the `tag` config), respecting semver. +(specified by the `tag` config), respecting the semver constraints of +both your package and its dependencies (if they also require the same +package). It will also install missing packages. @@ -101,6 +103,39 @@ Then `npm update` will install `dep1@0.4.1`, because that is the highest-sorting version that satisfies `^0.4.0` (`>= 0.4.0 <0.5.0`) +#### Subdependencies + +Suppose your app now also has a dependency on `dep2` + +```json +{ + "name": "my-app", + "dependencies": { + "dep1": "^1.0.0", + "dep2": "1.0.0" + } +} +``` + +and `dep2` itself depends on this limited range of `dep1` + +```json +{ +"name": "dep2", + "dependencies": { + "dep1": "~1.1.1" + } +} +``` + +Then `npm update` will install `dep1@1.1.2` because that is the highest +version that `dep2` allows. npm will prioritize having a single version +of `dep1` in your tree rather than two when that single version can +satisfy the semver requirements of multiple dependencies in your tree. +In this case if you really did need your package to use a newer version +you would need to use `npm install`. + + #### Updating Globally-Installed Packages `npm update -g` will apply the `update` action to each globally installed @@ -220,9 +255,10 @@ will *not* run any pre- or post-scripts. * Default: true * Type: Boolean -When "true" submit audit reports alongside `npm install` runs to the default -registry and all registries configured for scopes. See the documentation for -[`npm audit`](/commands/npm-audit) for details on what is submitted. +When "true" submit audit reports alongside the current npm command to the +default registry and all registries configured for scopes. See the +documentation for [`npm audit`](/commands/npm-audit) for details on what is +submitted. #### `bin-links` diff --git a/deps/npm/docs/content/commands/npm-version.md b/deps/npm/docs/content/commands/npm-version.md index d24207d1e7e341..a3e34153a06da8 100644 --- a/deps/npm/docs/content/commands/npm-version.md +++ b/deps/npm/docs/content/commands/npm-version.md @@ -47,6 +47,9 @@ Tag the commit when using the `npm version` command. Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. #### `preid` diff --git a/deps/npm/docs/content/commands/npm-view.md b/deps/npm/docs/content/commands/npm-view.md index 8cbd3267b4bf05..b3d5df86e34a40 100644 --- a/deps/npm/docs/content/commands/npm-view.md +++ b/deps/npm/docs/content/commands/npm-view.md @@ -49,7 +49,7 @@ npm view opts@$(npm view ronn dependencies.opts) For fields that are arrays, requesting a non-numeric field will return all of the values from the objects in the list. For example, to get all -the contributor names for the `express` package, you would run: +the contributor email addresses for the `express` package, you would run: ```bash npm view express contributors.email @@ -105,6 +105,9 @@ npm view connect versions Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. #### `workspace` diff --git a/deps/npm/docs/content/configuring-npm/folders.md b/deps/npm/docs/content/configuring-npm/folders.md index 75e31cd733161f..218870765b2625 100644 --- a/deps/npm/docs/content/configuring-npm/folders.md +++ b/deps/npm/docs/content/configuring-npm/folders.md @@ -45,14 +45,16 @@ Global installs on Windows go to `{prefix}/node_modules` (that is, no Scoped packages are installed the same way, except they are grouped together in a sub-folder of the relevant `node_modules` folder with the name of that scope prefix by the @ symbol, e.g. `npm install @myorg/package` would place -the package in `{prefix}/node_modules/@myorg/package`. See [`scope`](/using-npm/scope) for more details. +the package in `{prefix}/node_modules/@myorg/package`. See +[`scope`](/using-npm/scope) for more details. If you wish to `require()` a package, then install it locally. #### Executables When in global mode, executables are linked into `{prefix}/bin` on Unix, -or directly into `{prefix}` on Windows. +or directly into `{prefix}` on Windows. Ensure that path is in your +terminal's `PATH` environment to run them. When in local mode, executables are linked into `./node_modules/.bin` so that they can be made available to scripts run diff --git a/deps/npm/docs/content/configuring-npm/package-json.md b/deps/npm/docs/content/configuring-npm/package-json.md index 5cacf68ba175f9..0fc5dc5075ee3c 100644 --- a/deps/npm/docs/content/configuring-npm/package-json.md +++ b/deps/npm/docs/content/configuring-npm/package-json.md @@ -341,9 +341,12 @@ install into the PATH. npm makes this pretty easy (in fact, it uses this feature to install the "npm" executable.) To use this, supply a `bin` field in your package.json which is a map of -command name to local file name. On install, npm will symlink that file -into `prefix/bin` for global installs, or `./node_modules/.bin/` for local -installs. +command name to local file name. When this package is installed +globally, that file will be linked where global bins go so it is +available to run by name. When this package is installed as a +dependency in another package, the file will be linked where it will be +available to that package either directly by `npm exec` or by name in other +scripts when invoking them via `npm run-script`. For example, myapp could have this: @@ -388,6 +391,9 @@ executable! Note that you can also set the executable files using [directories.bin](#directoriesbin). +See [folders](/configuring-npm/folders#executables) for more info on +executables. + ### man Specify either a single file or an array of filenames to put in place for diff --git a/deps/npm/docs/content/using-npm/config.md b/deps/npm/docs/content/using-npm/config.md index 1036895101fcc1..c4d1afed35cc8b 100644 --- a/deps/npm/docs/content/using-npm/config.md +++ b/deps/npm/docs/content/using-npm/config.md @@ -67,6 +67,7 @@ The following shorthands are parsed on the command-line: * `--desc`: `--description` * `-f`: `--force` * `-g`: `--global` +* `-L`: `--location` * `-d`: `--loglevel info` * `-s`: `--loglevel silent` * `--silent`: `--loglevel silent` @@ -170,9 +171,10 @@ to the same value as the current version. * Default: true * Type: Boolean -When "true" submit audit reports alongside `npm install` runs to the default -registry and all registries configured for scopes. See the documentation for -[`npm audit`](/commands/npm-audit) for details on what is submitted. +When "true" submit audit reports alongside the current npm command to the +default registry and all registries configured for scopes. See the +documentation for [`npm audit`](/commands/npm-audit) for details on what is +submitted. #### `audit-level` @@ -495,6 +497,7 @@ mistakes, unnecessary performance degradation, and malicious input. * Allow unpublishing all versions of a published package. * Allow conflicting peerDependencies to be installed in the root project. * Implicitly set `--yes` during `npm init`. +* Allow clobbering existing values in `npm pkg` If you don't have a clear idea of what you want to do, it is strongly recommended that you do not use this option! @@ -694,6 +697,9 @@ number, if not already set in package.json. Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. #### `key` @@ -753,6 +759,14 @@ Used with `npm ls`, limiting output to only those packages that are linked. The IP address of the local interface to use when making connections to the npm registry. Must be IPv4 in versions of Node prior to 0.12. +#### `location` + +* Default: "user" unless `--global` is passed, which will also set this value + to "global" +* Type: "global", "user", or "project" + +When passed to `npm config` this refers to which config file to use. + #### `loglevel` * Default: "notice" diff --git a/deps/npm/docs/content/using-npm/scripts.md b/deps/npm/docs/content/using-npm/scripts.md index 8df9660ca8f4cd..8fd5c5c0dbc9d8 100644 --- a/deps/npm/docs/content/using-npm/scripts.md +++ b/deps/npm/docs/content/using-npm/scripts.md @@ -54,7 +54,8 @@ situations. These scripts happen in addition to the `pre`, `post`, the prepare script will be run, before the package is packaged and installed. -* As of `npm@7` these scripts run in the background +* As of `npm@7` these scripts run in the background. + To see the output, run with: `--foreground-scripts`. **prepublish** (DEPRECATED) * Does not run during `npm publish`, but does run during `npm ci` @@ -303,8 +304,8 @@ Scripts are run by passing the line as a script argument to `sh`. If the script exits with a code other than 0, then this will abort the process. -Note that these script files don't have to be nodejs or even -javascript programs. They just have to be some kind of executable +Note that these script files don't have to be Node.js or even +JavaScript programs. They just have to be some kind of executable file. ### Best Practices diff --git a/deps/npm/docs/content/using-npm/workspaces.md b/deps/npm/docs/content/using-npm/workspaces.md index 829168864abe45..7cc125b3c7a7cc 100644 --- a/deps/npm/docs/content/using-npm/workspaces.md +++ b/deps/npm/docs/content/using-npm/workspaces.md @@ -37,7 +37,7 @@ Workspaces are usually defined via the `workspaces` property of the Given the above `package.json` example living at a current working directory `.` that contains a folder named `workspace-a` that itself contains -a `package.json` inside it, defining a nodejs package, e.g: +a `package.json` inside it, defining a Node.js package, e.g: ``` . diff --git a/deps/npm/docs/output/commands/npm-audit.html b/deps/npm/docs/output/commands/npm-audit.html index a1c58d89633742..5cffb546dc721c 100644 --- a/deps/npm/docs/output/commands/npm-audit.html +++ b/deps/npm/docs/output/commands/npm-audit.html @@ -309,6 +309,7 @@

force

  • Allow unpublishing all versions of a published package.
  • Allow conflicting peerDependencies to be installed in the root project.
  • Implicitly set --yes during npm init.
  • +
  • Allow clobbering existing values in npm pkg
  • If you don’t have a clear idea of what you want to do, it is strongly recommended that you do not use this option!

    @@ -318,6 +319,10 @@

    json

  • Type: Boolean
  • Whether or not to output JSON data, rather than the normal output.

    +
      +
    • In npm pkg set it enables parsing set values with JSON.parse() before +saving them to your package.json.
    • +

    Not supported by all npm commands.

    package-lock-only

      diff --git a/deps/npm/docs/output/commands/npm-ci.html b/deps/npm/docs/output/commands/npm-ci.html index 82049f7287d04a..9f5c85b36374da 100644 --- a/deps/npm/docs/output/commands/npm-ci.html +++ b/deps/npm/docs/output/commands/npm-ci.html @@ -141,7 +141,7 @@

      npm-ci

      Table of contents

      - +

      Synopsis

      @@ -193,6 +193,15 @@

      Example

      Configuration

      +

      audit

      +
        +
      • Default: true
      • +
      • Type: Boolean
      • +
      +

      When “true” submit audit reports alongside the current npm command to the +default registry and all registries configured for scopes. See the +documentation for npm audit for details on what is +submitted.

      ignore-scripts

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

      +
        +
      • In npm pkg set it enables parsing set values with JSON.parse() before +saving them to your package.json.
      • +

      Not supported by all npm commands.

      global

        @@ -228,6 +232,13 @@

        editor

      • Type: String

      The command to run for npm edit and npm config edit.

      +

      location

      +
        +
      • Default: “user” unless --global is passed, which will also set this value +to “global”
      • +
      • Type: “global”, “user”, or “project”
      • +
      +

      When passed to npm config this refers to which config file to use.

      long

      • Default: false
      • diff --git a/deps/npm/docs/output/commands/npm-dedupe.html b/deps/npm/docs/output/commands/npm-dedupe.html index c1fe98aeead67b..9de232141e17a2 100644 --- a/deps/npm/docs/output/commands/npm-dedupe.html +++ b/deps/npm/docs/output/commands/npm-dedupe.html @@ -269,9 +269,10 @@

        audit

      • Default: true
      • Type: Boolean
      -

      When “true” submit audit reports alongside npm install runs to the default -registry and all registries configured for scopes. See the documentation for -npm audit for details on what is submitted.

      +

      When “true” submit audit reports alongside the current npm command to the +default registry and all registries configured for scopes. See the +documentation for npm audit for details on what is +submitted.

      • Default: true
      • diff --git a/deps/npm/docs/output/commands/npm-explain.html b/deps/npm/docs/output/commands/npm-explain.html index 1c3afda5a1632f..decfd4d556e6e3 100644 --- a/deps/npm/docs/output/commands/npm-explain.html +++ b/deps/npm/docs/output/commands/npm-explain.html @@ -190,6 +190,10 @@

        json

      • Type: Boolean

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

      +
        +
      • In npm pkg set it enables parsing set values with JSON.parse() before +saving them to your package.json.
      • +

      Not supported by all npm commands.

      workspace

        diff --git a/deps/npm/docs/output/commands/npm-find-dupes.html b/deps/npm/docs/output/commands/npm-find-dupes.html index d727f561dfefca..9f6c4de7857077 100644 --- a/deps/npm/docs/output/commands/npm-find-dupes.html +++ b/deps/npm/docs/output/commands/npm-find-dupes.html @@ -228,9 +228,10 @@

        audit

      • Default: true
      • Type: Boolean
      -

      When “true” submit audit reports alongside npm install runs to the default -registry and all registries configured for scopes. See the documentation for -npm audit for details on what is submitted.

      +

      When “true” submit audit reports alongside the current npm command to the +default registry and all registries configured for scopes. See the +documentation for npm audit for details on what is +submitted.

      • Default: true
      • diff --git a/deps/npm/docs/output/commands/npm-fund.html b/deps/npm/docs/output/commands/npm-fund.html index a37ff56e145118..074ac10573592e 100644 --- a/deps/npm/docs/output/commands/npm-fund.html +++ b/deps/npm/docs/output/commands/npm-fund.html @@ -195,6 +195,10 @@

        json

      • Type: Boolean

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

      +
        +
      • In npm pkg set it enables parsing set values with JSON.parse() before +saving them to your package.json.
      • +

      Not supported by all npm commands.

      browser

        diff --git a/deps/npm/docs/output/commands/npm-init.html b/deps/npm/docs/output/commands/npm-init.html index 79538c36ace191..eaa5dfe0f72c88 100644 --- a/deps/npm/docs/output/commands/npm-init.html +++ b/deps/npm/docs/output/commands/npm-init.html @@ -273,6 +273,7 @@

        force

      • Allow unpublishing all versions of a published package.
      • Allow conflicting peerDependencies to be installed in the root project.
      • Implicitly set --yes during npm init.
      • +
      • Allow clobbering existing values in npm pkg

      If you don’t have a clear idea of what you want to do, it is strongly recommended that you do not use this option!

      diff --git a/deps/npm/docs/output/commands/npm-install-ci-test.html b/deps/npm/docs/output/commands/npm-install-ci-test.html index 3982ad2da20f19..d7414ff56cf904 100644 --- a/deps/npm/docs/output/commands/npm-install-ci-test.html +++ b/deps/npm/docs/output/commands/npm-install-ci-test.html @@ -141,7 +141,7 @@

      npm-install-ci-test

      Table of contents

      - +

      Synopsis

      @@ -154,6 +154,15 @@

      Description

      Configuration

      +

      audit

      +
        +
      • Default: true
      • +
      • Type: Boolean
      • +
      +

      When “true” submit audit reports alongside the current npm command to the +default registry and all registries configured for scopes. See the +documentation for npm audit for details on what is +submitted.

      ignore-scripts

      • Default: false
      • diff --git a/deps/npm/docs/output/commands/npm-install-test.html b/deps/npm/docs/output/commands/npm-install-test.html index be781628967ce0..d2f536e5d811c6 100644 --- a/deps/npm/docs/output/commands/npm-install-test.html +++ b/deps/npm/docs/output/commands/npm-install-test.html @@ -267,9 +267,10 @@

        audit

      • Default: true
      • Type: Boolean
      -

      When “true” submit audit reports alongside npm install runs to the default -registry and all registries configured for scopes. See the documentation for -npm audit for details on what is submitted.

      +

      When “true” submit audit reports alongside the current npm command to the +default registry and all registries configured for scopes. See the +documentation for npm audit for details on what is +submitted.

      • Default: true
      • diff --git a/deps/npm/docs/output/commands/npm-install.html b/deps/npm/docs/output/commands/npm-install.html index a081c98e1b263c..cebc5ac780edd4 100644 --- a/deps/npm/docs/output/commands/npm-install.html +++ b/deps/npm/docs/output/commands/npm-install.html @@ -589,9 +589,10 @@

        audit

      • Default: true
      • Type: Boolean
      -

      When “true” submit audit reports alongside npm install runs to the default -registry and all registries configured for scopes. See the documentation for -npm audit for details on what is submitted.

      +

      When “true” submit audit reports alongside the current npm command to the +default registry and all registries configured for scopes. See the +documentation for npm audit for details on what is +submitted.

      • Default: true
      • diff --git a/deps/npm/docs/output/commands/npm-link.html b/deps/npm/docs/output/commands/npm-link.html index d558cb9d0a535b..6ac2699867e6d2 100644 --- a/deps/npm/docs/output/commands/npm-link.html +++ b/deps/npm/docs/output/commands/npm-link.html @@ -323,9 +323,10 @@

        audit

      • Default: true
      • Type: Boolean
      -

      When “true” submit audit reports alongside npm install runs to the default -registry and all registries configured for scopes. See the documentation for -npm audit for details on what is submitted.

      +

      When “true” submit audit reports alongside the current npm command to the +default registry and all registries configured for scopes. See the +documentation for npm audit for details on what is +submitted.

      • Default: true
      • diff --git a/deps/npm/docs/output/commands/npm-ls.html b/deps/npm/docs/output/commands/npm-ls.html index e79b119cee8bab..8af88b78dd57b3 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.19.1 /path/to/npm
        +
        npm@7.20.0 /path/to/npm
         └─┬ init-package-json@0.0.4
           └── promzard@0.1.5
         
        @@ -208,6 +208,10 @@

        json

      • Type: Boolean

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

      +
        +
      • In npm pkg set it enables parsing set values with JSON.parse() before +saving them to your package.json.
      • +

      Not supported by all npm commands.

      long

        diff --git a/deps/npm/docs/output/commands/npm-org.html b/deps/npm/docs/output/commands/npm-org.html index 3b6df5123f9e23..b9b976f05f9ef6 100644 --- a/deps/npm/docs/output/commands/npm-org.html +++ b/deps/npm/docs/output/commands/npm-org.html @@ -197,6 +197,10 @@

        json

      • Type: Boolean

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

      +
        +
      • In npm pkg set it enables parsing set values with JSON.parse() before +saving them to your package.json.
      • +

      Not supported by all npm commands.

      parseable

        diff --git a/deps/npm/docs/output/commands/npm-outdated.html b/deps/npm/docs/output/commands/npm-outdated.html index 3a45257b3d1065..2584460fe6b9dc 100644 --- a/deps/npm/docs/output/commands/npm-outdated.html +++ b/deps/npm/docs/output/commands/npm-outdated.html @@ -230,6 +230,10 @@

        json

      • Type: Boolean

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

      +
        +
      • In npm pkg set it enables parsing set values with JSON.parse() before +saving them to your package.json.
      • +

      Not supported by all npm commands.

      long

        diff --git a/deps/npm/docs/output/commands/npm-pack.html b/deps/npm/docs/output/commands/npm-pack.html index 622d88306cadc4..a569ff799aab1d 100644 --- a/deps/npm/docs/output/commands/npm-pack.html +++ b/deps/npm/docs/output/commands/npm-pack.html @@ -167,6 +167,10 @@

        json

      • Type: Boolean

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

      +
        +
      • In npm pkg set it enables parsing set values with JSON.parse() before +saving them to your package.json.
      • +

      Not supported by all npm commands.

      pack-destination

        diff --git a/deps/npm/docs/output/commands/npm-pkg.html b/deps/npm/docs/output/commands/npm-pkg.html new file mode 100644 index 00000000000000..1f8a86e76e5725 --- /dev/null +++ b/deps/npm/docs/output/commands/npm-pkg.html @@ -0,0 +1,343 @@ + +npm-pkg + + + + + +
        +
        +

        npm-pkg

        +Manages your package.json +
        + +
        +

        Table of contents

        + +
        + +

        Synopsis

        +
        npm pkg get [<field> [.<subfield> ...]]
        +npm pkg set <field>=<value> [.<subfield>=<value> ...]
        +npm pkg delete <field> [.<subfield> ...]
        +
        +

        Description

        +

        A command that automates the management of package.json files. +npm pkg provide 3 different sub commands that allow you to modify or retrieve +values for given object keys in your packge.json.

        +

        The syntax to retrieve and set fields is a dot separated representation of +the nested object properties to be found within your package.json, it’s the +same notation used in npm view to retrieve information +from the registry manifest, below you can find more examples on how to use it.

        +

        Returned values are always in json format.

        +
          +
        • +

          npm pkg get <field>

          +

          Retrieves a value key, defined in your package.json file.

          +

          For example, in order to retrieve the name of the current package, you +can run:

          +
          npm pkg get name
          +
          +

          It’s also possible to retrieve multiple values at once:

          +
          npm pkg get name version
          +
          +

          You can view child fields by separating them with a period. To retrieve +the value of a test script value, you would run the following command:

          +
          npm pkg get scripts.test
          +
          +

          For fields that are arrays, requesting a non-numeric field will return +all of the values from the objects in the list. For example, to get all +the contributor emails for a package, you would run:

          +
          npm pkg get contributors.email
          +
          +

          You may also use numeric indices in square braces to specifically select +an item in an array field. To just get the email address of the first +contributor in the list, you can run:

          +
          npm pkg get contributors[0].email
          +
          +
        • +
        • +

          npm pkg set <field>=<value>

          +

          Sets a value in your package.json based on the field value. When +saving to your package.json file the same set of rules used during +npm install and other cli commands that touches the package.json file +are used, making sure to respect the existing indentation and possibly +applying some validation prior to saving values to the file.

          +

          The same syntax used to retrieve values from your package can also be used +to define new properties or overriding existing ones, below are some +examples of how the dot separated syntax can be used to edit your +package.json file.

          +

          Defining a new bin named mynewcommand in your package.json that points +to a file cli.js:

          +
          npm pkg set bin.mynewcommand=cli.js
          +
          +

          Setting multiple fields at once is also possible:

          +
          npm pkg set description='Awesome package' engines.node='>=10'
          +
          +

          It’s also possible to add to array values, for example to add a new +contributor entry:

          +
          npm pkg set contributors[0].name='Foo' contributors[0].email='foo@bar.ca'
          +
          +

          You may also append items to the end of an array using the special +empty bracket notation:

          +
          npm pkg set contributors[].name='Foo' contributors[].name='Bar'
          +
          +

          It’s also possible to parse values as json prior to saving them to your +package.json file, for example in order to set a "private": true +property:

          +
          npm pkg set private=true --json
          +
          +

          It also enables saving values as numbers:

          +
          npm pkg set tap.timeout=60 --json
          +
          +
        • +
        • +

          npm pkg delete <key>

          +

          Deletes a key from your package.json

          +

          The same syntax used to set values from your package can also be used +to remove existing ones. For example, in order to remove a script named +build:

          +
          npm pkg delete scripts.build
          +
          +
        • +
        +

        Workspaces support

        +

        You can set/get/delete items across your configured workspaces by using the +workspace or workspaces config options.

        +

        For example, setting a funding value across all configured workspaces +of a project:

        +
        npm pkg set funding=https://example.com --ws
        +
        +

        When using npm pkg get to retrieve info from your configured workspaces, the +returned result will be in a json format in which top level keys are the +names of each workspace, the values of these keys will be the result values +returned from each of the configured workspaces, e.g:

        +
        npm pkg get name version --ws
        +{
        +  "a": {
        +    "name": "a",
        +    "version": "1.0.0"
        +  },
        +  "b": {
        +    "name": "b",
        +    "version": "1.0.0"
        +  }
        +}
        +
        +

        Configuration

        + + +

        force

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

        Removes various protections against unfortunate side effects, common +mistakes, unnecessary performance degradation, and malicious input.

        +
          +
        • Allow clobbering non-npm files in global installs.
        • +
        • Allow the npm version command to work on an unclean git repository.
        • +
        • Allow deleting the cache folder with npm cache clean.
        • +
        • Allow installing packages that have an engines declaration requiring a +different version of npm.
        • +
        • Allow installing packages that have an engines declaration requiring a +different version of node, even if --engine-strict is enabled.
        • +
        • Allow npm audit fix to install modules outside your stated dependency +range (including SemVer-major changes).
        • +
        • Allow unpublishing all versions of a published package.
        • +
        • Allow conflicting peerDependencies to be installed in the root project.
        • +
        • Implicitly set --yes during npm init.
        • +
        • Allow clobbering existing values in npm pkg
        • +
        +

        If you don’t have a clear idea of what you want to do, it is strongly +recommended that you do not use this option!

        +

        json

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

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

        +
          +
        • In npm pkg set it enables parsing set values with JSON.parse() before +saving them to your package.json.
        • +
        +

        Not supported by all npm commands.

        +

        workspace

        +
          +
        • Default:
        • +
        • Type: String (can be set multiple times)
        • +
        +

        Enable running a command in the context of the configured workspaces of the +current project while filtering by running only the workspaces defined by +this configuration option.

        +

        Valid values for the workspace config are either:

        +
          +
        • Workspace names
        • +
        • Path to a workspace directory
        • +
        • Path to a parent workspace directory (will result to selecting all of the +nested workspaces)
        • +
        +

        When set for the npm init command, this may be set to the folder of a +workspace which does not yet exist, to create the folder and set it up as a +brand new workspace within the project.

        +

        This value is not exported to the environment for child processes.

        +

        workspaces

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

        Enable running a command in the context of all the configured +workspaces.

        +

        This value is not exported to the environment for child processes.

        + +

        See Also

        + +
        + + +
        + + + + \ No newline at end of file diff --git a/deps/npm/docs/output/commands/npm-profile.html b/deps/npm/docs/output/commands/npm-profile.html index 3f79af93ea3c8c..0c24fffead70d8 100644 --- a/deps/npm/docs/output/commands/npm-profile.html +++ b/deps/npm/docs/output/commands/npm-profile.html @@ -227,6 +227,10 @@

        json

      • Type: Boolean

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

      +
        +
      • In npm pkg set it enables parsing set values with JSON.parse() before +saving them to your package.json.
      • +

      Not supported by all npm commands.

      parseable

        diff --git a/deps/npm/docs/output/commands/npm-prune.html b/deps/npm/docs/output/commands/npm-prune.html index 6011d914b0034e..2dcfe0e1ce5483 100644 --- a/deps/npm/docs/output/commands/npm-prune.html +++ b/deps/npm/docs/output/commands/npm-prune.html @@ -197,6 +197,10 @@

        json

      • Type: Boolean

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

      +
        +
      • In npm pkg set it enables parsing set values with JSON.parse() before +saving them to your package.json.
      • +

      Not supported by all npm commands.

      workspace

        diff --git a/deps/npm/docs/output/commands/npm-search.html b/deps/npm/docs/output/commands/npm-search.html index e3bcffc665ff11..634229987f2c6f 100644 --- a/deps/npm/docs/output/commands/npm-search.html +++ b/deps/npm/docs/output/commands/npm-search.html @@ -183,6 +183,10 @@

        json

      • Type: Boolean

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

      +
        +
      • In npm pkg set it enables parsing set values with JSON.parse() before +saving them to your package.json.
      • +

      Not supported by all npm commands.

      color

        diff --git a/deps/npm/docs/output/commands/npm-team.html b/deps/npm/docs/output/commands/npm-team.html index 5f848d566380b9..3e0d06db228fa9 100644 --- a/deps/npm/docs/output/commands/npm-team.html +++ b/deps/npm/docs/output/commands/npm-team.html @@ -247,6 +247,10 @@

        json

      • Type: Boolean

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

      +
        +
      • In npm pkg set it enables parsing set values with JSON.parse() before +saving them to your package.json.
      • +

      Not supported by all npm commands.

      See Also

      diff --git a/deps/npm/docs/output/commands/npm-unpublish.html b/deps/npm/docs/output/commands/npm-unpublish.html index 59beb148dfd484..3d330e9db5fd06 100644 --- a/deps/npm/docs/output/commands/npm-unpublish.html +++ b/deps/npm/docs/output/commands/npm-unpublish.html @@ -202,6 +202,7 @@

      force

    • Allow unpublishing all versions of a published package.
    • Allow conflicting peerDependencies to be installed in the root project.
    • Implicitly set --yes during npm init.
    • +
    • Allow clobbering existing values in npm pkg

    If you don’t have a clear idea of what you want to do, it is strongly recommended that you do not use this option!

    diff --git a/deps/npm/docs/output/commands/npm-update.html b/deps/npm/docs/output/commands/npm-update.html index 044345ab35e63f..f2491347aee66f 100644 --- a/deps/npm/docs/output/commands/npm-update.html +++ b/deps/npm/docs/output/commands/npm-update.html @@ -141,7 +141,7 @@

    npm-update

    Table of contents

    - +

    Synopsis

    @@ -151,7 +151,9 @@

    Table of contents

    Description

    This command will update all the packages listed to the latest version -(specified by the tag config), respecting semver.

    +(specified by the tag config), respecting the semver constraints of +both your package and its dependencies (if they also require the same +package).

    It will also install missing packages.

    If the -g flag is specified, this command will update globally installed packages.

    @@ -209,6 +211,30 @@

    Caret Dependencies below 1.0.0

    Then npm update will install dep1@0.4.1, because that is the highest-sorting version that satisfies ^0.4.0 (>= 0.4.0 <0.5.0)

    +

    Subdependencies

    +

    Suppose your app now also has a dependency on dep2

    +
    {
    +  "name": "my-app",
    +  "dependencies": {
    +      "dep1": "^1.0.0",
    +      "dep2": "1.0.0"
    +  }
    +}
    +
    +

    and dep2 itself depends on this limited range of dep1

    +
    {
    +"name": "dep2",
    +  "dependencies": {
    +    "dep1": "~1.1.1"
    +  }
    +}
    +
    +

    Then npm update will install dep1@1.1.2 because that is the highest +version that dep2 allows. npm will prioritize having a single version +of dep1 in your tree rather than two when that single version can +satisfy the semver requirements of multiple dependencies in your tree. +In this case if you really did need your package to use a newer version +you would need to use npm install.

    Updating Globally-Installed Packages

    npm update -g will apply the update action to each globally installed package that is outdated – that is, has a version that is different from @@ -310,9 +336,10 @@

    audit

  • Default: true
  • Type: Boolean
  • -

    When “true” submit audit reports alongside npm install runs to the default -registry and all registries configured for scopes. See the documentation for -npm audit for details on what is submitted.

    +

    When “true” submit audit reports alongside the current npm command to the +default registry and all registries configured for scopes. See the +documentation for npm audit for details on what is +submitted.

    • Default: true
    • diff --git a/deps/npm/docs/output/commands/npm-version.html b/deps/npm/docs/output/commands/npm-version.html index 1889060401bb77..c81569608d55c9 100644 --- a/deps/npm/docs/output/commands/npm-version.html +++ b/deps/npm/docs/output/commands/npm-version.html @@ -179,6 +179,10 @@

      json

    • Type: Boolean

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

    +
      +
    • In npm pkg set it enables parsing set values with JSON.parse() before +saving them to your package.json.
    • +

    Not supported by all npm commands.

    preid

      diff --git a/deps/npm/docs/output/commands/npm-view.html b/deps/npm/docs/output/commands/npm-view.html index 54400bd44e87c7..1a0eba4c1431fe 100644 --- a/deps/npm/docs/output/commands/npm-view.html +++ b/deps/npm/docs/output/commands/npm-view.html @@ -171,7 +171,7 @@

      Description

      For fields that are arrays, requesting a non-numeric field will return all of the values from the objects in the list. For example, to get all -the contributor names for the express package, you would run:

      +the contributor email addresses for the express package, you would run:

      npm view express contributors.email
       

      You may also use numeric indices in square braces to specifically select @@ -207,6 +207,10 @@

      json

    • Type: Boolean

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

    +
      +
    • In npm pkg set it enables parsing set values with JSON.parse() before +saving them to your package.json.
    • +

    Not supported by all npm commands.

    workspace

    -

    When “true” submit audit reports alongside npm install runs to the default -registry and all registries configured for scopes. See the documentation for -npm audit for details on what is submitted.

    +

    When “true” submit audit reports alongside the current npm command to the +default registry and all registries configured for scopes. See the +documentation for npm audit for details on what is +submitted.

    audit-level

    • Default: null
    • @@ -554,6 +556,7 @@

      force

    • Allow unpublishing all versions of a published package.
    • Allow conflicting peerDependencies to be installed in the root project.
    • Implicitly set --yes during npm init.
    • +
    • Allow clobbering existing values in npm pkg

    If you don’t have a clear idea of what you want to do, it is strongly recommended that you do not use this option!

    @@ -726,6 +729,10 @@

    json

  • Type: Boolean
  • Whether or not to output JSON data, rather than the normal output.

    +
      +
    • In npm pkg set it enables parsing set values with JSON.parse() before +saving them to your package.json.
    • +

    Not supported by all npm commands.

    key

      @@ -773,6 +780,13 @@

      local-address

    The IP address of the local interface to use when making connections to the npm registry. Must be IPv4 in versions of Node prior to 0.12.

    +

    location

    +
      +
    • Default: “user” unless --global is passed, which will also set this value +to “global”
    • +
    • Type: “global”, “user”, or “project”
    • +
    +

    When passed to npm config this refers to which config file to use.

    loglevel

    • Default: “notice”
    • diff --git a/deps/npm/docs/output/using-npm/scripts.html b/deps/npm/docs/output/using-npm/scripts.html index 320fcb248ced12..9b1a2e322e3621 100644 --- a/deps/npm/docs/output/using-npm/scripts.html +++ b/deps/npm/docs/output/using-npm/scripts.html @@ -198,7 +198,8 @@

      Life Cycle Scripts

      installed.

    • -

      As of npm@7 these scripts run in the background

      +

      As of npm@7 these scripts run in the background. +To see the output, run with: --foreground-scripts.

    prepublish (DEPRECATED)

    @@ -408,8 +409,8 @@

    Exiting

    Scripts are run by passing the line as a script argument to sh.

    If the script exits with a code other than 0, then this will abort the process.

    -

    Note that these script files don’t have to be nodejs or even -javascript programs. They just have to be some kind of executable +

    Note that these script files don’t have to be Node.js or even +JavaScript programs. They just have to be some kind of executable file.

    Best Practices

      diff --git a/deps/npm/docs/output/using-npm/workspaces.html b/deps/npm/docs/output/using-npm/workspaces.html index 55bdb32ec460d8..f0a5945d61153e 100644 --- a/deps/npm/docs/output/using-npm/workspaces.html +++ b/deps/npm/docs/output/using-npm/workspaces.html @@ -169,7 +169,7 @@

      Defining workspaces

      Given the above package.json example living at a current working directory . that contains a folder named workspace-a that itself contains -a package.json inside it, defining a nodejs package, e.g:

      +a package.json inside it, defining a Node.js package, e.g:

      .
       +-- package.json
       `-- workspace-a
      diff --git a/deps/npm/lib/base-command.js b/deps/npm/lib/base-command.js
      index 4077733a934b07..870c69acc492d7 100644
      --- a/deps/npm/lib/base-command.js
      +++ b/deps/npm/lib/base-command.js
      @@ -75,7 +75,6 @@ class BaseCommand {
         }
       
         async setWorkspaces (filters) {
      -    // TODO npm guards workspaces/global mode so we should use this.npm.prefix?
           const ws = await getWorkspaces(filters, { path: this.npm.localPrefix })
           this.workspaces = ws
           this.workspaceNames = [...ws.keys()]
      diff --git a/deps/npm/lib/ci.js b/deps/npm/lib/ci.js
      index 3ff4b65badb49f..6634ffcdc19bcb 100644
      --- a/deps/npm/lib/ci.js
      +++ b/deps/npm/lib/ci.js
      @@ -33,6 +33,7 @@ class CI extends ArboristWorkspaceCmd {
         /* istanbul ignore next - see test/lib/load-all-commands.js */
         static get params () {
           return [
      +      'audit',
             'ignore-scripts',
             'script-shell',
           ]
      diff --git a/deps/npm/lib/config.js b/deps/npm/lib/config.js
      index d1585f414dca89..a56dd92ffbde6a 100644
      --- a/deps/npm/lib/config.js
      +++ b/deps/npm/lib/config.js
      @@ -56,6 +56,7 @@ class Config extends BaseCommand {
             'json',
             'global',
             'editor',
      +      'location',
             'long',
           ]
         }
      @@ -137,7 +138,7 @@ class Config extends BaseCommand {
           if (!args.length)
             throw this.usageError()
       
      -    const where = this.npm.config.get('global') ? 'global' : 'user'
      +    const where = this.npm.config.get('location')
           for (const [key, val] of Object.entries(keyValues(args))) {
             this.npm.log.info('config', 'set %j %j', key, val)
             this.npm.config.set(key, val || '', where)
      @@ -167,16 +168,15 @@ class Config extends BaseCommand {
           if (!keys.length)
             throw this.usageError()
       
      -    const where = this.npm.config.get('global') ? 'global' : 'user'
      +    const where = this.npm.config.get('location')
           for (const key of keys)
             this.npm.config.delete(key, where)
           await this.npm.config.save(where)
         }
       
         async edit () {
      -    const global = this.npm.config.get('global')
           const e = this.npm.config.get('editor')
      -    const where = global ? 'global' : 'user'
      +    const where = this.npm.config.get('location')
           const file = this.npm.config.data.get(where).source
       
           // save first, just to make sure it's synced up
      diff --git a/deps/npm/lib/install-ci-test.js b/deps/npm/lib/install-ci-test.js
      index 0d408178b33f2d..871f24b2f32d6a 100644
      --- a/deps/npm/lib/install-ci-test.js
      +++ b/deps/npm/lib/install-ci-test.js
      @@ -13,14 +13,6 @@ class InstallCITest extends CI {
           return 'install-ci-test'
         }
       
      -  /* istanbul ignore next - see test/lib/load-all-commands.js */
      -  static get params () {
      -    return [
      -      'ignore-scripts',
      -      'script-shell',
      -    ]
      -  }
      -
         exec (args, cb) {
           this.npm.commands.ci(args, (er) => {
             if (er)
      diff --git a/deps/npm/lib/ls.js b/deps/npm/lib/ls.js
      index 7540692911976c..91e9a9dd3dba8d 100644
      --- a/deps/npm/lib/ls.js
      +++ b/deps/npm/lib/ls.js
      @@ -138,7 +138,7 @@ class LS extends ArboristWorkspaceCmd {
                 !(node instanceof Arborist.Node) || (currentDepth > depthToPrint)
               return (shouldSkipChildren)
                 ? []
      -          : [...(node.target || node).edgesOut.values()]
      +          : [...(node.target).edgesOut.values()]
                   .filter(filterBySelectedWorkspaces)
                   .filter(filterByEdgesTypes({
                     currentDepth,
      diff --git a/deps/npm/lib/npm.js b/deps/npm/lib/npm.js
      index 7046a84d0bcfa2..db3559a384bd7e 100644
      --- a/deps/npm/lib/npm.js
      +++ b/deps/npm/lib/npm.js
      @@ -1,12 +1,7 @@
      -// The order of the code in this file is relevant, because a lot of things
      -// require('npm.js'), but also we need to use some of those modules.  So,
      -// we define and instantiate the singleton ahead of loading any modules
      -// required for its methods.
      -
      -// these are all dependencies used in the ctor
       const EventEmitter = require('events')
       const { resolve, dirname } = require('path')
       const Config = require('@npmcli/config')
      +const log = require('npmlog')
       
       // Patch the global fs module here at the app level
       require('graceful-fs').gracefulify(require('fs'))
      @@ -37,23 +32,51 @@ const proxyCmds = new Proxy({}, {
         },
       })
       
      +// Timers in progress
      +const timers = new Map()
      +// Finished timers
      +const timings = {}
      +
      +const processOnTimeHandler = (name) => {
      +  timers.set(name, Date.now())
      +}
      +
      +const processOnTimeEndHandler = (name) => {
      +  if (timers.has(name)) {
      +    const ms = Date.now() - timers.get(name)
      +    log.timing(name, `Completed in ${ms}ms`)
      +    timings[name] = ms
      +    timers.delete(name)
      +  } else
      +    log.silly('timing', "Tried to end timer that doesn't exist:", name)
      +}
      +
       const { definitions, flatten, shorthands } = require('./utils/config/index.js')
       const { shellouts } = require('./utils/cmd-list.js')
       const usage = require('./utils/npm-usage.js')
       
      +const which = require('which')
      +
      +const deref = require('./utils/deref-command.js')
      +const setupLog = require('./utils/setup-log.js')
      +const cleanUpLogFiles = require('./utils/cleanup-log-files.js')
      +const getProjectScope = require('./utils/get-project-scope.js')
      +
       let warnedNonDashArg = false
       const _runCmd = Symbol('_runCmd')
       const _load = Symbol('_load')
       const _tmpFolder = Symbol('_tmpFolder')
       const _title = Symbol('_title')
      +
       const npm = module.exports = new class extends EventEmitter {
         constructor () {
           super()
      -    // TODO make this only ever load once (or unload) in tests
      -    require('./utils/perf.js')
           this.started = Date.now()
           this.command = null
           this.commands = proxyCmds
      +    this.timings = timings
      +    this.timers = timers
      +    this.perfStart()
           procLogListener()
           process.emit('time', 'npm')
           this.version = require('../package.json').version
      @@ -67,6 +90,16 @@ const npm = module.exports = new class extends EventEmitter {
           this.updateNotification = null
         }
       
      +  perfStart () {
      +    process.on('time', processOnTimeHandler)
      +    process.on('timeEnd', processOnTimeEndHandler)
      +  }
      +
      +  perfStop () {
      +    process.off('time', processOnTimeHandler)
      +    process.off('timeEnd', processOnTimeEndHandler)
      +  }
      +
         get shelloutCommands () {
           return shellouts
         }
      @@ -317,16 +350,5 @@ const npm = module.exports = new class extends EventEmitter {
         }
       }()
       
      -// now load everything required by the class methods
      -
      -const log = require('npmlog')
      -
      -const which = require('which')
      -
      -const deref = require('./utils/deref-command.js')
      -const setupLog = require('./utils/setup-log.js')
      -const cleanUpLogFiles = require('./utils/cleanup-log-files.js')
      -const getProjectScope = require('./utils/get-project-scope.js')
      -
       if (require.main === module)
         require('./cli.js')(process)
      diff --git a/deps/npm/lib/outdated.js b/deps/npm/lib/outdated.js
      index 9d60d143d71ce2..01e268fe96aee8 100644
      --- a/deps/npm/lib/outdated.js
      +++ b/deps/npm/lib/outdated.js
      @@ -158,7 +158,7 @@ class Outdated extends ArboristWorkspaceCmd {
             edge.from
               && this.filterSet
               && this.filterSet.size > 0
      -        && !this.filterSet.has(edge.from.target || edge.from)
      +        && !this.filterSet.has(edge.from.target)
       
           if (filteredOut)
             return
      diff --git a/deps/npm/lib/pkg.js b/deps/npm/lib/pkg.js
      new file mode 100644
      index 00000000000000..9ba92c930e1f0e
      --- /dev/null
      +++ b/deps/npm/lib/pkg.js
      @@ -0,0 +1,152 @@
      +const PackageJson = require('@npmcli/package-json')
      +const BaseCommand = require('./base-command.js')
      +const Queryable = require('./utils/queryable.js')
      +
      +class Pkg extends BaseCommand {
      +  static get description () {
      +    return 'Manages your package.json'
      +  }
      +
      +  /* istanbul ignore next - see test/lib/load-all-commands.js */
      +  static get name () {
      +    return 'pkg'
      +  }
      +
      +  /* istanbul ignore next - see test/lib/load-all-commands.js */
      +  static get usage () {
      +    return [
      +      'set = [= ...]',
      +      'get [ [ ...]]',
      +      'delete  [ ...]',
      +    ]
      +  }
      +
      +  /* istanbul ignore next - see test/lib/load-all-commands.js */
      +  static get params () {
      +    return [
      +      'force',
      +      'json',
      +      'workspace',
      +      'workspaces',
      +    ]
      +  }
      +
      +  exec (args, cb) {
      +    this.prefix = this.npm.localPrefix
      +    this.pkg(args).then(() => cb()).catch(cb)
      +  }
      +
      +  execWorkspaces (args, filters, cb) {
      +    this.pkgWorkspaces(args, filters).then(() => cb()).catch(cb)
      +  }
      +
      +  async pkg (args) {
      +    if (this.npm.config.get('global')) {
      +      throw Object.assign(
      +        new Error(`There's no package.json file to manage on global mode`),
      +        { code: 'EPKGGLOBAL' }
      +      )
      +    }
      +
      +    const [cmd, ..._args] = args
      +    switch (cmd) {
      +      case 'get':
      +        return this.get(_args)
      +      case 'set':
      +        return this.set(_args)
      +      case 'delete':
      +        return this.delete(_args)
      +      default:
      +        throw this.usageError()
      +    }
      +  }
      +
      +  async pkgWorkspaces (args, filters) {
      +    await this.setWorkspaces(filters)
      +    const result = {}
      +    for (const [workspaceName, workspacePath] of this.workspaces.entries()) {
      +      this.prefix = workspacePath
      +      result[workspaceName] = await this.pkg(args)
      +    }
      +    // when running in workspaces names, make sure to key by workspace
      +    // name the results of each value retrieved in each ws
      +    this.npm.output(JSON.stringify(result, null, 2))
      +  }
      +
      +  async get (args) {
      +    const pkgJson = await PackageJson.load(this.prefix)
      +
      +    const { content } = pkgJson
      +    let result = !args.length && content
      +
      +    if (!result) {
      +      const q = new Queryable(content)
      +      result = q.query(args)
      +
      +      // in case there's only a single result from the query
      +      // just prints that one element to stdout
      +      if (Object.keys(result).length === 1)
      +        result = result[args]
      +    }
      +
      +    // only outputs if not running with workspaces config,
      +    // in case you're retrieving info for workspaces the pkgWorkspaces
      +    // will handle the output to make sure it get keyed by ws name
      +    if (!this.workspaces)
      +      this.npm.output(JSON.stringify(result, null, 2))
      +
      +    return result
      +  }
      +
      +  async set (args) {
      +    const setError = () =>
      +      Object.assign(
      +        new TypeError('npm pkg set expects a key=value pair of args.'),
      +        { code: 'EPKGSET' }
      +      )
      +
      +    if (!args.length)
      +      throw setError()
      +
      +    const force = this.npm.config.get('force')
      +    const json = this.npm.config.get('json')
      +    const pkgJson = await PackageJson.load(this.prefix)
      +    const q = new Queryable(pkgJson.content)
      +    for (const arg of args) {
      +      const [key, ...rest] = arg.split('=')
      +      const value = rest.join('=')
      +      if (!key || !value)
      +        throw setError()
      +
      +      q.set(key, json ? JSON.parse(value) : value, { force })
      +    }
      +
      +    pkgJson.update(q.toJSON())
      +    await pkgJson.save()
      +  }
      +
      +  async delete (args) {
      +    const setError = () =>
      +      Object.assign(
      +        new TypeError('npm pkg delete expects key args.'),
      +        { code: 'EPKGDELETE' }
      +      )
      +
      +    if (!args.length)
      +      throw setError()
      +
      +    const pkgJson = await PackageJson.load(this.prefix)
      +    const q = new Queryable(pkgJson.content)
      +    for (const key of args) {
      +      if (!key)
      +        throw setError()
      +
      +      q.delete(key)
      +    }
      +
      +    pkgJson.update(q.toJSON())
      +    await pkgJson.save()
      +  }
      +}
      +
      +module.exports = Pkg
      diff --git a/deps/npm/lib/publish.js b/deps/npm/lib/publish.js
      index f35388a30f4ed7..9c747eb5068f0c 100644
      --- a/deps/npm/lib/publish.js
      +++ b/deps/npm/lib/publish.js
      @@ -66,6 +66,7 @@ class Publish extends BaseCommand {
           const dryRun = this.npm.config.get('dry-run')
           const json = this.npm.config.get('json')
           const defaultTag = this.npm.config.get('tag')
      +    const ignoreScripts = this.npm.config.get('ignore-scripts')
           const silent = log.level === 'silent'
       
           if (semver.validRange(defaultTag))
      @@ -82,7 +83,7 @@ class Publish extends BaseCommand {
             flatten(manifest.publishConfig, opts)
       
           // only run scripts for directory type publishes
      -    if (spec.type === 'directory') {
      +    if (spec.type === 'directory' && !ignoreScripts) {
             await runScript({
               event: 'prepublishOnly',
               path: spec.fetchSpec,
      @@ -119,7 +120,7 @@ class Publish extends BaseCommand {
             await otplease(opts, opts => libpub(manifest, tarballData, opts))
           }
       
      -    if (spec.type === 'directory') {
      +    if (spec.type === 'directory' && !ignoreScripts) {
             await runScript({
               event: 'publish',
               path: spec.fetchSpec,
      diff --git a/deps/npm/lib/utils/cmd-list.js b/deps/npm/lib/utils/cmd-list.js
      index c865cdabb4014e..26da5390065886 100644
      --- a/deps/npm/lib/utils/cmd-list.js
      +++ b/deps/npm/lib/utils/cmd-list.js
      @@ -122,6 +122,7 @@ const cmdList = [
         'diff',
         'dist-tag',
         'ping',
      +  'pkg',
       
         'test',
         'stop',
      diff --git a/deps/npm/lib/utils/config/definition.js b/deps/npm/lib/utils/config/definition.js
      index 507be6a6440423..1354851326adfd 100644
      --- a/deps/npm/lib/utils/config/definition.js
      +++ b/deps/npm/lib/utils/config/definition.js
      @@ -91,13 +91,27 @@ ${noEnvExport}`)
       }
       
       const describeUsage = (def) => {
      -  let key = `--${def.key}`
      -  if (def.short && typeof def.short === 'string')
      -    key = `-${def.short}|${key}`
      +  let key = ''
       
         // Single type
      -  if (!Array.isArray(def.type))
      -    return `${key}${def.type === Boolean ? '' : ' ' + def.hint}`
      +  if (!Array.isArray(def.type)) {
      +    if (def.short)
      +      key = `-${def.short}|`
      +
      +    if (def.type === Boolean && def.default !== false)
      +      key = `${key}--no-${def.key}`
      +    else
      +      key = `${key}--${def.key}`
      +
      +    if (def.type !== Boolean)
      +      key = `${key} ${def.hint}`
      +
      +    return key
      +  }
      +
      +  key = `--${def.key}`
      +  if (def.short)
      +    key = `-${def.short}|--${def.key}`
       
         // Multiple types
         let types = def.type
      @@ -120,8 +134,12 @@ const describeUsage = (def) => {
           description = def.hint
         }
       
      -  if (bool)
      -    key = `${key}|${key}`
      +  if (bool) {
      +    // Currently none of our multi-type configs with boolean values default to
      +    // false so all their hints should show `--no-`, if we ever add ones that
      +    // default to false we can branch the logic here
      +    key = `--no-${def.key}|${key}`
      +  }
       
         const usage = `${key} ${description}`
         if (multiple)
      diff --git a/deps/npm/lib/utils/config/definitions.js b/deps/npm/lib/utils/config/definitions.js
      index d540b0fc67e82a..abe6bda70d8bc5 100644
      --- a/deps/npm/lib/utils/config/definitions.js
      +++ b/deps/npm/lib/utils/config/definitions.js
      @@ -203,10 +203,10 @@ define('audit', {
         default: true,
         type: Boolean,
         description: `
      -    When "true" submit audit reports alongside \`npm install\` runs to the
      +    When "true" submit audit reports alongside the current npm command to the
           default registry and all registries configured for scopes.  See the
      -    documentation for [\`npm audit\`](/commands/npm-audit) for details on
      -    what is submitted.
      +    documentation for [\`npm audit\`](/commands/npm-audit) for details on what
      +    is submitted.
         `,
         flatten,
       })
      @@ -440,6 +440,7 @@ define('cidr', {
       
       define('color', {
         default: !process.env.NO_COLOR || process.env.NO_COLOR === '0',
      +  usage: '--color|--no-color|--color always',
         defaultDescription: `
           true unless the NO_COLOR environ is set to something other than '0'
         `,
      @@ -715,6 +716,7 @@ define('force', {
           * Allow unpublishing all versions of a published package.
           * Allow conflicting peerDependencies to be installed in the root project.
           * Implicitly set \`--yes\` during \`npm init\`.
      +    * Allow clobbering existing values in \`npm pkg\`
       
           If you don't have a clear idea of what you want to do, it is strongly
           recommended that you do not use this option!
      @@ -1029,6 +1031,9 @@ define('json', {
         description: `
           Whether or not to output JSON data, rather than the normal output.
       
      +    * In \`npm pkg set\` it enables parsing set values with JSON.parse()
      +    before saving them to your \`package.json\`.
      +
           Not supported by all npm commands.
         `,
         flatten,
      @@ -1103,6 +1108,31 @@ define('local-address', {
         flatten,
       })
       
      +define('location', {
      +  default: 'user',
      +  short: 'L',
      +  type: [
      +    'global',
      +    'user',
      +    'project',
      +  ],
      +  defaultDescription: `
      +    "user" unless \`--global\` is passed, which will also set this value to "global"
      +  `,
      +  description: `
      +    When passed to \`npm config\` this refers to which config file to use.
      +  `,
      +  // NOTE: the flattener here deliberately does not alter the value of global
      +  // for now, this is to avoid inadvertently causing any breakage. the value of
      +  // global, however, does modify this flag.
      +  flatten (key, obj, flatOptions) {
      +    // if global is set, we override ourselves
      +    if (obj.global)
      +      obj.location = 'global'
      +    flatOptions.location = obj.location
      +  },
      +})
      +
       define('loglevel', {
         default: 'notice',
         type: [
      @@ -1200,7 +1230,10 @@ define('noproxy', {
           Also accepts a comma-delimited string.
         `,
         flatten (key, obj, flatOptions) {
      -    flatOptions.noProxy = obj[key].join(',')
      +    if (Array.isArray(obj[key]))
      +      flatOptions.noProxy = obj[key].join(',')
      +    else
      +      flatOptions.noProxy = obj[key]
         },
       })
       
      diff --git a/deps/npm/lib/utils/error-message.js b/deps/npm/lib/utils/error-message.js
      index 125cdf8c53581b..3b590f712e783c 100644
      --- a/deps/npm/lib/utils/error-message.js
      +++ b/deps/npm/lib/utils/error-message.js
      @@ -269,6 +269,7 @@ module.exports = (er, npm) => {
           case 'ECONNRESET':
           case 'ENOTFOUND':
           case 'ETIMEDOUT':
      +    case 'ERR_SOCKET_TIMEOUT':
           case 'EAI_FAIL':
             short.push(['network', er.message])
             detail.push([
      diff --git a/deps/npm/lib/utils/exit-handler.js b/deps/npm/lib/utils/exit-handler.js
      index 931527704b9b71..95c9655a716cf3 100644
      --- a/deps/npm/lib/utils/exit-handler.js
      +++ b/deps/npm/lib/utils/exit-handler.js
      @@ -1,4 +1,3 @@
      -const log = require('npmlog')
       const os = require('os')
       const path = require('path')
       const writeFileAtomic = require('write-file-atomic')
      @@ -13,8 +12,6 @@ let logFileName
       let npm // set by the cli
       let wroteLogFile = false
       
      -const timings = {}
      -
       const getLogFile = () => {
         // we call this multiple times, so we need to treat it as a singleton because
         // the date is part of the name
      @@ -24,17 +21,15 @@ const getLogFile = () => {
         return logFileName
       }
       
      -process.on('timing', (name, value) => {
      -  if (timings[name])
      -    timings[name] += value
      -  else
      -    timings[name] = value
      -})
      -
       process.on('exit', code => {
      +  // process.emit is synchronous, so the timeEnd handler will run before the
      +  // unfinished timer check below
         process.emit('timeEnd', 'npm')
      -  log.disableProgress()
      -  if (npm.config && npm.config.loaded && npm.config.get('timing')) {
      +  npm.log.disableProgress()
      +  for (const [name, timers] of npm.timers)
      +    npm.log.verbose('unfinished npm timer', name, timers)
      +
      +  if (npm.config.loaded && npm.config.get('timing')) {
           try {
             const file = path.resolve(npm.config.get('cache'), '_timing.json')
             const dir = path.dirname(npm.config.get('cache'))
      @@ -44,7 +39,7 @@ process.on('exit', code => {
               command: process.argv.slice(2),
               logfile: getLogFile(),
               version: npm.version,
      -        ...timings,
      +        ...npm.timings,
             }) + '\n')
       
             const st = fs.lstatSync(path.dirname(npm.config.get('cache')))
      @@ -56,27 +51,27 @@ process.on('exit', code => {
         }
       
         if (!code)
      -    log.info('ok')
      +    npm.log.info('ok')
         else {
      -    log.verbose('code', code)
      +    npm.log.verbose('code', code)
           if (!exitHandlerCalled) {
      -      log.error('', 'Exit handler never called!')
      +      npm.log.error('', 'Exit handler never called!')
             console.error('')
      -      log.error('', 'This is an error with npm itself. Please report this error at:')
      -      log.error('', '    ')
      +      npm.log.error('', 'This is an error with npm itself. Please report this error at:')
      +      npm.log.error('', '    ')
             // TODO this doesn't have an npm.config.loaded guard
             writeLogFile()
           }
         }
         // In timing mode we always write the log file
      -  if (npm.config && npm.config.loaded && npm.config.get('timing') && !wroteLogFile)
      +  if (npm.config.loaded && npm.config.get('timing') && !wroteLogFile)
           writeLogFile()
         if (wroteLogFile) {
           // just a line break
      -    if (log.levels[log.level] <= log.levels.error)
      +    if (npm.log.levels[npm.log.level] <= npm.log.levels.error)
             console.error('')
       
      -    log.error(
      +    npm.log.error(
             '',
             [
               'A complete log of this run can be found in:',
      @@ -88,121 +83,114 @@ process.on('exit', code => {
         // these are needed for the tests to have a clean slate in each test case
         exitHandlerCalled = false
         wroteLogFile = false
      -
      -  // actually exit.
      -  process.exit(code)
       })
       
      -const exit = (code, noLog) => {
      -  log.verbose('exit', code || 0)
      -  if (log.level === 'silent')
      -    noLog = true
      -
      -  // noLog is true if there was an error, including if config wasn't loaded, so
      -  // this doesn't need a config.loaded guard
      -  if (code && !noLog)
      -    writeLogFile()
      -
      -  // Exit directly -- nothing in the CLI should still be running in the
      -  // background at this point, and this makes sure anything left dangling
      -  // for whatever reason gets thrown away, instead of leaving the CLI open
      -  process.stdout.write('', () => {
      -    process.exit(code)
      -  })
      -}
      -
       const exitHandler = (err) => {
      -  log.disableProgress()
      -  if (!npm.config || !npm.config.loaded) {
      -    // logging won't work unless we pretend that it's ready
      +  npm.log.disableProgress()
      +  if (!npm.config.loaded) {
           err = err || new Error('Exit prior to config file resolving.')
           console.error(err.stack || err.message)
         }
       
      -  if (exitHandlerCalled)
      -    err = err || new Error('Exit handler called more than once.')
      -
      -  // only show the notification if it finished before the other stuff we
      -  // were doing.  no need to hang on `npm -v` or something.
      +  // only show the notification if it finished.
         if (typeof npm.updateNotification === 'string') {
      -    const { level } = log
      -    log.level = log.levels.notice
      -    log.notice('', npm.updateNotification)
      -    log.level = level
      +    const { level } = npm.log
      +    npm.log.level = 'notice'
      +    npm.log.notice('', npm.updateNotification)
      +    npm.log.level = level
         }
       
         exitHandlerCalled = true
      -  if (!err)
      -    return exit()
      -
      -  // if we got a command that just shells out to something else, then it
      -  // will presumably print its own errors and exit with a proper status
      -  // code if there's a problem.  If we got an error with a code=0, then...
      -  // something else went wrong along the way, so maybe an npm problem?
      -  const isShellout = npm.shelloutCommands.includes(npm.command)
      -  const quietShellout = isShellout && typeof err.code === 'number' && err.code
      -  if (quietShellout)
      -    return exit(err.code, true)
      -  else if (typeof err === 'string') {
      -    log.error('', err)
      -    return exit(1, true)
      -  } else if (!(err instanceof Error)) {
      -    log.error('weird error', err)
      -    return exit(1, true)
      -  }
      -
      -  if (!err.code) {
      -    const matchErrorCode = err.message.match(/^(?:Error: )?(E[A-Z]+)/)
      -    err.code = matchErrorCode && matchErrorCode[1]
      -  }
       
      -  for (const k of ['type', 'stack', 'statusCode', 'pkgid']) {
      -    const v = err[k]
      -    if (v)
      -      log.verbose(k, replaceInfo(v))
      +  let exitCode
      +  let noLog
      +
      +  if (err) {
      +    exitCode = 1
      +    // if we got a command that just shells out to something else, then it
      +    // will presumably print its own errors and exit with a proper status
      +    // code if there's a problem.  If we got an error with a code=0, then...
      +    // something else went wrong along the way, so maybe an npm problem?
      +    const isShellout = npm.shelloutCommands.includes(npm.command)
      +    const quietShellout = isShellout && typeof err.code === 'number' && err.code
      +    if (quietShellout) {
      +      exitCode = err.code
      +      noLog = true
      +    } else if (typeof err === 'string') {
      +      noLog = true
      +      npm.log.error('', err)
      +    } else if (!(err instanceof Error)) {
      +      noLog = true
      +      npm.log.error('weird error', err)
      +    } else {
      +      if (!err.code) {
      +        const matchErrorCode = err.message.match(/^(?:Error: )?(E[A-Z]+)/)
      +        err.code = matchErrorCode && matchErrorCode[1]
      +      }
      +
      +      for (const k of ['type', 'stack', 'statusCode', 'pkgid']) {
      +        const v = err[k]
      +        if (v)
      +          npm.log.verbose(k, replaceInfo(v))
      +      }
      +
      +      npm.log.verbose('cwd', process.cwd())
      +
      +      const args = replaceInfo(process.argv)
      +      npm.log.verbose('', os.type() + ' ' + os.release())
      +      npm.log.verbose('argv', args.map(JSON.stringify).join(' '))
      +      npm.log.verbose('node', process.version)
      +      npm.log.verbose('npm ', 'v' + npm.version)
      +
      +      for (const k of ['code', 'syscall', 'file', 'path', 'dest', 'errno']) {
      +        const v = err[k]
      +        if (v)
      +          npm.log.error(k, v)
      +      }
      +
      +      const msg = errorMessage(err, npm)
      +      for (const errline of [...msg.summary, ...msg.detail])
      +        npm.log.error(...errline)
      +
      +      if (npm.config.loaded && npm.config.get('json')) {
      +        const error = {
      +          error: {
      +            code: err.code,
      +            summary: messageText(msg.summary),
      +            detail: messageText(msg.detail),
      +          },
      +        }
      +        console.error(JSON.stringify(error, null, 2))
      +      }
      +
      +      if (typeof err.errno === 'number')
      +        exitCode = err.errno
      +      else if (typeof err.code === 'number')
      +        exitCode = err.code
      +    }
         }
      +  npm.log.verbose('exit', exitCode || 0)
       
      -  log.verbose('cwd', process.cwd())
      -
      -  const args = replaceInfo(process.argv)
      -  log.verbose('', os.type() + ' ' + os.release())
      -  log.verbose('argv', args.map(JSON.stringify).join(' '))
      -  log.verbose('node', process.version)
      -  log.verbose('npm ', 'v' + npm.version)
      -
      -  for (const k of ['code', 'syscall', 'file', 'path', 'dest', 'errno']) {
      -    const v = err[k]
      -    if (v)
      -      log.error(k, v)
      -  }
      +  if (npm.log.level === 'silent')
      +    noLog = true
       
      -  const msg = errorMessage(err, npm)
      -  for (const errline of [...msg.summary, ...msg.detail])
      -    log.error(...errline)
      -
      -  if (npm.config && npm.config.get('json')) {
      -    const error = {
      -      error: {
      -        code: err.code,
      -        summary: messageText(msg.summary),
      -        detail: messageText(msg.detail),
      -      },
      -    }
      -    console.error(JSON.stringify(error, null, 2))
      -  }
      +  // noLog is true if there was an error, including if config wasn't loaded, so
      +  // this doesn't need a config.loaded guard
      +  if (exitCode && !noLog)
      +    writeLogFile()
       
      -  exit(typeof err.errno === 'number' ? err.errno : typeof err.code === 'number' ? err.code : 1)
      +  // explicitly call process.exit now so we don't hang on things like the
      +  // update notifier, also flush stdout beforehand because process.exit doesn't
      +  // wait for that to happen.
      +  process.stdout.write('', () => process.exit(exitCode))
       }
       
       const messageText = msg => msg.map(line => line.slice(1).join(' ')).join('\n')
       
       const writeLogFile = () => {
      -  if (wroteLogFile)
      -    return
      -
         try {
           let logOutput = ''
      -    log.record.forEach(m => {
      +    npm.log.record.forEach(m => {
             const p = [m.id, m.level]
             if (m.prefix)
               p.push(m.prefix)
      @@ -225,7 +213,7 @@ const writeLogFile = () => {
           fs.chownSync(file, st.uid, st.gid)
       
           // truncate once it's been written.
      -    log.record.length = 0
      +    npm.log.record.length = 0
           wroteLogFile = true
         } catch (ex) {
       
      diff --git a/deps/npm/lib/utils/perf.js b/deps/npm/lib/utils/perf.js
      deleted file mode 100644
      index 4961054d909ad6..00000000000000
      --- a/deps/npm/lib/utils/perf.js
      +++ /dev/null
      @@ -1,23 +0,0 @@
      -const log = require('npmlog')
      -const timings = new Map()
      -
      -process.on('time', (name) => {
      -  timings.set(name, Date.now())
      -})
      -
      -process.on('timeEnd', (name) => {
      -  if (timings.has(name)) {
      -    const ms = Date.now() - timings.get(name)
      -    process.emit('timing', name, ms)
      -    log.timing(name, `Completed in ${ms}ms`)
      -    timings.delete(name)
      -  } else
      -    log.silly('timing', "Tried to end timer that doesn't exist:", name)
      -})
      -
      -// for tests
      -/* istanbul ignore next */
      -exports.reset = () => {
      -  process.removeAllListeners('time')
      -  process.removeAllListeners('timeEnd')
      -}
      diff --git a/deps/npm/lib/utils/queryable.js b/deps/npm/lib/utils/queryable.js
      new file mode 100644
      index 00000000000000..e10eba3b5f092a
      --- /dev/null
      +++ b/deps/npm/lib/utils/queryable.js
      @@ -0,0 +1,314 @@
      +const util = require('util')
      +const _data = Symbol('data')
      +const _delete = Symbol('delete')
      +const _append = Symbol('append')
      +
      +const sqBracketsMatcher = str => str.match(/(.+)\[([^\]]+)\]\.?(.*)$/)
      +
      +// replaces any occurence of an empty-brackets (e.g: []) with a special
      +// Symbol(append) to represent it, this is going to be useful for the setter
      +// method that will push values to the end of the array when finding these
      +const replaceAppendSymbols = str => {
      +  const matchEmptyBracket = str.match(/^(.*)\[\]\.?(.*)$/)
      +
      +  if (matchEmptyBracket) {
      +    const [, pre, post] = matchEmptyBracket
      +    return [...replaceAppendSymbols(pre), _append, post].filter(Boolean)
      +  }
      +
      +  return [str]
      +}
      +
      +const parseKeys = (key) => {
      +  const sqBracketItems = new Set()
      +  sqBracketItems.add(_append)
      +  const parseSqBrackets = (str) => {
      +    const index = sqBracketsMatcher(str)
      +
      +    // once we find square brackets, we recursively parse all these
      +    if (index) {
      +      const preSqBracketPortion = index[1]
      +
      +      // we want to have a `new String` wrapper here in order to differentiate
      +      // between multiple occurences of the same string, e.g:
      +      // foo.bar[foo.bar] should split into { foo: { bar: { 'foo.bar': {} } }
      +      /* eslint-disable-next-line no-new-wrappers */
      +      const foundKey = new String(index[2])
      +      const postSqBracketPortion = index[3]
      +
      +      // we keep track of items found during this step to make sure
      +      // we don't try to split-separate keys that were defined within
      +      // square brackets, since the key name itself might contain dots
      +      sqBracketItems.add(foundKey)
      +
      +      // returns an array that contains either dot-separate items (that will
      +      // be splitted appart during the next step OR the fully parsed keys
      +      // read from square brackets, e.g:
      +      // foo.bar[1.0.0].a.b -> ['foo.bar', '1.0.0', 'a.b']
      +      return [
      +        ...parseSqBrackets(preSqBracketPortion),
      +        foundKey,
      +        ...(
      +          postSqBracketPortion
      +            ? parseSqBrackets(postSqBracketPortion)
      +            : []
      +        ),
      +      ]
      +    }
      +
      +    // at the end of parsing, any usage of the special empty-bracket syntax
      +    // (e.g: foo.array[]) has  not yet been parsed, here we'll take care
      +    // of parsing it and adding a special symbol to represent it in
      +    // the resulting list of keys
      +    return replaceAppendSymbols(str)
      +  }
      +
      +  const res = []
      +  // starts by parsing items defined as square brackets, those might be
      +  // representing properties that have a dot in the name or just array
      +  // indexes, e.g: foo[1.0.0] or list[0]
      +  const sqBracketKeys = parseSqBrackets(key.trim())
      +
      +  for (const k of sqBracketKeys) {
      +    // keys parsed from square brackets should just be added to list of
      +    // resulting keys as they might have dots as part of the key
      +    if (sqBracketItems.has(k))
      +      res.push(k)
      +    else {
      +      // splits the dot-sep property names and add them to the list of keys
      +      for (const splitKey of k.split('.'))
      +        /* eslint-disable-next-line no-new-wrappers */
      +        res.push(new String(splitKey))
      +    }
      +  }
      +
      +  // returns an ordered list of strings in which each entry
      +  // represents a key in an object defined by the previous entry
      +  return res
      +}
      +
      +const getter = ({ data, key }) => {
      +  // keys are a list in which each entry represents the name of
      +  // a property that should be walked through the object in order to
      +  // return the final found value
      +  const keys = parseKeys(key)
      +  let _data = data
      +  let label = ''
      +
      +  for (const k of keys) {
      +    // empty-bracket-shortcut-syntax is not supported on getter
      +    if (k === _append) {
      +      throw Object.assign(
      +        new Error('Empty brackets are not valid syntax for retrieving values.'),
      +        { code: 'EINVALIDSYNTAX' }
      +      )
      +    }
      +
      +    // extra logic to take into account printing array, along with its
      +    // special syntax in which using a dot-sep property name after an
      +    // arry will expand it's results, e.g:
      +    // arr.name -> arr[0].name=value, arr[1].name=value, ...
      +    const maybeIndex = Number(k)
      +    if (Array.isArray(_data) && !Number.isInteger(maybeIndex)) {
      +      _data = _data.reduce((acc, i, index) => {
      +        acc[`${label}[${index}].${k}`] = i[k]
      +        return acc
      +      }, {})
      +      return _data
      +    } else {
      +      // if can't find any more values, it means it's just over
      +      // and there's nothing to return
      +      if (!_data[k])
      +        return undefined
      +
      +      // otherwise sets the next value
      +      _data = _data[k]
      +    }
      +
      +    label += k
      +  }
      +
      +  // these are some legacy expectations from
      +  // the old API consumed by lib/view.js
      +  if (Array.isArray(_data) && _data.length <= 1)
      +    _data = _data[0]
      +
      +  return {
      +    [key]: _data,
      +  }
      +}
      +
      +const setter = ({ data, key, value, force }) => {
      +  // setter goes to recursively transform the provided data obj,
      +  // setting properties from the list of parsed keys, e.g:
      +  // ['foo', 'bar', 'baz'] -> { foo: { bar: { baz:  {} } }
      +  const keys = parseKeys(key)
      +  const setKeys = (_data, _key) => {
      +    // handles array indexes, converting valid integers to numbers,
      +    // note that occurences of Symbol(append) will throw,
      +    // so we just ignore these for now
      +    let maybeIndex = Number.NaN
      +    try {
      +      maybeIndex = Number(_key)
      +    } catch (err) {}
      +    if (!Number.isNaN(maybeIndex))
      +      _key = maybeIndex
      +
      +    // creates new array in case key is an index
      +    // and the array obj is not yet defined
      +    const keyIsAnArrayIndex = _key === maybeIndex || _key === _append
      +    const dataHasNoItems = !Object.keys(_data).length
      +    if (keyIsAnArrayIndex && dataHasNoItems && !Array.isArray(_data))
      +      _data = []
      +
      +    // converting from array to an object is also possible, in case the
      +    // user is using force mode, we should also convert existing arrays
      +    // to an empty object if the current _data is an array
      +    if (force && Array.isArray(_data) && !keyIsAnArrayIndex)
      +      _data = { ..._data }
      +
      +    // the _append key is a special key that is used to represent
      +    // the empty-bracket notation, e.g: arr[] -> arr[arr.length]
      +    if (_key === _append) {
      +      if (!Array.isArray(_data)) {
      +        throw Object.assign(
      +          new Error(`Can't use append syntax in non-Array element`),
      +          { code: 'ENOAPPEND' }
      +        )
      +      }
      +      _key = _data.length
      +    }
      +
      +    // retrieves the next data object to recursively iterate on,
      +    // throws if trying to override a literal value or add props to an array
      +    const next = () => {
      +      const haveContents =
      +        !force &&
      +        _data[_key] != null &&
      +        value !== _delete
      +      const shouldNotOverrideLiteralValue =
      +        !(typeof _data[_key] === 'object')
      +      // if the next obj to recurse is an array and the next key to be
      +      // appended to the resulting obj is not an array index, then it
      +      // should throw since we can't append arbitrary props to arrays
      +      const shouldNotAddPropsToArrays =
      +        typeof keys[0] !== 'symbol' &&
      +        Array.isArray(_data[_key]) &&
      +        Number.isNaN(Number(keys[0]))
      +
      +      const overrideError =
      +        haveContents &&
      +        shouldNotOverrideLiteralValue
      +      if (overrideError) {
      +        throw Object.assign(
      +          new Error(`Property ${_key} already exists and is not an Array or Object.`),
      +          { code: 'EOVERRIDEVALUE' }
      +        )
      +      }
      +
      +      const addPropsToArrayError =
      +        haveContents &&
      +        shouldNotAddPropsToArrays
      +      if (addPropsToArrayError) {
      +        throw Object.assign(
      +          new Error(`Can't add property ${key} to an Array.`),
      +          { code: 'ENOADDPROP' }
      +        )
      +      }
      +
      +      return typeof _data[_key] === 'object' ? _data[_key] || {} : {}
      +    }
      +
      +    // sets items from the parsed array of keys as objects, recurses to
      +    // setKeys in case there are still items to be handled, otherwise it
      +    // just sets the original value set by the user
      +    if (keys.length)
      +      _data[_key] = setKeys(next(), keys.shift())
      +    else {
      +      // handles special deletion cases for obj props / array items
      +      if (value === _delete) {
      +        if (Array.isArray(_data))
      +          _data.splice(_key, 1)
      +        else
      +          delete _data[_key]
      +      } else
      +        // finally, sets the value in its right place
      +        _data[_key] = value
      +    }
      +
      +    return _data
      +  }
      +
      +  setKeys(data, keys.shift())
      +}
      +
      +class Queryable {
      +  constructor (obj) {
      +    if (!obj || typeof obj !== 'object') {
      +      throw Object.assign(
      +        new Error('Queryable needs an object to query properties from.'),
      +        { code: 'ENOQUERYABLEOBJ' }
      +      )
      +    }
      +
      +    this[_data] = obj
      +  }
      +
      +  query (queries) {
      +    // this ugly interface here is meant to be a compatibility layer
      +    // with the legacy API lib/view.js is consuming, if at some point
      +    // we refactor that command then we can revisit making this nicer
      +    if (queries === '')
      +      return { '': this[_data] }
      +
      +    const q = query => getter({
      +      data: this[_data],
      +      key: query,
      +    })
      +
      +    if (Array.isArray(queries)) {
      +      let res = {}
      +      for (const query of queries)
      +        res = { ...res, ...q(query) }
      +      return res
      +    } else
      +      return q(queries)
      +  }
      +
      +  // return the value for a single query if found, otherwise returns undefined
      +  get (query) {
      +    const obj = this.query(query)
      +    if (obj)
      +      return obj[query]
      +  }
      +
      +  // creates objects along the way for the provided `query` parameter
      +  // and assigns `value` to the last property of the query chain
      +  set (query, value, { force } = {}) {
      +    setter({
      +      data: this[_data],
      +      key: query,
      +      value,
      +      force,
      +    })
      +  }
      +
      +  // deletes the value of the property found at `query`
      +  delete (query) {
      +    setter({
      +      data: this[_data],
      +      key: query,
      +      value: _delete,
      +    })
      +  }
      +
      +  toJSON () {
      +    return this[_data]
      +  }
      +
      +  [util.inspect.custom] () {
      +    return this.toJSON()
      +  }
      +}
      +
      +module.exports = Queryable
      diff --git a/deps/npm/lib/utils/update-notifier.js b/deps/npm/lib/utils/update-notifier.js
      index ed5806ced2a7d9..14c4fac0d58b35 100644
      --- a/deps/npm/lib/utils/update-notifier.js
      +++ b/deps/npm/lib/utils/update-notifier.js
      @@ -33,12 +33,6 @@ const checkTimeout = async (npm, duration) => {
         return t > st.mtime
       }
       
      -const updateTimeout = async npm => {
      -  // best effort, if this fails, it's ok.
      -  // might be using /dev/null as the cache or something weird like that.
      -  await writeFile(lastCheckedFile(npm), '').catch(() => {})
      -}
      -
       const updateNotifier = async (npm, spec = 'latest') => {
         // never check for updates in CI, when updating npm already, or opted out
         if (!npm.config.get('update-notifier') ||
      @@ -111,15 +105,16 @@ const updateNotifier = async (npm, spec = 'latest') => {
           `${oldc} -> ${latestc}\n` +
           `Changelog: ${changelogc}\n` +
           `Run ${cmdc} to update!\n`
      -  const messagec = !useColor ? message : chalk.bgBlack.white(message)
       
      -  return messagec
      +  return message
       }
       
       // only update the notification timeout if we actually finished checking
       module.exports = async npm => {
         const notification = await updateNotifier(npm)
      -  // intentional.  do not await this.  it's a best-effort update.
      -  updateTimeout(npm)
      +  // intentional.  do not await this.  it's a best-effort update.  if this
      +  // fails, it's ok.  might be using /dev/null as the cache or something weird
      +  // like that.
      +  writeFile(lastCheckedFile(npm), '').catch(() => {})
         npm.updateNotification = notification
       }
      diff --git a/deps/npm/lib/view.js b/deps/npm/lib/view.js
      index 788df3ed0b4d83..47e631f5565c0d 100644
      --- a/deps/npm/lib/view.js
      +++ b/deps/npm/lib/view.js
      @@ -17,6 +17,7 @@ const { packument } = require('pacote')
       const readFile = promisify(fs.readFile)
       const readJson = async file => jsonParse(await readFile(file, 'utf8'))
       
      +const Queryable = require('./utils/queryable.js')
       const BaseCommand = require('./base-command.js')
       class View extends BaseCommand {
         /* istanbul ignore next - see test/lib/load-all-commands.js */
      @@ -459,56 +460,13 @@ function showFields (data, version, fields) {
             o[k] = s[k]
           })
         })
      -  return search(o, fields.split('.'), version.version, fields)
      -}
       
      -function search (data, fields, version, title) {
      -  let field
      -  const tail = fields
      -  while (!field && fields.length)
      -    field = tail.shift()
      -  fields = [field].concat(tail)
      -  let o
      -  if (!field && !tail.length) {
      -    o = {}
      -    o[version] = {}
      -    o[version][title] = data
      -    return o
      -  }
      -  let index = field.match(/(.+)\[([^\]]+)\]$/)
      -  if (index) {
      -    field = index[1]
      -    index = index[2]
      -    if (data[field] && data[field][index])
      -      return search(data[field][index], tail, version, title)
      -    else
      -      field = field + '[' + index + ']'
      -  }
      -  if (Array.isArray(data)) {
      -    if (data.length === 1)
      -      return search(data[0], fields, version, title)
      -
      -    let results = []
      -    data.forEach((data, i) => {
      -      const tl = title.length
      -      const newt = title.substr(0, tl - fields.join('.').length - 1) +
      -                 '[' + i + ']' + [''].concat(fields).join('.')
      -      results.push(search(data, fields.slice(), version, newt))
      -    })
      -    results = results.reduce(reducer, {})
      -    return results
      -  }
      -  if (!data[field])
      -    return undefined
      -  data = data[field]
      -  if (tail.length) {
      -    // there are more fields to deal with.
      -    return search(data, tail, version, title)
      -  }
      -  o = {}
      -  o[version] = {}
      -  o[version][title] = data
      -  return o
      +  const queryable = new Queryable(o)
      +  const s = queryable.query(fields)
      +  const res = { [version.version]: s }
      +
      +  if (s)
      +    return res
       }
       
       function cleanup (data) {
      diff --git a/deps/npm/man/man1/npm-audit.1 b/deps/npm/man/man1/npm-audit.1
      index ba569a749e9058..b1638993cf8a5d 100644
      --- a/deps/npm/man/man1/npm-audit.1
      +++ b/deps/npm/man/man1/npm-audit.1
      @@ -263,6 +263,8 @@ Allow unpublishing all versions of a published package\.
       Allow conflicting peerDependencies to be installed in the root project\.
       .IP \(bu 2
       Implicitly set \fB\-\-yes\fP during \fBnpm init\fP\|\.
      +.IP \(bu 2
      +Allow clobbering existing values in \fBnpm pkg\fP
       
       .RE
       .P
      @@ -278,6 +280,12 @@ Type: Boolean
       .RE
       .P
       Whether or not to output JSON data, rather than the normal output\.
      +.RS 0
      +.IP \(bu 2
      +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before
      +saving them to your \fBpackage\.json\fP\|\.
      +
      +.RE
       .P
       Not supported by all npm commands\.
       .SS \fBpackage\-lock\-only\fP
      diff --git a/deps/npm/man/man1/npm-ci.1 b/deps/npm/man/man1/npm-ci.1
      index 0d11f277eea839..f4ad77607e77ae 100644
      --- a/deps/npm/man/man1/npm-ci.1
      +++ b/deps/npm/man/man1/npm-ci.1
      @@ -81,6 +81,19 @@ cache:
       .SS Configuration
       
       
      +.SS \fBaudit\fP
      +.RS 0
      +.IP \(bu 2
      +Default: true
      +.IP \(bu 2
      +Type: Boolean
      +
      +.RE
      +.P
      +When "true" submit audit reports alongside the current npm command to the
      +default registry and all registries configured for scopes\. See the
      +documentation for npm help \fBaudit\fP for details on what is
      +submitted\.
       .SS \fBignore\-scripts\fP
       .RS 0
       .IP \(bu 2
      diff --git a/deps/npm/man/man1/npm-config.1 b/deps/npm/man/man1/npm-config.1
      index 70a2d136495eba..405160025f1895 100644
      --- a/deps/npm/man/man1/npm-config.1
      +++ b/deps/npm/man/man1/npm-config.1
      @@ -107,6 +107,12 @@ Type: Boolean
       .RE
       .P
       Whether or not to output JSON data, rather than the normal output\.
      +.RS 0
      +.IP \(bu 2
      +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before
      +saving them to your \fBpackage\.json\fP\|\.
      +
      +.RE
       .P
       Not supported by all npm commands\.
       .SS \fBglobal\fP
      @@ -142,6 +148,17 @@ Type: String
       .RE
       .P
       The command to run for \fBnpm edit\fP and \fBnpm config edit\fP\|\.
      +.SS \fBlocation\fP
      +.RS 0
      +.IP \(bu 2
      +Default: "user" unless \fB\-\-global\fP is passed, which will also set this value
      +to "global"
      +.IP \(bu 2
      +Type: "global", "user", or "project"
      +
      +.RE
      +.P
      +When passed to \fBnpm config\fP this refers to which config file to use\.
       .SS \fBlong\fP
       .RS 0
       .IP \(bu 2
      diff --git a/deps/npm/man/man1/npm-dedupe.1 b/deps/npm/man/man1/npm-dedupe.1
      index 664f973b763688..2930a90609d4ea 100644
      --- a/deps/npm/man/man1/npm-dedupe.1
      +++ b/deps/npm/man/man1/npm-dedupe.1
      @@ -188,9 +188,10 @@ Type: Boolean
       
       .RE
       .P
      -When "true" submit audit reports alongside \fBnpm install\fP runs to the default
      -registry and all registries configured for scopes\. See the documentation for
      -npm help \fBaudit\fP for details on what is submitted\.
      +When "true" submit audit reports alongside the current npm command to the
      +default registry and all registries configured for scopes\. See the
      +documentation for npm help \fBaudit\fP for details on what is
      +submitted\.
       .SS \fBbin\-links\fP
       .RS 0
       .IP \(bu 2
      diff --git a/deps/npm/man/man1/npm-explain.1 b/deps/npm/man/man1/npm-explain.1
      index ee436af72dfaf9..dee71496115b35 100644
      --- a/deps/npm/man/man1/npm-explain.1
      +++ b/deps/npm/man/man1/npm-explain.1
      @@ -67,6 +67,12 @@ Type: Boolean
       .RE
       .P
       Whether or not to output JSON data, rather than the normal output\.
      +.RS 0
      +.IP \(bu 2
      +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before
      +saving them to your \fBpackage\.json\fP\|\.
      +
      +.RE
       .P
       Not supported by all npm commands\.
       .SS \fBworkspace\fP
      diff --git a/deps/npm/man/man1/npm-find-dupes.1 b/deps/npm/man/man1/npm-find-dupes.1
      index 740ea6b4ce15f2..285dc3128d8cf0 100644
      --- a/deps/npm/man/man1/npm-find-dupes.1
      +++ b/deps/npm/man/man1/npm-find-dupes.1
      @@ -125,9 +125,10 @@ Type: Boolean
       
       .RE
       .P
      -When "true" submit audit reports alongside \fBnpm install\fP runs to the default
      -registry and all registries configured for scopes\. See the documentation for
      -npm help \fBaudit\fP for details on what is submitted\.
      +When "true" submit audit reports alongside the current npm command to the
      +default registry and all registries configured for scopes\. See the
      +documentation for npm help \fBaudit\fP for details on what is
      +submitted\.
       .SS \fBbin\-links\fP
       .RS 0
       .IP \(bu 2
      diff --git a/deps/npm/man/man1/npm-fund.1 b/deps/npm/man/man1/npm-fund.1
      index 073096e37b15f9..a1fc486010dc17 100644
      --- a/deps/npm/man/man1/npm-fund.1
      +++ b/deps/npm/man/man1/npm-fund.1
      @@ -73,6 +73,12 @@ Type: Boolean
       .RE
       .P
       Whether or not to output JSON data, rather than the normal output\.
      +.RS 0
      +.IP \(bu 2
      +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before
      +saving them to your \fBpackage\.json\fP\|\.
      +
      +.RE
       .P
       Not supported by all npm commands\.
       .SS \fBbrowser\fP
      diff --git a/deps/npm/man/man1/npm-init.1 b/deps/npm/man/man1/npm-init.1
      index cf630053bd1625..bce9c09f6ed0ca 100644
      --- a/deps/npm/man/man1/npm-init.1
      +++ b/deps/npm/man/man1/npm-init.1
      @@ -211,6 +211,8 @@ Allow unpublishing all versions of a published package\.
       Allow conflicting peerDependencies to be installed in the root project\.
       .IP \(bu 2
       Implicitly set \fB\-\-yes\fP during \fBnpm init\fP\|\.
      +.IP \(bu 2
      +Allow clobbering existing values in \fBnpm pkg\fP
       
       .RE
       .P
      diff --git a/deps/npm/man/man1/npm-install-ci-test.1 b/deps/npm/man/man1/npm-install-ci-test.1
      index b5c9bb4c57a4c6..b2fad00b06b2f1 100644
      --- a/deps/npm/man/man1/npm-install-ci-test.1
      +++ b/deps/npm/man/man1/npm-install-ci-test.1
      @@ -16,6 +16,19 @@ This command runs \fBnpm ci\fP followed immediately by \fBnpm test\fP\|\.
       .SS Configuration
       
       
      +.SS \fBaudit\fP
      +.RS 0
      +.IP \(bu 2
      +Default: true
      +.IP \(bu 2
      +Type: Boolean
      +
      +.RE
      +.P
      +When "true" submit audit reports alongside the current npm command to the
      +default registry and all registries configured for scopes\. See the
      +documentation for npm help \fBaudit\fP for details on what is
      +submitted\.
       .SS \fBignore\-scripts\fP
       .RS 0
       .IP \(bu 2
      diff --git a/deps/npm/man/man1/npm-install-test.1 b/deps/npm/man/man1/npm-install-test.1
      index ccd9c6ef055440..0b403e8fee7865 100644
      --- a/deps/npm/man/man1/npm-install-test.1
      +++ b/deps/npm/man/man1/npm-install-test.1
      @@ -181,9 +181,10 @@ Type: Boolean
       
       .RE
       .P
      -When "true" submit audit reports alongside \fBnpm install\fP runs to the default
      -registry and all registries configured for scopes\. See the documentation for
      -npm help \fBaudit\fP for details on what is submitted\.
      +When "true" submit audit reports alongside the current npm command to the
      +default registry and all registries configured for scopes\. See the
      +documentation for npm help \fBaudit\fP for details on what is
      +submitted\.
       .SS \fBbin\-links\fP
       .RS 0
       .IP \(bu 2
      diff --git a/deps/npm/man/man1/npm-install.1 b/deps/npm/man/man1/npm-install.1
      index b6c5fece489aa1..5ad3b9024fddfe 100644
      --- a/deps/npm/man/man1/npm-install.1
      +++ b/deps/npm/man/man1/npm-install.1
      @@ -583,9 +583,10 @@ Type: Boolean
       
       .RE
       .P
      -When "true" submit audit reports alongside \fBnpm install\fP runs to the default
      -registry and all registries configured for scopes\. See the documentation for
      -npm help \fBaudit\fP for details on what is submitted\.
      +When "true" submit audit reports alongside the current npm command to the
      +default registry and all registries configured for scopes\. See the
      +documentation for npm help \fBaudit\fP for details on what is
      +submitted\.
       .SS \fBbin\-links\fP
       .RS 0
       .IP \(bu 2
      diff --git a/deps/npm/man/man1/npm-link.1 b/deps/npm/man/man1/npm-link.1
      index 7f4ae29f812697..3527512232360d 100644
      --- a/deps/npm/man/man1/npm-link.1
      +++ b/deps/npm/man/man1/npm-link.1
      @@ -271,9 +271,10 @@ Type: Boolean
       
       .RE
       .P
      -When "true" submit audit reports alongside \fBnpm install\fP runs to the default
      -registry and all registries configured for scopes\. See the documentation for
      -npm help \fBaudit\fP for details on what is submitted\.
      +When "true" submit audit reports alongside the current npm command to the
      +default registry and all registries configured for scopes\. See the
      +documentation for npm help \fBaudit\fP for details on what is
      +submitted\.
       .SS \fBbin\-links\fP
       .RS 0
       .IP \(bu 2
      diff --git a/deps/npm/man/man1/npm-ls.1 b/deps/npm/man/man1/npm-ls.1
      index 3fe8962f231764..a1814ca4633e3a 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\.19\.1 /path/to/npm
      +npm@7\.20\.0 /path/to/npm
       └─┬ init\-package\-json@0\.0\.4
         └── promzard@0\.1\.5
       .fi
      @@ -94,6 +94,12 @@ Type: Boolean
       .RE
       .P
       Whether or not to output JSON data, rather than the normal output\.
      +.RS 0
      +.IP \(bu 2
      +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before
      +saving them to your \fBpackage\.json\fP\|\.
      +
      +.RE
       .P
       Not supported by all npm commands\.
       .SS \fBlong\fP
      diff --git a/deps/npm/man/man1/npm-org.1 b/deps/npm/man/man1/npm-org.1
      index faf5beccf779a1..ca4d12eb3b466b 100644
      --- a/deps/npm/man/man1/npm-org.1
      +++ b/deps/npm/man/man1/npm-org.1
      @@ -103,6 +103,12 @@ Type: Boolean
       .RE
       .P
       Whether or not to output JSON data, rather than the normal output\.
      +.RS 0
      +.IP \(bu 2
      +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before
      +saving them to your \fBpackage\.json\fP\|\.
      +
      +.RE
       .P
       Not supported by all npm commands\.
       .SS \fBparseable\fP
      diff --git a/deps/npm/man/man1/npm-outdated.1 b/deps/npm/man/man1/npm-outdated.1
      index 44949711c0a700..5bea638d57d8e9 100644
      --- a/deps/npm/man/man1/npm-outdated.1
      +++ b/deps/npm/man/man1/npm-outdated.1
      @@ -126,6 +126,12 @@ Type: Boolean
       .RE
       .P
       Whether or not to output JSON data, rather than the normal output\.
      +.RS 0
      +.IP \(bu 2
      +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before
      +saving them to your \fBpackage\.json\fP\|\.
      +
      +.RE
       .P
       Not supported by all npm commands\.
       .SS \fBlong\fP
      diff --git a/deps/npm/man/man1/npm-pack.1 b/deps/npm/man/man1/npm-pack.1
      index f881df420ad8c4..7402a53f7c9c9d 100644
      --- a/deps/npm/man/man1/npm-pack.1
      +++ b/deps/npm/man/man1/npm-pack.1
      @@ -37,6 +37,12 @@ Type: Boolean
       .RE
       .P
       Whether or not to output JSON data, rather than the normal output\.
      +.RS 0
      +.IP \(bu 2
      +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before
      +saving them to your \fBpackage\.json\fP\|\.
      +
      +.RE
       .P
       Not supported by all npm commands\.
       .SS \fBpack\-destination\fP
      diff --git a/deps/npm/man/man1/npm-pkg.1 b/deps/npm/man/man1/npm-pkg.1
      new file mode 100644
      index 00000000000000..48044b58ae77a2
      --- /dev/null
      +++ b/deps/npm/man/man1/npm-pkg.1
      @@ -0,0 +1,294 @@
      +.TH "NPM\-PKG" "1" "July 2021" "" ""
      +.SH "NAME"
      +\fBnpm-pkg\fR \- Manages your package\.json
      +.SS Synopsis
      +.P
      +.RS 2
      +.nf
      +npm pkg get [ [\. \.\.\.]]
      +npm pkg set = [\.= \.\.\.]
      +npm pkg delete  [\. \.\.\.]
      +.fi
      +.RE
      +.SS Description
      +.P
      +A command that automates the management of \fBpackage\.json\fP files\.
      +\fBnpm pkg\fP provide 3 different sub commands that allow you to modify or retrieve
      +values for given object keys in your \fBpackge\.json\fP\|\.
      +.P
      +The syntax to retrieve and set fields is a dot separated representation of
      +the nested object properties to be found within your \fBpackage\.json\fP, it's the
      +same notation used in npm help \fBview\fP to retrieve information
      +from the registry manifest, below you can find more examples on how to use it\.
      +.P
      +Returned values are always in \fBjson\fR format\.
      +.RS 0
      +.IP \(bu 2
      +\fBnpm pkg get \fP
      +  Retrieves a value \fBkey\fP, defined in your \fBpackage\.json\fP file\.
      +  For example, in order to retrieve the name of the current package, you
      +  can run:
      +.P
      +.RS 2
      +.nf
      +  npm pkg get name
      +.fi
      +.RE
      +  It's also possible to retrieve multiple values at once:
      +.P
      +.RS 2
      +.nf
      +  npm pkg get name version
      +.fi
      +.RE
      +  You can view child fields by separating them with a period\. To retrieve
      +  the value of a test \fBscript\fP value, you would run the following command:
      +.P
      +.RS 2
      +.nf
      +  npm pkg get scripts\.test
      +.fi
      +.RE
      +  For fields that are arrays, requesting a non\-numeric field will return
      +  all of the values from the objects in the list\. For example, to get all
      +  the contributor emails for a package, you would run:
      +.P
      +.RS 2
      +.nf
      +  npm pkg get contributors\.email
      +.fi
      +.RE
      +  You may also use numeric indices in square braces to specifically select
      +  an item in an array field\. To just get the email address of the first
      +  contributor in the list, you can run:
      +.P
      +.RS 2
      +.nf
      +  npm pkg get contributors[0]\.email
      +.fi
      +.RE
      +.IP \(bu 2
      +\fBnpm pkg set =\fP
      +  Sets a \fBvalue\fP in your \fBpackage\.json\fP based on the \fBfield\fP value\. When
      +  saving to your \fBpackage\.json\fP file the same set of rules used during
      +  \fBnpm install\fP and other cli commands that touches the \fBpackage\.json\fP file
      +  are used, making sure to respect the existing indentation and possibly
      +  applying some validation prior to saving values to the file\.
      +  The same syntax used to retrieve values from your package can also be used
      +  to define new properties or overriding existing ones, below are some
      +  examples of how the dot separated syntax can be used to edit your
      +  \fBpackage\.json\fP file\.
      +  Defining a new bin named \fBmynewcommand\fP in your \fBpackage\.json\fP that points
      +  to a file \fBcli\.js\fP:
      +.P
      +.RS 2
      +.nf
      +  npm pkg set bin\.mynewcommand=cli\.js
      +.fi
      +.RE
      +  Setting multiple fields at once is also possible:
      +.P
      +.RS 2
      +.nf
      +  npm pkg set description='Awesome package' engines\.node='>=10'
      +.fi
      +.RE
      +  It's also possible to add to array values, for example to add a new
      +  contributor entry:
      +.P
      +.RS 2
      +.nf
      +  npm pkg set contributors[0]\.name='Foo' contributors[0]\.email='foo@bar\.ca'
      +.fi
      +.RE
      +  You may also append items to the end of an array using the special
      +  empty bracket notation:
      +.P
      +.RS 2
      +.nf
      +  npm pkg set contributors[]\.name='Foo' contributors[]\.name='Bar'
      +.fi
      +.RE
      +  It's also possible to parse values as json prior to saving them to your
      +  \fBpackage\.json\fP file, for example in order to set a \fB"private": true\fP
      +  property:
      +.P
      +.RS 2
      +.nf
      +  npm pkg set private=true \-\-json
      +.fi
      +.RE
      +  It also enables saving values as numbers:
      +.P
      +.RS 2
      +.nf
      +  npm pkg set tap\.timeout=60 \-\-json
      +.fi
      +.RE
      +.IP \(bu 2
      +\fBnpm pkg delete \fP
      +  Deletes a \fBkey\fP from your \fBpackage\.json\fP
      +  The same syntax used to set values from your package can also be used
      +  to remove existing ones\. For example, in order to remove a script named
      +  build:
      +.P
      +.RS 2
      +.nf
      +  npm pkg delete scripts\.build
      +.fi
      +.RE
      +
      +.RE
      +.SS Workspaces support
      +.P
      +You can set/get/delete items across your configured workspaces by using the
      +\fBworkspace\fP or \fBworkspaces\fP config options\.
      +.P
      +For example, setting a \fBfunding\fP value across all configured workspaces
      +of a project:
      +.P
      +.RS 2
      +.nf
      +npm pkg set funding=https://example\.com \-\-ws
      +.fi
      +.RE
      +.P
      +When using \fBnpm pkg get\fP to retrieve info from your configured workspaces, the
      +returned result will be in a json format in which top level keys are the
      +names of each workspace, the values of these keys will be the result values
      +returned from each of the configured workspaces, e\.g:
      +.P
      +.RS 2
      +.nf
      +npm pkg get name version \-\-ws
      +{
      +  "a": {
      +    "name": "a",
      +    "version": "1\.0\.0"
      +  },
      +  "b": {
      +    "name": "b",
      +    "version": "1\.0\.0"
      +  }
      +}
      +.fi
      +.RE
      +.SS Configuration
      +
      +
      +.SS \fBforce\fP
      +.RS 0
      +.IP \(bu 2
      +Default: false
      +.IP \(bu 2
      +Type: Boolean
      +
      +.RE
      +.P
      +Removes various protections against unfortunate side effects, common
      +mistakes, unnecessary performance degradation, and malicious input\.
      +.RS 0
      +.IP \(bu 2
      +Allow clobbering non\-npm files in global installs\.
      +.IP \(bu 2
      +Allow the \fBnpm version\fP command to work on an unclean git repository\.
      +.IP \(bu 2
      +Allow deleting the cache folder with \fBnpm cache clean\fP\|\.
      +.IP \(bu 2
      +Allow installing packages that have an \fBengines\fP declaration requiring a
      +different version of npm\.
      +.IP \(bu 2
      +Allow installing packages that have an \fBengines\fP declaration requiring a
      +different version of \fBnode\fP, even if \fB\-\-engine\-strict\fP is enabled\.
      +.IP \(bu 2
      +Allow \fBnpm audit fix\fP to install modules outside your stated dependency
      +range (including SemVer\-major changes)\.
      +.IP \(bu 2
      +Allow unpublishing all versions of a published package\.
      +.IP \(bu 2
      +Allow conflicting peerDependencies to be installed in the root project\.
      +.IP \(bu 2
      +Implicitly set \fB\-\-yes\fP during \fBnpm init\fP\|\.
      +.IP \(bu 2
      +Allow clobbering existing values in \fBnpm pkg\fP
      +
      +.RE
      +.P
      +If you don't have a clear idea of what you want to do, it is strongly
      +recommended that you do not use this option!
      +.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\.
      +.RS 0
      +.IP \(bu 2
      +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before
      +saving them to your \fBpackage\.json\fP\|\.
      +
      +.RE
      +.P
      +Not supported by all npm commands\.
      +.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\.
      +
      +.SH See Also
      +.RS 0
      +.IP \(bu 2
      +npm help install
      +.IP \(bu 2
      +npm help init
      +.IP \(bu 2
      +npm help config
      +.IP \(bu 2
      +npm help set\-script
      +.IP \(bu 2
      +npm help workspaces
      +
      +.RE
      diff --git a/deps/npm/man/man1/npm-profile.1 b/deps/npm/man/man1/npm-profile.1
      index 5402a125fe6591..930fbf2d9402af 100644
      --- a/deps/npm/man/man1/npm-profile.1
      +++ b/deps/npm/man/man1/npm-profile.1
      @@ -105,6 +105,12 @@ Type: Boolean
       .RE
       .P
       Whether or not to output JSON data, rather than the normal output\.
      +.RS 0
      +.IP \(bu 2
      +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before
      +saving them to your \fBpackage\.json\fP\|\.
      +
      +.RE
       .P
       Not supported by all npm commands\.
       .SS \fBparseable\fP
      diff --git a/deps/npm/man/man1/npm-prune.1 b/deps/npm/man/man1/npm-prune.1
      index 863283a87cb0b7..41b7b00a5cdb1c 100644
      --- a/deps/npm/man/man1/npm-prune.1
      +++ b/deps/npm/man/man1/npm-prune.1
      @@ -80,6 +80,12 @@ Type: Boolean
       .RE
       .P
       Whether or not to output JSON data, rather than the normal output\.
      +.RS 0
      +.IP \(bu 2
      +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before
      +saving them to your \fBpackage\.json\fP\|\.
      +
      +.RE
       .P
       Not supported by all npm commands\.
       .SS \fBworkspace\fP
      diff --git a/deps/npm/man/man1/npm-search.1 b/deps/npm/man/man1/npm-search.1
      index 9b0b17b433ccd7..d500a4e8ef8b92 100644
      --- a/deps/npm/man/man1/npm-search.1
      +++ b/deps/npm/man/man1/npm-search.1
      @@ -57,6 +57,12 @@ Type: Boolean
       .RE
       .P
       Whether or not to output JSON data, rather than the normal output\.
      +.RS 0
      +.IP \(bu 2
      +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before
      +saving them to your \fBpackage\.json\fP\|\.
      +
      +.RE
       .P
       Not supported by all npm commands\.
       .SS \fBcolor\fP
      diff --git a/deps/npm/man/man1/npm-team.1 b/deps/npm/man/man1/npm-team.1
      index 2fef23d16b084a..54e27248b54b80 100644
      --- a/deps/npm/man/man1/npm-team.1
      +++ b/deps/npm/man/man1/npm-team.1
      @@ -150,6 +150,12 @@ Type: Boolean
       .RE
       .P
       Whether or not to output JSON data, rather than the normal output\.
      +.RS 0
      +.IP \(bu 2
      +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before
      +saving them to your \fBpackage\.json\fP\|\.
      +
      +.RE
       .P
       Not supported by all npm commands\.
       
      diff --git a/deps/npm/man/man1/npm-unpublish.1 b/deps/npm/man/man1/npm-unpublish.1
      index 8bee0313fca987..edef7115fc040a 100644
      --- a/deps/npm/man/man1/npm-unpublish.1
      +++ b/deps/npm/man/man1/npm-unpublish.1
      @@ -93,6 +93,8 @@ Allow unpublishing all versions of a published package\.
       Allow conflicting peerDependencies to be installed in the root project\.
       .IP \(bu 2
       Implicitly set \fB\-\-yes\fP during \fBnpm init\fP\|\.
      +.IP \(bu 2
      +Allow clobbering existing values in \fBnpm pkg\fP
       
       .RE
       .P
      diff --git a/deps/npm/man/man1/npm-update.1 b/deps/npm/man/man1/npm-update.1
      index 6e1ccbcaadff30..ca717f8d02fb2e 100644
      --- a/deps/npm/man/man1/npm-update.1
      +++ b/deps/npm/man/man1/npm-update.1
      @@ -13,7 +13,9 @@ aliases: up, upgrade
       .SS Description
       .P
       This command will update all the packages listed to the latest version
      -(specified by the \fBtag\fP config), respecting semver\.
      +(specified by the \fBtag\fP config), respecting the semver constraints of
      +both your package and its dependencies (if they also require the same
      +package)\.
       .P
       It will also install missing packages\.
       .P
      @@ -103,6 +105,41 @@ If the dependence were on \fB^0\.4\.0\fP:
       .P
       Then \fBnpm update\fP will install \fBdep1@0\.4\.1\fP, because that is the highest\-sorting
       version that satisfies \fB^0\.4\.0\fP (\fB>= 0\.4\.0 <0\.5\.0\fP)
      +.SS Subdependencies
      +.P
      +Suppose your app now also has a dependency on \fBdep2\fP
      +.P
      +.RS 2
      +.nf
      +{
      +  "name": "my\-app",
      +  "dependencies": {
      +      "dep1": "^1\.0\.0",
      +      "dep2": "1\.0\.0"
      +  }
      +}
      +.fi
      +.RE
      +.P
      +and \fBdep2\fP itself depends on this limited range of \fBdep1\fP
      +.P
      +.RS 2
      +.nf
      +{
      +"name": "dep2",
      +  "dependencies": {
      +    "dep1": "~1\.1\.1"
      +  }
      +}
      +.fi
      +.RE
      +.P
      +Then \fBnpm update\fP will install \fBdep1@1\.1\.2\fP because that is the highest
      +version that \fBdep2\fP allows\.  npm will prioritize having a single version
      +of \fBdep1\fP in your tree rather than two when that single version can
      +satisfy the semver requirements of multiple dependencies in your tree\.
      +In this case if you really did need your package to use a newer version
      +you would need to use \fBnpm install\fP\|\.
       .SS Updating Globally\-Installed Packages
       .P
       \fBnpm update \-g\fP will apply the \fBupdate\fP action to each globally installed
      @@ -250,9 +287,10 @@ Type: Boolean
       
       .RE
       .P
      -When "true" submit audit reports alongside \fBnpm install\fP runs to the default
      -registry and all registries configured for scopes\. See the documentation for
      -npm help \fBaudit\fP for details on what is submitted\.
      +When "true" submit audit reports alongside the current npm command to the
      +default registry and all registries configured for scopes\. See the
      +documentation for npm help \fBaudit\fP for details on what is
      +submitted\.
       .SS \fBbin\-links\fP
       .RS 0
       .IP \(bu 2
      diff --git a/deps/npm/man/man1/npm-version.1 b/deps/npm/man/man1/npm-version.1
      index 874337beb37927..f798ed97a15223 100644
      --- a/deps/npm/man/man1/npm-version.1
      +++ b/deps/npm/man/man1/npm-version.1
      @@ -56,6 +56,12 @@ Type: Boolean
       .RE
       .P
       Whether or not to output JSON data, rather than the normal output\.
      +.RS 0
      +.IP \(bu 2
      +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before
      +saving them to your \fBpackage\.json\fP\|\.
      +
      +.RE
       .P
       Not supported by all npm commands\.
       .SS \fBpreid\fP
      diff --git a/deps/npm/man/man1/npm-view.1 b/deps/npm/man/man1/npm-view.1
      index 08d9fe0abd3a9f..a63cab9feec386 100644
      --- a/deps/npm/man/man1/npm-view.1
      +++ b/deps/npm/man/man1/npm-view.1
      @@ -55,7 +55,7 @@ npm view opts@$(npm view ronn dependencies\.opts)
       .P
       For fields that are arrays, requesting a non\-numeric field will return
       all of the values from the objects in the list\. For example, to get all
      -the contributor names for the \fBexpress\fP package, you would run:
      +the contributor email addresses for the \fBexpress\fP package, you would run:
       .P
       .RS 2
       .nf
      @@ -124,6 +124,12 @@ Type: Boolean
       .RE
       .P
       Whether or not to output JSON data, rather than the normal output\.
      +.RS 0
      +.IP \(bu 2
      +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before
      +saving them to your \fBpackage\.json\fP\|\.
      +
      +.RE
       .P
       Not supported by all npm commands\.
       .SS \fBworkspace\fP
      diff --git a/deps/npm/man/man1/npm.1 b/deps/npm/man/man1/npm.1
      index d73ecc120df55c..36f677399d49b1 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\.19\.1
      +7\.20\.0
       .SS Description
       .P
       npm is the package manager for the Node JavaScript platform\.  It puts
      diff --git a/deps/npm/man/man5/folders.5 b/deps/npm/man/man5/folders.5
      index e0f5574b747694..80b6db8074002f 100644
      --- a/deps/npm/man/man5/folders.5
      +++ b/deps/npm/man/man5/folders.5
      @@ -46,13 +46,15 @@ Global installs on Windows go to \fB{prefix}/node_modules\fP (that is, no
       Scoped packages are installed the same way, except they are grouped together
       in a sub\-folder of the relevant \fBnode_modules\fP folder with the name of that
       scope prefix by the @ symbol, e\.g\. \fBnpm install @myorg/package\fP would place
      -the package in \fB{prefix}/node_modules/@myorg/package\fP\|\. See npm help \fBscope\fP for more details\.
      +the package in \fB{prefix}/node_modules/@myorg/package\fP\|\. See
      +npm help \fBscope\fP for more details\.
       .P
       If you wish to \fBrequire()\fP a package, then install it locally\.
       .SS Executables
       .P
       When in global mode, executables are linked into \fB{prefix}/bin\fP on Unix,
      -or directly into \fB{prefix}\fP on Windows\.
      +or directly into \fB{prefix}\fP on Windows\.  Ensure that path is in your
      +terminal's \fBPATH\fP environment to run them\.
       .P
       When in local mode, executables are linked into
       \fB\|\./node_modules/\.bin\fP so that they can be made available to scripts run
      diff --git a/deps/npm/man/man5/package-json.5 b/deps/npm/man/man5/package-json.5
      index f97a3d2d5fdb1d..323394188a455b 100644
      --- a/deps/npm/man/man5/package-json.5
      +++ b/deps/npm/man/man5/package-json.5
      @@ -388,9 +388,12 @@ install into the PATH\. npm makes this pretty easy (in fact, it uses this
       feature to install the "npm" executable\.)
       .P
       To use this, supply a \fBbin\fP field in your package\.json which is a map of
      -command name to local file name\. On install, npm will symlink that file
      -into \fBprefix/bin\fP for global installs, or \fB\|\./node_modules/\.bin/\fP for local
      -installs\.
      +command name to local file name\. When this package is installed
      +globally, that file will be linked where global bins go so it is
      +available to run by name\.  When this package is installed as a
      +dependency in another package, the file will be linked where it will be
      +available to that package either directly by \fBnpm exec\fP or by name in other
      +scripts when invoking them via \fBnpm run\-script\fP\|\.
       .P
       For example, myapp could have this:
       .P
      @@ -439,6 +442,9 @@ Please make sure that your file(s) referenced in \fBbin\fP starts with
       executable!
       .P
       Note that you can also set the executable files using directories\.bin \fI#directoriesbin\fR\|\.
      +.P
      +See npm help folders for more info on
      +executables\.
       .SS man
       .P
       Specify either a single file or an array of filenames to put in place for
      diff --git a/deps/npm/man/man7/config.7 b/deps/npm/man/man7/config.7
      index 048dcf14113927..ac0a415f10a363 100644
      --- a/deps/npm/man/man7/config.7
      +++ b/deps/npm/man/man7/config.7
      @@ -72,6 +72,8 @@ The following shorthands are parsed on the command\-line:
       .IP \(bu 2
       \fB\-g\fP: \fB\-\-global\fP
       .IP \(bu 2
      +\fB\-L\fP: \fB\-\-location\fP
      +.IP \(bu 2
       \fB\-d\fP: \fB\-\-loglevel info\fP
       .IP \(bu 2
       \fB\-s\fP: \fB\-\-loglevel silent\fP
      @@ -226,9 +228,10 @@ Type: Boolean
       
       .RE
       .P
      -When "true" submit audit reports alongside \fBnpm install\fP runs to the default
      -registry and all registries configured for scopes\. See the documentation for
      -npm help \fBaudit\fP for details on what is submitted\.
      +When "true" submit audit reports alongside the current npm command to the
      +default registry and all registries configured for scopes\. See the
      +documentation for npm help \fBaudit\fP for details on what is
      +submitted\.
       .SS \fBaudit\-level\fP
       .RS 0
       .IP \(bu 2
      @@ -663,6 +666,8 @@ Allow unpublishing all versions of a published package\.
       Allow conflicting peerDependencies to be installed in the root project\.
       .IP \(bu 2
       Implicitly set \fB\-\-yes\fP during \fBnpm init\fP\|\.
      +.IP \(bu 2
      +Allow clobbering existing values in \fBnpm pkg\fP
       
       .RE
       .P
      @@ -931,6 +936,12 @@ Type: Boolean
       .RE
       .P
       Whether or not to output JSON data, rather than the normal output\.
      +.RS 0
      +.IP \(bu 2
      +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before
      +saving them to your \fBpackage\.json\fP\|\.
      +
      +.RE
       .P
       Not supported by all npm commands\.
       .SS \fBkey\fP
      @@ -1007,6 +1018,17 @@ Type: IP Address
       .P
       The IP address of the local interface to use when making connections to the
       npm registry\. Must be IPv4 in versions of Node prior to 0\.12\.
      +.SS \fBlocation\fP
      +.RS 0
      +.IP \(bu 2
      +Default: "user" unless \fB\-\-global\fP is passed, which will also set this value
      +to "global"
      +.IP \(bu 2
      +Type: "global", "user", or "project"
      +
      +.RE
      +.P
      +When passed to \fBnpm config\fP this refers to which config file to use\.
       .SS \fBloglevel\fP
       .RS 0
       .IP \(bu 2
      diff --git a/deps/npm/man/man7/scripts.7 b/deps/npm/man/man7/scripts.7
      index 56a3326b6c445e..cac6ab0a2a3565 100644
      --- a/deps/npm/man/man7/scripts.7
      +++ b/deps/npm/man/man7/scripts.7
      @@ -60,7 +60,8 @@ script, its \fBdependencies\fP and \fBdevDependencies\fP will be installed, and
       the prepare script will be run, before the package is packaged and
       installed\.
       .IP \(bu 2
      -As of \fBnpm@7\fP these scripts run in the background
      +As of \fBnpm@7\fP these scripts run in the background\.
      +To see the output, run with: \fB\-\-foreground\-scripts\fP\|\.
       
       .RE
       .P
      @@ -391,8 +392,8 @@ Scripts are run by passing the line as a script argument to \fBsh\fP\|\.
       If the script exits with a code other than 0, then this will abort the
       process\.
       .P
      -Note that these script files don't have to be nodejs or even
      -javascript programs\. They just have to be some kind of executable
      +Note that these script files don't have to be Node\.js or even
      +JavaScript programs\. They just have to be some kind of executable
       file\.
       .SS Best Practices
       .RS 0
      diff --git a/deps/npm/man/man7/workspaces.7 b/deps/npm/man/man7/workspaces.7
      index 70abfd5f97235f..52128895a4acb7 100644
      --- a/deps/npm/man/man7/workspaces.7
      +++ b/deps/npm/man/man7/workspaces.7
      @@ -35,7 +35,7 @@ npm help \fBpackage\.json\fP file, e\.g:
       .P
       Given the above \fBpackage\.json\fP example living at a current working
       directory \fB\|\.\fP that contains a folder named \fBworkspace\-a\fP that itself contains
      -a \fBpackage\.json\fP inside it, defining a nodejs package, e\.g:
      +a \fBpackage\.json\fP inside it, defining a Node\.js package, e\.g:
       .P
       .RS 2
       .nf
      diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js
      index 5db11eb3832eb0..fdb947dc5905c3 100644
      --- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js
      +++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js
      @@ -324,7 +324,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
             .then(async root => {
               if (!this[_updateAll] && !this[_global] && !root.meta.loadedFromDisk) {
                 await new this.constructor(this.options).loadActual({ root })
      -          const tree = root.target || root
      +          const tree = root.target
                 // even though we didn't load it from a package-lock.json FILE,
                 // we still loaded it "from disk", meaning we have to reset
                 // dep flags before assuming that any mutations were reflected.
      @@ -396,7 +396,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
         // update.names request by queueing nodes dependent on those named.
         async [_applyUserRequests] (options) {
           process.emit('time', 'idealTree:userRequests')
      -    const tree = this.idealTree.target || this.idealTree
      +    const tree = this.idealTree.target
       
           if (!this[_workspaces].length)
             await this[_applyUserRequestsToNode](tree, options)
      @@ -532,7 +532,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
           /* istanbul ignore else - should also be covered by realpath failure */
           if (filepath) {
             const { name } = spec
      -      const tree = this.idealTree.target || this.idealTree
      +      const tree = this.idealTree.target
             spec = npa(`file:${relpath(tree.path, filepath)}`, tree.path)
             spec.name = name
           }
      @@ -730,7 +730,7 @@ This is a one-time fix-up, please be patient...
         // or extraneous.
         [_buildDeps] () {
           process.emit('time', 'idealTree:buildDeps')
      -    const tree = this.idealTree.target || this.idealTree
      +    const tree = this.idealTree.target
           this[_depsQueue].push(tree)
           this.log.silly('idealTree', 'buildDeps')
           this.addTracker('idealTree', tree.name, '')
      @@ -788,7 +788,11 @@ This is a one-time fix-up, please be patient...
             const Arborist = this.constructor
             const opt = { ...this.options }
             await cacache.tmp.withTmp(this.cache, opt, async path => {
      -        await pacote.extract(node.resolved, path, opt)
      +        await pacote.extract(node.resolved, path, {
      +          ...opt,
      +          resolved: node.resolved,
      +          integrity: node.integrity,
      +        })
       
               if (hasShrinkwrap) {
                 await new Arborist({ ...this.options, path })
      @@ -914,7 +918,7 @@ This is a one-time fix-up, please be patient...
           await Promise.all(promises)
       
           for (const { to } of node.edgesOut.values()) {
      -      if (to && to.isLink)
      +      if (to && to.isLink && to.target)
               this[_linkNodes].add(to)
           }
       
      @@ -1293,7 +1297,7 @@ This is a one-time fix-up, please be patient...
       
             // when installing globally, or just in global style, we never place
             // deps above the first level.
      -      const tree = this.idealTree && this.idealTree.target || this.idealTree
      +      const tree = this.idealTree && this.idealTree.target
             if (this[_globalStyle] && check.resolveParent === tree)
               break
           }
      @@ -1362,7 +1366,7 @@ This is a one-time fix-up, please be patient...
             integrity: dep.integrity,
             legacyPeerDeps: this.legacyPeerDeps,
             error: dep.errors[0],
      -      ...(dep.target ? { target: dep.target, realpath: dep.target.path } : {}),
      +      ...(dep.isLink ? { target: dep.target, realpath: dep.target.path } : {}),
           })
           if (this[_loadFailures].has(dep))
             this[_loadFailures].add(newDep)
      @@ -1421,7 +1425,7 @@ This is a one-time fix-up, please be patient...
           // prune anything deeper in the tree that can be replaced by this
           if (this.idealTree) {
             for (const node of this.idealTree.inventory.query('name', newDep.name)) {
      -        if (node.isDescendantOf(target))
      +        if (!node.isTop && node.isDescendantOf(target))
                 this[_pruneDedupable](node, false)
             }
           }
      @@ -1819,7 +1823,7 @@ This is a one-time fix-up, please be patient...
           const current = target !== entryEdge.from && target.resolve(dep.name)
           if (current) {
             for (const edge of current.edgesIn.values()) {
      -        if (edge.from.isDescendantOf(target) && edge.valid) {
      +        if (!edge.from.isTop && edge.from.isDescendantOf(target) && edge.valid) {
                 if (!edge.satisfiedBy(dep))
                   return CONFLICT
               }
      @@ -1876,7 +1880,8 @@ This is a one-time fix-up, please be patient...
             if (link.root !== this.idealTree)
               continue
       
      -      const external = /^\.\.(\/|$)/.test(relpath(this.path, link.realpath))
      +      const tree = this.idealTree.target
      +      const external = !link.target.isDescendantOf(tree)
       
             // outside the root, somebody else's problem, ignore it
             if (external && !this[_follow])
      diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/index.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/index.js
      index 94501cae12c840..b26a26c2be2abe 100644
      --- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/index.js
      +++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/index.js
      @@ -81,7 +81,7 @@ class Arborist extends Base {
               const dep = edge.to
               if (dep) {
                 set.add(dep)
      -          if (dep.target)
      +          if (dep.isLink)
                   set.add(dep.target)
               }
             }
      diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-actual.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-actual.js
      index 9fca7d6425da05..86856d868b4269 100644
      --- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-actual.js
      +++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-actual.js
      @@ -315,7 +315,7 @@ module.exports = cls => class ActualLoader extends cls {
       
         [_loadFSTree] (node) {
           const did = this[_actualTreeLoaded]
      -    node = node.target || node
      +    node = node.target
       
           // if a Link target has started, but not completed, then
           // a Promise will be in the cache to indicate this.
      diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js
      index a98ed23b2a458c..d1edcaca01d7e1 100644
      --- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js
      +++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js
      @@ -221,7 +221,7 @@ module.exports = cls => class VirtualLoader extends cls {
         [assignBundles] (nodes) {
           for (const [location, node] of nodes) {
             // Skip assignment of parentage for the root package
      -      if (!location || node.target && !node.target.location)
      +      if (!location || node.isLink && !node.target.location)
               continue
             const { name, parent, package: { inBundle }} = node
       
      diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/rebuild.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/rebuild.js
      index d189ad8c99e3ca..8e447bb8f5ad16 100644
      --- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/rebuild.js
      +++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/rebuild.js
      @@ -169,7 +169,7 @@ module.exports = cls => class Builder extends cls {
           const queue = [...set].sort(sortNodes)
       
           for (const node of queue) {
      -      const { package: { bin, scripts = {} } } = node
      +      const { package: { bin, scripts = {} } } = node.target
             const { preinstall, install, postinstall, prepare } = scripts
             const tests = { bin, preinstall, install, postinstall, prepare }
             for (const [key, has] of Object.entries(tests)) {
      @@ -202,7 +202,7 @@ module.exports = cls => class Builder extends cls {
               !(meta.originalLockfileVersion >= 2)
           }
       
      -    const { package: pkg, hasInstallScript } = node
      +    const { package: pkg, hasInstallScript } = node.target
           const { gypfile, bin, scripts = {} } = pkg
       
           const { preinstall, install, postinstall, prepare } = scripts
      @@ -263,7 +263,7 @@ module.exports = cls => class Builder extends cls {
               devOptional,
               package: pkg,
               location,
      -      } = node.target || node
      +      } = node.target
       
             // skip any that we know we'll be deleting
             if (this[_trashList].has(path))
      diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js
      index f259a69b548e10..18b5cd65262a63 100644
      --- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js
      +++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js
      @@ -289,8 +289,8 @@ module.exports = cls => class Reifier extends cls {
       
           const filterNodes = []
           if (this[_global] && this.explicitRequests.size) {
      -      const idealTree = this.idealTree.target || this.idealTree
      -      const actualTree = this.actualTree.target || this.actualTree
      +      const idealTree = this.idealTree.target
      +      const actualTree = this.actualTree.target
             // we ONLY are allowed to make changes in the global top-level
             // children where there's an explicit request.
             for (const { name } of this.explicitRequests) {
      @@ -404,10 +404,9 @@ module.exports = cls => class Reifier extends cls {
             return
       
           process.emit('time', 'reify:trashOmits')
      -    // node.parent is checked to make sure this is a node that's in the tree, and
      -    // not the parent-less top level nodes
      +
           const filter = node =>
      -      node.isDescendantOf(this.idealTree) &&
      +      node.top.isProjectRoot &&
               (node.peer && this[_omitPeer] ||
                 node.dev && this[_omitDev] ||
                 node.optional && this[_omitOptional] ||
      @@ -664,7 +663,7 @@ module.exports = cls => class Reifier extends cls {
               const node = diff.ideal
               if (!node)
                 return
      -        if (node.isProjectRoot || (node.target && node.target.isProjectRoot))
      +        if (node.isProjectRoot)
                 return
       
               const { bundleDependencies } = node.package
      @@ -887,6 +886,18 @@ module.exports = cls => class Reifier extends cls {
             filter: diff => diff.action === 'ADD' || diff.action === 'CHANGE',
           })
       
      +    // pick up link nodes from the unchanged list as we want to run their
      +    // scripts in every install despite of having a diff status change
      +    for (const node of this.diff.unchanged) {
      +      const tree = node.root.target
      +
      +      // skip links that only live within node_modules as they are most
      +      // likely managed by packages we installed, we only want to rebuild
      +      // unchanged links we directly manage
      +      if (node.isLink && node.target.fsTop === tree)
      +        nodes.push(node)
      +    }
      +
           return this.rebuild({ nodes, handleOptionalFailure: true })
             .then(() => process.emit('timeEnd', 'reify:build'))
         }
      diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/calc-dep-flags.js b/deps/npm/node_modules/@npmcli/arborist/lib/calc-dep-flags.js
      index 21d8ddcf7b442e..968fc83c5136cf 100644
      --- a/deps/npm/node_modules/@npmcli/arborist/lib/calc-dep-flags.js
      +++ b/deps/npm/node_modules/@npmcli/arborist/lib/calc-dep-flags.js
      @@ -29,7 +29,7 @@ const calcDepFlagsStep = (node) => {
         resetParents(node, 'optional')
       
         // for links, map their hierarchy appropriately
      -  if (node.target) {
      +  if (node.isLink) {
           node.target.dev = node.dev
           node.target.optional = node.optional
           node.target.devOptional = node.devOptional
      @@ -92,10 +92,10 @@ const unsetFlag = (node, flag) => {
             tree: node,
             visit: node => {
               node.extraneous = node[flag] = false
      -        if (node.target)
      +        if (node.isLink)
                 node.target.extraneous = node.target[flag] = false
             },
      -      getChildren: node => [...(node.target || node).edgesOut.values()]
      +      getChildren: node => [...node.target.edgesOut.values()]
               .filter(edge => edge.to && edge.to[flag] &&
                 (flag !== 'peer' && edge.type === 'peer' || edge.type === 'prod'))
               .map(edge => edge.to),
      diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/diff.js b/deps/npm/node_modules/@npmcli/arborist/lib/diff.js
      index 1f8eff0f0c4d9c..2008ef7a35bddf 100644
      --- a/deps/npm/node_modules/@npmcli/arborist/lib/diff.js
      +++ b/deps/npm/node_modules/@npmcli/arborist/lib/diff.js
      @@ -45,8 +45,7 @@ class Diff {
             const { root } = filterNode
             if (root !== ideal && root !== actual)
               throw new Error('invalid filterNode: outside idealTree/actualTree')
      -      const { target } = root
      -      const rootTarget = target || root
      +      const rootTarget = root.target
             const edge = [...rootTarget.edgesOut.values()].filter(e => {
               return e.to && (e.to === filterNode || e.to.target === filterNode)
             })[0]
      @@ -56,8 +55,7 @@ class Diff {
             filterSet.add(actual)
             if (edge && edge.to) {
               filterSet.add(edge.to)
      -        if (edge.to.target)
      -          filterSet.add(edge.to.target)
      +        filterSet.add(edge.to.target)
             }
             filterSet.add(filterNode)
       
      @@ -65,7 +63,7 @@ class Diff {
               tree: filterNode,
               visit: node => filterSet.add(node),
               getChildren: node => {
      -          node = node.target || node
      +          node = node.target
                 const loc = node.location
                 const idealNode = ideal.inventory.get(loc)
                 const ideals = !idealNode ? []
      diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/node.js b/deps/npm/node_modules/@npmcli/arborist/lib/node.js
      index c21bc46cfb5396..2ef0a64f088298 100644
      --- a/deps/npm/node_modules/@npmcli/arborist/lib/node.js
      +++ b/deps/npm/node_modules/@npmcli/arborist/lib/node.js
      @@ -409,7 +409,7 @@ class Node {
         }
       
         isDescendantOf (node) {
      -    for (let p = this; p; p = p.parent) {
      +    for (let p = this; p; p = p.resolveParent) {
             if (p === node)
               return true
           }
      @@ -649,7 +649,7 @@ class Node {
               })
       
               if (this.isLink) {
      -          const target = node.target || node
      +          const target = node.target
                 this[_target] = target
                 this[_package] = target.package
                 target.linksIn.add(this)
      @@ -1174,7 +1174,7 @@ class Node {
         }
       
         get target () {
      -    return null
      +    return this
         }
       
         set target (n) {
      @@ -1197,6 +1197,14 @@ class Node {
           return this.isTop ? this : this.parent.top
         }
       
      +  get isFsTop () {
      +    return !this.fsParent
      +  }
      +
      +  get fsTop () {
      +    return this.isFsTop ? this : this.fsParent.fsTop
      +  }
      +
         get resolveParent () {
           return this.parent || this.fsParent
         }
      diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/shrinkwrap.js b/deps/npm/node_modules/@npmcli/arborist/lib/shrinkwrap.js
      index b251539a94c902..3b2cf0bde10361 100644
      --- a/deps/npm/node_modules/@npmcli/arborist/lib/shrinkwrap.js
      +++ b/deps/npm/node_modules/@npmcli/arborist/lib/shrinkwrap.js
      @@ -802,7 +802,7 @@ class Shrinkwrap {
           if (this.tree) {
             if (this.yarnLock)
               this.yarnLock.fromTree(this.tree)
      -      const root = Shrinkwrap.metaFromNode(this.tree.target || this.tree, this.path)
      +      const root = Shrinkwrap.metaFromNode(this.tree.target, this.path)
             this.data.packages = {}
             if (Object.keys(root).length)
               this.data.packages[''] = root
      @@ -864,7 +864,7 @@ class Shrinkwrap {
           const spec = !edge ? rSpec
             : npa.resolve(node.name, edge.spec, edge.from.realpath)
       
      -    if (node.target)
      +    if (node.isLink)
             lock.version = `file:${relpath(this.path, node.realpath)}`
           else if (spec && (spec.type === 'file' || spec.type === 'remote'))
             lock.version = spec.saveSpec
      @@ -888,7 +888,7 @@ class Shrinkwrap {
           // when we didn't resolve to git, file, or dir, and didn't request
           // git, file, dir, or remote, then the resolved value is necessary.
           if (node.resolved &&
      -        !node.target &&
      +        !node.isLink &&
               rSpec.type !== 'git' &&
               rSpec.type !== 'file' &&
               rSpec.type !== 'directory' &&
      @@ -917,7 +917,7 @@ class Shrinkwrap {
               lock.optional = true
           }
       
      -    const depender = node.target || node
      +    const depender = node.target
           if (depender.edgesOut.size > 0) {
             if (node !== this.tree) {
               lock.requires = [...depender.edgesOut.entries()].reduce((set, [k, v]) => {
      @@ -942,7 +942,7 @@ class Shrinkwrap {
           }
       
           // now we walk the children, putting them in the 'dependencies' object
      -    const {children} = node.target || node
      +    const {children} = node.target
           if (!children.size)
             delete lock.dependencies
           else {
      diff --git a/deps/npm/node_modules/@npmcli/arborist/package.json b/deps/npm/node_modules/@npmcli/arborist/package.json
      index 138d6ec25b4c2d..c45a61086ea5e3 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.4",
      +  "version": "2.7.1",
         "description": "Manage node_modules trees",
         "dependencies": {
           "@npmcli/installed-package-contents": "^1.0.7",
      @@ -16,6 +16,7 @@
           "common-ancestor-path": "^1.0.1",
           "json-parse-even-better-errors": "^2.3.1",
           "json-stringify-nice": "^1.1.4",
      +    "mkdirp": "^1.0.4",
           "mkdirp-infer-owner": "^2.0.0",
           "npm-install-checks": "^4.0.0",
           "npm-package-arg": "^8.1.0",
      @@ -28,7 +29,9 @@
           "promise-call-limit": "^1.0.1",
           "read-package-json-fast": "^2.0.2",
           "readdir-scoped-modules": "^1.1.0",
      +    "rimraf": "^3.0.2",
           "semver": "^7.3.5",
      +    "ssri": "^8.0.1",
           "tar": "^6.1.0",
           "treeverse": "^1.0.4",
           "walk-up-path": "^1.0.0"
      diff --git a/deps/npm/node_modules/@npmcli/git/lib/errors.js b/deps/npm/node_modules/@npmcli/git/lib/errors.js
      new file mode 100644
      index 00000000000000..25b2b9f9fd6a6a
      --- /dev/null
      +++ b/deps/npm/node_modules/@npmcli/git/lib/errors.js
      @@ -0,0 +1,36 @@
      +
      +const maxRetry = 3
      +
      +class GitError extends Error {
      +  shouldRetry () {
      +    return false
      +  }
      +}
      +
      +class GitConnectionError extends GitError {
      +  constructor (message) {
      +    super('A git connection error occurred')
      +  }
      +
      +  shouldRetry (number) {
      +    return number < maxRetry
      +  }
      +}
      +
      +class GitPathspecError extends GitError {
      +  constructor (message) {
      +    super('The git reference could not be found')
      +  }
      +}
      +
      +class GitUnknownError extends GitError {
      +  constructor (message) {
      +    super('An unknown git error occurred')
      +  }
      +}
      +
      +module.exports = {
      +  GitConnectionError,
      +  GitPathspecError,
      +  GitUnknownError
      +}
      diff --git a/deps/npm/node_modules/@npmcli/git/lib/index.js b/deps/npm/node_modules/@npmcli/git/lib/index.js
      index 50fd889b89b5ad..20d7cfd01cfd12 100644
      --- a/deps/npm/node_modules/@npmcli/git/lib/index.js
      +++ b/deps/npm/node_modules/@npmcli/git/lib/index.js
      @@ -4,5 +4,6 @@ module.exports = {
         spawn: require('./spawn.js'),
         is: require('./is.js'),
         find: require('./find.js'),
      -  isClean: require('./is-clean.js')
      +  isClean: require('./is-clean.js'),
      +  errors: require('./errors.js')
       }
      diff --git a/deps/npm/node_modules/@npmcli/git/lib/make-error.js b/deps/npm/node_modules/@npmcli/git/lib/make-error.js
      new file mode 100644
      index 00000000000000..043a8e6e95181e
      --- /dev/null
      +++ b/deps/npm/node_modules/@npmcli/git/lib/make-error.js
      @@ -0,0 +1,33 @@
      +const {
      +  GitConnectionError,
      +  GitPathspecError,
      +  GitUnknownError
      +} = require('./errors.js')
      +
      +const connectionErrorRe = new RegExp([
      +  'remote error: Internal Server Error',
      +  'The remote end hung up unexpectedly',
      +  'Connection timed out',
      +  'Operation timed out',
      +  'Failed to connect to .* Timed out',
      +  'Connection reset by peer',
      +  'SSL_ERROR_SYSCALL',
      +  'The requested URL returned error: 503'
      +].join('|'))
      +
      +const missingPathspecRe = /pathspec .* did not match any file\(s\) known to git/
      +
      +function makeError (er) {
      +  const message = er.stderr
      +  let gitEr
      +  if (connectionErrorRe.test(message)) {
      +    gitEr = new GitConnectionError(message)
      +  } else if (missingPathspecRe.test(message)) {
      +    gitEr = new GitPathspecError(message)
      +  } else {
      +    gitEr = new GitUnknownError(message)
      +  }
      +  return Object.assign(gitEr, er)
      +}
      +
      +module.exports = makeError
      diff --git a/deps/npm/node_modules/@npmcli/git/lib/should-retry.js b/deps/npm/node_modules/@npmcli/git/lib/should-retry.js
      deleted file mode 100644
      index 8082bb5d7c6e71..00000000000000
      --- a/deps/npm/node_modules/@npmcli/git/lib/should-retry.js
      +++ /dev/null
      @@ -1,17 +0,0 @@
      -const transientErrors = [
      -  'remote error: Internal Server Error',
      -  'The remote end hung up unexpectedly',
      -  'Connection timed out',
      -  'Operation timed out',
      -  'Failed to connect to .* Timed out',
      -  'Connection reset by peer',
      -  'SSL_ERROR_SYSCALL',
      -  'The requested URL returned error: 503'
      -].join('|')
      -
      -const transientErrorRe = new RegExp(transientErrors)
      -
      -const maxRetry = 3
      -
      -module.exports = (error, number) =>
      -  transientErrorRe.test(error) && (number < maxRetry)
      diff --git a/deps/npm/node_modules/@npmcli/git/lib/spawn.js b/deps/npm/node_modules/@npmcli/git/lib/spawn.js
      index 337164a9a012dc..1c89a4c53cf86a 100644
      --- a/deps/npm/node_modules/@npmcli/git/lib/spawn.js
      +++ b/deps/npm/node_modules/@npmcli/git/lib/spawn.js
      @@ -1,6 +1,6 @@
       const spawn = require('@npmcli/promise-spawn')
       const promiseRetry = require('promise-retry')
      -const shouldRetry = require('./should-retry.js')
      +const makeError = require('./make-error.js')
       const whichGit = require('./which.js')
       const makeOpts = require('./opts.js')
       const procLog = require('./proc-log.js')
      @@ -33,10 +33,11 @@ module.exports = (gitArgs, opts = {}) => {
       
           return spawn(gitPath, args, makeOpts(opts))
             .catch(er => {
      -        if (!shouldRetry(er.stderr, number)) {
      -          throw er
      +        const gitError = makeError(er)
      +        if (!gitError.shouldRetry(number)) {
      +          throw gitError
               }
      -        retry(er)
      +        retry(gitError)
             })
         }, retry)
       }
      diff --git a/deps/npm/node_modules/@npmcli/git/package.json b/deps/npm/node_modules/@npmcli/git/package.json
      index 0fe94686ece20c..9475da5007a7dc 100644
      --- a/deps/npm/node_modules/@npmcli/git/package.json
      +++ b/deps/npm/node_modules/@npmcli/git/package.json
      @@ -1,6 +1,6 @@
       {
         "name": "@npmcli/git",
      -  "version": "2.0.9",
      +  "version": "2.1.0",
         "main": "lib/index.js",
         "files": [
           "lib/*.js"
      diff --git a/deps/npm/node_modules/make-fetch-happen/lib/cache/entry.js b/deps/npm/node_modules/make-fetch-happen/lib/cache/entry.js
      index 41f8a3d215ee14..a2acea156ee6f5 100644
      --- a/deps/npm/node_modules/make-fetch-happen/lib/cache/entry.js
      +++ b/deps/npm/node_modules/make-fetch-happen/lib/cache/entry.js
      @@ -48,6 +48,7 @@ const KEEP_RESPONSE_HEADERS = [
       // return an object containing all metadata to be written to the index
       const getMetadata = (request, response, options) => {
         const metadata = {
      +    time: Date.now(),
           url: request.url,
           reqHeaders: {},
           resHeaders: {},
      @@ -112,9 +113,18 @@ const _policy = Symbol('policy')
       
       class CacheEntry {
         constructor ({ entry, request, response, options }) {
      -    this.entry = entry
      +    if (entry) {
      +      this.key = entry.key
      +      this.entry = entry
      +      // previous versions of this module didn't write an explicit timestamp in
      +      // the metadata, so fall back to the entry's timestamp. we can't use the
      +      // entry timestamp to determine staleness because cacache will update it
      +      // when it verifies its data
      +      this.entry.metadata.time = this.entry.metadata.time || this.entry.time
      +    } else
      +      this.key = cacheKey(request)
      +
           this.options = options
      -    this.key = entry ? entry.key : cacheKey(request)
       
           // these properties are behind getters that lazily evaluate
           this[_request] = request
      @@ -340,13 +350,25 @@ class CacheEntry {
                   const content = await cacache.get.byDigest(this.options.cachePath, this.entry.integrity, { memoize: this.options.memoize })
                   body.end(content)
                 } catch (err) {
      +            if (err.code === 'EINTEGRITY')
      +              await cacache.rm.content(this.options.cachePath, this.entry.integrity, { memoize: this.options.memoize })
      +            if (err.code === 'ENOENT' || err.code === 'EINTEGRITY')
      +              await CacheEntry.invalidate(this.request, this.options)
                   body.emit('error', err)
                 }
               }
             } else {
               onResume = () => {
                 const cacheStream = cacache.get.stream.byDigest(this.options.cachePath, this.entry.integrity, { memoize: this.options.memoize })
      -          cacheStream.on('error', (err) => body.emit('error', err))
      +          cacheStream.on('error', async (err) => {
      +            cacheStream.pause()
      +            if (err.code === 'EINTEGRITY')
      +              await cacache.rm.content(this.options.cachePath, this.entry.integrity, { memoize: this.options.memoize })
      +            if (err.code === 'ENOENT' || err.code === 'EINTEGRITY')
      +              await CacheEntry.invalidate(this.request, this.options)
      +            body.emit('error', err)
      +            cacheStream.resume()
      +          })
                 cacheStream.pipe(body)
               }
             }
      @@ -368,7 +390,7 @@ class CacheEntry {
           response.headers.set('x-local-cache-key', encodeURIComponent(this.key))
           response.headers.set('x-local-cache-mode', shouldBuffer ? 'buffer' : 'stream')
           response.headers.set('x-local-cache-status', status)
      -    response.headers.set('x-local-cache-time', new Date(this.entry.time).toUTCString())
      +    response.headers.set('x-local-cache-time', new Date(this.entry.metadata.time).toUTCString())
           return response
         }
       
      diff --git a/deps/npm/node_modules/make-fetch-happen/lib/cache/policy.js b/deps/npm/node_modules/make-fetch-happen/lib/cache/policy.js
      index 189dce80ee68ed..e0959f64ddf9df 100644
      --- a/deps/npm/node_modules/make-fetch-happen/lib/cache/policy.js
      +++ b/deps/npm/node_modules/make-fetch-happen/lib/cache/policy.js
      @@ -67,7 +67,7 @@ class CachePolicy {
             // this is necessary because the CacheSemantics constructor forces
             // the value to Date.now() which means a policy created from a
             // cache entry is likely to always identify itself as stale
      -      this.policy._responseTime = this.entry.time
      +      this.policy._responseTime = this.entry.metadata.time
           }
         }
       
      diff --git a/deps/npm/node_modules/make-fetch-happen/lib/remote.js b/deps/npm/node_modules/make-fetch-happen/lib/remote.js
      index e37f39de845f38..7e4ed24edb5304 100644
      --- a/deps/npm/node_modules/make-fetch-happen/lib/remote.js
      +++ b/deps/npm/node_modules/make-fetch-happen/lib/remote.js
      @@ -14,6 +14,7 @@ const RETRY_ERRORS = [
         'ECONNREFUSED', // remote host refused to open connection
         'EADDRINUSE', // failed to bind to a local port (proxy?)
         'ETIMEDOUT', // someone in the transaction is WAY TOO SLOW
      +  'ERR_SOCKET_TIMEOUT', // same as above, but this one comes from agentkeepalive
         // Known codes we do NOT retry on:
         // ENOTFOUND (getaddrinfo failure. Either bad hostname, or offline)
       ]
      diff --git a/deps/npm/node_modules/make-fetch-happen/package.json b/deps/npm/node_modules/make-fetch-happen/package.json
      index 44330998bb02f7..e4a26a9cd94dfc 100644
      --- a/deps/npm/node_modules/make-fetch-happen/package.json
      +++ b/deps/npm/node_modules/make-fetch-happen/package.json
      @@ -1,6 +1,6 @@
       {
         "name": "make-fetch-happen",
      -  "version": "9.0.3",
      +  "version": "9.0.4",
         "description": "Opinionated, caching, retrying fetch client",
         "main": "lib/index.js",
         "files": [
      diff --git a/deps/npm/node_modules/minipass-fetch/lib/index.js b/deps/npm/node_modules/minipass-fetch/lib/index.js
      index d6ed57942e80f4..2ffcba85105540 100644
      --- a/deps/npm/node_modules/minipass-fetch/lib/index.js
      +++ b/deps/npm/node_modules/minipass-fetch/lib/index.js
      @@ -94,6 +94,19 @@ const fetch = (url, opts) => {
           }
       
           req.on('error', er => {
      +      // if a 'response' event is emitted before the 'error' event, then by the
      +      // time this handler is run it's too late to reject the Promise for the
      +      // response. instead, we forward the error event to the response stream
      +      // so that the error will surface to the user when they try to consume
      +      // the body. this is done as a side effect of aborting the request except
      +      // for in windows, where we must forward the event manually, otherwise
      +      // there is no longer a ref'd socket attached to the request and the
      +      // stream never ends so the event loop runs out of work and the process
      +      // exits without warning.
      +      // coverage skipped here due to the difficulty in testing
      +      // istanbul ignore next
      +      if (req.res)
      +        req.res.emit('error', er)
             reject(new FetchError(`request to ${request.url} failed, reason: ${
               er.message}`, 'system', er))
             finalize()
      @@ -286,8 +299,16 @@ const fetch = (url, opts) => {
       
       
             // for br
      -      if (codings == 'br' && typeof zlib.BrotliDecompress === 'function') {
      -        const decoder = new zlib.BrotliDecompress()
      +      if (codings == 'br') {
      +        // ignoring coverage so tests don't have to fake support (or lack of) for brotli
      +        // istanbul ignore next
      +        try {
      +          var decoder = new zlib.BrotliDecompress()
      +        } catch (err) {
      +          reject(err)
      +          finalize()
      +          return
      +        }
               // exceedingly rare that the stream would have an error,
               // but just in case we proxy it to the stream in use.
               body.on('error', /* istanbul ignore next */ er => decoder.emit('error', er)).pipe(decoder)
      diff --git a/deps/npm/node_modules/minipass-fetch/lib/request.js b/deps/npm/node_modules/minipass-fetch/lib/request.js
      index c5208a7fc1300a..173f415d18e7b4 100644
      --- a/deps/npm/node_modules/minipass-fetch/lib/request.js
      +++ b/deps/npm/node_modules/minipass-fetch/lib/request.js
      @@ -77,6 +77,7 @@ class Request extends Body {
             crl,
             dhparam,
             ecdhCurve,
      +      family,
             honorCipherOrder,
             key,
             passphrase,
      @@ -101,6 +102,7 @@ class Request extends Body {
             crl,
             dhparam,
             ecdhCurve,
      +      family,
             honorCipherOrder,
             key,
             passphrase,
      @@ -208,6 +210,7 @@ class Request extends Body {
             crl,
             dhparam,
             ecdhCurve,
      +      family,
             honorCipherOrder,
             key,
             passphrase,
      @@ -234,6 +237,7 @@ class Request extends Body {
             crl,
             dhparam,
             ecdhCurve,
      +      family,
             honorCipherOrder,
             key,
             passphrase,
      diff --git a/deps/npm/node_modules/minipass-fetch/package.json b/deps/npm/node_modules/minipass-fetch/package.json
      index df48f372a60796..64dab7816bd120 100644
      --- a/deps/npm/node_modules/minipass-fetch/package.json
      +++ b/deps/npm/node_modules/minipass-fetch/package.json
      @@ -1,6 +1,6 @@
       {
         "name": "minipass-fetch",
      -  "version": "1.3.3",
      +  "version": "1.3.4",
         "description": "An implementation of window.fetch in Node.js using Minipass streams",
         "license": "MIT",
         "main": "lib/index.js",
      diff --git a/deps/npm/node_modules/pacote/lib/fetcher.js b/deps/npm/node_modules/pacote/lib/fetcher.js
      index d488e88ff72369..69dd025b7bd98e 100644
      --- a/deps/npm/node_modules/pacote/lib/fetcher.js
      +++ b/deps/npm/node_modules/pacote/lib/fetcher.js
      @@ -119,6 +119,13 @@ class FetcherBase {
             '--no-progress',
             '--no-save',
             '--no-audit',
      +      // override any omit settings from the environment
      +      '--include=dev',
      +      '--include=peer',
      +      '--include=optional',
      +      // we need the actual things, not just the lockfile
      +      '--no-package-lock-only',
      +      '--no-dry-run',
           ]
         }
       
      @@ -430,6 +437,7 @@ class FetcherBase {
           return {
             cwd,
             noChmod: true,
      +      noMtime: true,
             filter: (name, entry) => {
               if (/Link$/.test(entry.type))
                 return false
      diff --git a/deps/npm/node_modules/pacote/lib/git.js b/deps/npm/node_modules/pacote/lib/git.js
      index 973e13ea9be43d..18f42547bb3ac9 100644
      --- a/deps/npm/node_modules/pacote/lib/git.js
      +++ b/deps/npm/node_modules/pacote/lib/git.js
      @@ -85,6 +85,9 @@ class GitFetcher extends Fetcher {
         [_resolvedFromHosted] (hosted) {
           return this[_resolvedFromRepo](hosted.https && hosted.https())
             .catch(er => {
      +        // Throw early since we know pathspec errors will fail again if retried
      +        if (er instanceof git.errors.GitPathspecError)
      +          throw er
               const ssh = hosted.sshurl && hosted.sshurl()
               // no fallthrough if we can't fall through or have https auth
               if (!ssh || hosted.auth)
      @@ -260,9 +263,11 @@ class GitFetcher extends Fetcher {
         // is present, otherwise ssh if the hosted type provides it
         [_cloneHosted] (ref, tmp) {
           const hosted = this.spec.hosted
      -    const https = hosted.https()
           return this[_cloneRepo](hosted.https({ noCommittish: true }), ref, tmp)
             .catch(er => {
      +        // Throw early since we know pathspec errors will fail again if retried
      +        if (er instanceof git.errors.GitPathspecError)
      +          throw er
               const ssh = hosted.sshurl && hosted.sshurl({ noCommittish: true })
               // no fallthrough if we can't fall through or have https auth
               if (!ssh || hosted.auth)
      diff --git a/deps/npm/node_modules/pacote/package.json b/deps/npm/node_modules/pacote/package.json
      index 7472c6eeab0cc8..437bb8f79e1d88 100644
      --- a/deps/npm/node_modules/pacote/package.json
      +++ b/deps/npm/node_modules/pacote/package.json
      @@ -1,6 +1,6 @@
       {
         "name": "pacote",
      -  "version": "11.3.4",
      +  "version": "11.3.5",
         "description": "JavaScript package downloader",
         "author": "Isaac Z. Schlueter  (https://izs.me)",
         "bin": {
      @@ -33,7 +33,7 @@
           "git"
         ],
         "dependencies": {
      -    "@npmcli/git": "^2.0.1",
      +    "@npmcli/git": "^2.1.0",
           "@npmcli/installed-package-contents": "^1.0.6",
           "@npmcli/promise-spawn": "^1.2.0",
           "@npmcli/run-script": "^1.8.2",
      diff --git a/deps/npm/node_modules/socks/typings/common/receivebuffer.d.ts b/deps/npm/node_modules/socks/typings/common/receivebuffer.d.ts
      new file mode 100644
      index 00000000000000..756e98b5893ed8
      --- /dev/null
      +++ b/deps/npm/node_modules/socks/typings/common/receivebuffer.d.ts
      @@ -0,0 +1,12 @@
      +/// 
      +declare class ReceiveBuffer {
      +    private buffer;
      +    private offset;
      +    private originalSize;
      +    constructor(size?: number);
      +    get length(): number;
      +    append(data: Buffer): number;
      +    peek(length: number): Buffer;
      +    get(length: number): Buffer;
      +}
      +export { ReceiveBuffer };
      diff --git a/deps/npm/package.json b/deps/npm/package.json
      index 73b03991026e1c..f0b9642905cede 100644
      --- a/deps/npm/package.json
      +++ b/deps/npm/package.json
      @@ -1,5 +1,5 @@
       {
      -  "version": "7.19.1",
      +  "version": "7.20.0",
         "name": "npm",
         "description": "a package manager for JavaScript",
         "workspaces": [
      @@ -53,7 +53,7 @@
           "./package.json": "./package.json"
         },
         "dependencies": {
      -    "@npmcli/arborist": "^2.6.4",
      +    "@npmcli/arborist": "^2.7.1",
           "@npmcli/ci-detect": "^1.2.0",
           "@npmcli/config": "^2.2.0",
           "@npmcli/package-json": "^1.0.1",
      @@ -88,7 +88,7 @@
           "libnpmsearch": "^3.1.1",
           "libnpmteam": "^2.0.3",
           "libnpmversion": "^1.2.1",
      -    "make-fetch-happen": "^9.0.3",
      +    "make-fetch-happen": "^9.0.4",
           "minipass": "^3.1.3",
           "minipass-pipeline": "^1.2.4",
           "mkdirp": "^1.0.4",
      @@ -104,7 +104,7 @@
           "npm-user-validate": "^1.0.1",
           "npmlog": "~4.1.2",
           "opener": "^1.5.2",
      -    "pacote": "^11.3.3",
      +    "pacote": "^11.3.5",
           "parse-conflict-json": "^1.1.1",
           "qrcode-terminal": "^0.12.0",
           "read": "~1.0.7",
      @@ -193,7 +193,7 @@
           "write-file-atomic"
         ],
         "devDependencies": {
      -    "eslint": "^7.26.0",
      +    "eslint": "^7.30.0",
           "eslint-plugin-import": "^2.23.4",
           "eslint-plugin-node": "^11.1.0",
           "eslint-plugin-promise": "^5.1.0",
      diff --git a/deps/npm/tap-snapshots/smoke-tests/index.js.test.cjs b/deps/npm/tap-snapshots/smoke-tests/index.js.test.cjs
      index 89c0cb20b5e367..0a79e38cdfa031 100644
      --- a/deps/npm/tap-snapshots/smoke-tests/index.js.test.cjs
      +++ b/deps/npm/tap-snapshots/smoke-tests/index.js.test.cjs
      @@ -26,10 +26,10 @@ All commands:
           edit, exec, explain, explore, find-dupes, fund, get, help,
           hook, init, install, install-ci-test, install-test, link,
           ll, login, logout, ls, org, outdated, owner, pack, ping,
      -    prefix, profile, prune, publish, rebuild, repo, restart,
      -    root, run-script, search, set, set-script, shrinkwrap, star,
      -    stars, start, stop, team, test, token, uninstall, unpublish,
      -    unstar, update, version, view, whoami
      +    pkg, prefix, profile, prune, publish, rebuild, repo,
      +    restart, root, run-script, search, set, set-script,
      +    shrinkwrap, star, stars, start, stop, team, test, token,
      +    uninstall, unpublish, unstar, update, version, view, whoami
       
       Specify configs in the ini-formatted file:
           {CWD}/smoke-tests/tap-testdir-index/.npmrc
      @@ -482,6 +482,89 @@ abbrev     1.0.4   1.1.1   1.1.1  node_modules/abbrev  project
       
       `
       
      +exports[`smoke-tests/index.js TAP npm pkg > should have expected npm pkg delete modified package.json result 1`] = `
      +{
      +  "name": "project",
      +  "version": "1.0.0",
      +  "description": "",
      +  "main": "index.js",
      +  "scripts": {
      +    "test": "echo /"Error: no test specified/" && exit 1",
      +    "hello": "echo Hello"
      +  },
      +  "keywords": [],
      +  "author": "",
      +  "license": "ISC",
      +  "dependencies": {
      +    "abbrev": "^1.0.4"
      +  }
      +}
      +
      +`
      +
      +exports[`smoke-tests/index.js TAP npm pkg > should have expected npm pkg set modified package.json result 1`] = `
      +{
      +  "name": "project",
      +  "version": "1.0.0",
      +  "description": "",
      +  "main": "index.js",
      +  "scripts": {
      +    "test": "echo /"Error: no test specified/" && exit 1",
      +    "hello": "echo Hello"
      +  },
      +  "keywords": [],
      +  "author": "",
      +  "license": "ISC",
      +  "dependencies": {
      +    "abbrev": "^1.0.4"
      +  },
      +  "tap": {
      +    "test-env": [
      +      "LC_ALL=sk"
      +    ]
      +  }
      +}
      +
      +`
      +
      +exports[`smoke-tests/index.js TAP npm pkg > should have expected pkg delete output 1`] = `
      +
      +`
      +
      +exports[`smoke-tests/index.js TAP npm pkg > should have expected pkg get output 1`] = `
      +"ISC"
      +
      +`
      +
      +exports[`smoke-tests/index.js TAP npm pkg > should have expected pkg set output 1`] = `
      +
      +`
      +
      +exports[`smoke-tests/index.js TAP npm pkg > should print package.json contents 1`] = `
      +{
      +  "name": "project",
      +  "version": "1.0.0",
      +  "description": "",
      +  "ma",
      +  "scripts": {
      +    "test": "echo /"Error: no test specified/" && exit 1",
      +    "hello": "echo Hello"
      +  },
      +  "keywords": [],
      +  "author": "",
      +  "license": "ISC",
      +  "dependencies": {
      +    "abbrev": "^1.0.4"
      +  },
      +  "tap": {
      +    "test-env": [
      +      "LC_ALL=sk"
      +    ]
      +  }
      +}
      +
      +`
      +
       exports[`smoke-tests/index.js TAP npm prefix > should have expected prefix output 1`] = `
       {CWD}/smoke-tests/tap-testdir-index/project
       
      diff --git a/deps/npm/tap-snapshots/test/lib/config.js.test.cjs b/deps/npm/tap-snapshots/test/lib/config.js.test.cjs
      index 84418ec2e816d2..a094bd32d56dfc 100644
      --- a/deps/npm/tap-snapshots/test/lib/config.js.test.cjs
      +++ b/deps/npm/tap-snapshots/test/lib/config.js.test.cjs
      @@ -5,7 +5,7 @@
        * Make sure to inspect the output below.  Do not ignore changes!
        */
       'use strict'
      -exports[`test/lib/config.js TAP config edit --global > should write global config file 1`] = `
      +exports[`test/lib/config.js TAP config edit --location=global > should write global config file 1`] = `
       ;;;;
       ; npm globalconfig file: /etc/npmrc
       ; this is a simple ini-formatted file
      @@ -92,8 +92,8 @@ cat = true
       chai = true 
       dog = true 
       editor = "vi" 
      -global = false 
       json = false 
      +location = "user"
       long = false 
       
       ; node bin location = /path/to/node
      @@ -116,8 +116,8 @@ cat = true
       chai = true 
       dog = true 
       editor = "vi" 
      -global = false 
       json = false 
      +location = "user"
       long = true
       `
       
      @@ -128,8 +128,8 @@ cat = true
       chai = true 
       dog = true 
       editor = "vi" 
      -global = false 
       json = false 
      +location = "user"
       long = false 
       
       ; node bin location = /path/to/node
      @@ -145,9 +145,9 @@ cat = true
       chai = true 
       dog = true 
       editor = "vi" 
      -global = false 
       init.author.name = "Bar" 
       json = false 
      +location = "user"
       long = false 
       
       ; "user" config from ~/.npmrc
      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 3575783a644b2f..8cf2e2837e2954 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
      @@ -84,7 +84,7 @@ Usage:
       npm bugs []
       
       Options:
      -[--browser|--browser ] [--registry ]
      +[--no-browser|--browser ] [--registry ]
       
       alias: issues
       
      @@ -120,7 +120,7 @@ Usage:
       npm ci
       
       Options:
      -[--ignore-scripts] [--script-shell ]
      +[--no-audit] [--ignore-scripts] [--script-shell ]
       
       aliases: clean-install, ic, install-clean, isntall-clean
       
      @@ -151,7 +151,8 @@ npm config list [--json]
       npm config edit
       
       Options:
      -[--json] [-g|--global] [--editor ] [-l|--long]
      +[--json] [-g|--global] [--editor ] [-L|--location ]
      +[-l|--long]
       
       alias: c
       
      @@ -167,9 +168,9 @@ Usage:
       npm dedupe
       
       Options:
      -[--global-style] [--legacy-bundling] [--strict-peer-deps] [--package-lock]
      +[--global-style] [--legacy-bundling] [--strict-peer-deps] [--no-package-lock]
       [--omit  [--omit  ...]] [--ignore-scripts]
      -[--audit] [--bin-links] [--fund] [--dry-run]
      +[--no-audit] [--no-bin-links] [--no-fund] [--dry-run]
       [-w|--workspace  [-w|--workspace  ...]]
       [-ws|--workspaces]
       
      @@ -239,7 +240,7 @@ Usage:
       npm docs [ [ ...]]
       
       Options:
      -[--browser|--browser ] [--registry ]
      +[--no-browser|--browser ] [--registry ]
       [-w|--workspace  [-w|--workspace  ...]]
       [-ws|--workspaces]
       
      @@ -337,9 +338,9 @@ Usage:
       npm find-dupes
       
       Options:
      -[--global-style] [--legacy-bundling] [--strict-peer-deps] [--package-lock]
      +[--global-style] [--legacy-bundling] [--strict-peer-deps] [--no-package-lock]
       [--omit  [--omit  ...]] [--ignore-scripts]
      -[--audit] [--bin-links] [--fund]
      +[--no-audit] [--no-bin-links] [--no-fund]
       [-w|--workspace  [-w|--workspace  ...]]
       [-ws|--workspaces]
       
      @@ -355,7 +356,7 @@ Usage:
       npm fund [[<@scope>/]]
       
       Options:
      -[--json] [--browser|--browser ] [--unicode]
      +[--json] [--no-browser|--browser ] [--unicode]
       [-w|--workspace  [-w|--workspace  ...]]
       [--which ]
       
      @@ -446,9 +447,9 @@ npm install /
       Options:
       [-S|--save|--no-save|--save-prod|--save-dev|--save-optional|--save-peer]
       [-E|--save-exact] [-g|--global] [--global-style] [--legacy-bundling]
      -[--strict-peer-deps] [--package-lock]
      +[--strict-peer-deps] [--no-package-lock]
       [--omit  [--omit  ...]] [--ignore-scripts]
      -[--audit] [--bin-links] [--fund] [--dry-run]
      +[--no-audit] [--no-bin-links] [--no-fund] [--dry-run]
       [-w|--workspace  [-w|--workspace  ...]]
       [-ws|--workspaces]
       
      @@ -466,7 +467,7 @@ Usage:
       npm install-ci-test
       
       Options:
      -[--ignore-scripts] [--script-shell ]
      +[--no-audit] [--ignore-scripts] [--script-shell ]
       
       alias: cit
       
      @@ -493,9 +494,9 @@ npm install-test /
       Options:
       [-S|--save|--no-save|--save-prod|--save-dev|--save-optional|--save-peer]
       [-E|--save-exact] [-g|--global] [--global-style] [--legacy-bundling]
      -[--strict-peer-deps] [--package-lock]
      +[--strict-peer-deps] [--no-package-lock]
       [--omit  [--omit  ...]] [--ignore-scripts]
      -[--audit] [--bin-links] [--fund] [--dry-run]
      +[--no-audit] [--no-bin-links] [--no-fund] [--dry-run]
       [-w|--workspace  [-w|--workspace  ...]]
       [-ws|--workspaces]
       
      @@ -516,9 +517,9 @@ npm link [<@scope>/][@]
       Options:
       [-S|--save|--no-save|--save-prod|--save-dev|--save-optional|--save-peer]
       [-E|--save-exact] [-g|--global] [--global-style] [--legacy-bundling]
      -[--strict-peer-deps] [--package-lock]
      +[--strict-peer-deps] [--no-package-lock]
       [--omit  [--omit  ...]] [--ignore-scripts]
      -[--audit] [--bin-links] [--fund] [--dry-run]
      +[--no-audit] [--no-bin-links] [--no-fund] [--dry-run]
       [-w|--workspace  [-w|--workspace  ...]]
       [-ws|--workspaces]
       
      @@ -678,6 +679,24 @@ Options:
       Run "npm help ping" for more info
       `
       
      +exports[`test/lib/load-all-commands.js TAP load each command pkg > must match snapshot 1`] = `
      +npm pkg
      +
      +Manages your package.json
      +
      +Usage:
      +npm pkg set = [= ...]
      +npm pkg get [ [ ...]]
      +npm pkg delete  [ ...]
      +
      +Options:
      +[-f|--force] [--json]
      +[-w|--workspace  [-w|--workspace  ...]]
      +[-ws|--workspaces]
      +
      +Run "npm help pkg" for more info
      +`
      +
       exports[`test/lib/load-all-commands.js TAP load each command prefix > must match snapshot 1`] = `
       npm prefix
       
      @@ -750,7 +769,7 @@ Usage:
       npm rebuild [[<@scope>/][@] ...]
       
       Options:
      -[-g|--global] [--bin-links] [--ignore-scripts]
      +[-g|--global] [--no-bin-links] [--ignore-scripts]
       [-w|--workspace  [-w|--workspace  ...]]
       [-ws|--workspaces]
       
      @@ -768,7 +787,7 @@ Usage:
       npm repo [ [ ...]]
       
       Options:
      -[--browser|--browser ]
      +[--no-browser|--browser ]
       [-w|--workspace  [-w|--workspace  ...]]
       [-ws|--workspaces]
       
      @@ -830,7 +849,7 @@ Usage:
       npm search [search terms ...]
       
       Options:
      -[-l|--long] [--json] [--color|--color ] [-p|--parseable]
      +[-l|--long] [--json] [--color|--no-color|--color always] [-p|--parseable]
       [--no-description] [--searchopts ] [--searchexclude ]
       [--registry ] [--prefer-online] [--prefer-offline] [--offline]
       
      @@ -1041,8 +1060,8 @@ npm update [...]
       
       Options:
       [-g|--global] [--global-style] [--legacy-bundling] [--strict-peer-deps]
      -[--package-lock] [--omit  [--omit  ...]]
      -[--ignore-scripts] [--audit] [--bin-links] [--fund] [--dry-run]
      +[--no-package-lock] [--omit  [--omit  ...]]
      +[--ignore-scripts] [--no-audit] [--no-bin-links] [--no-fund] [--dry-run]
       [-w|--workspace  [-w|--workspace  ...]]
       [-ws|--workspaces]
       
      @@ -1060,7 +1079,7 @@ Usage:
       npm version [ | major | minor | patch | premajor | preminor | prepatch | prerelease | from-git]
       
       Options:
      -[--allow-same-version] [--commit-hooks] [--git-tag-version] [--json]
      +[--allow-same-version] [--no-commit-hooks] [--no-git-tag-version] [--json]
       [--preid prerelease-id] [--sign-git-tag]
       [-w|--workspace  [-w|--workspace  ...]]
       [-ws|--workspaces]
      diff --git a/deps/npm/tap-snapshots/test/lib/utils/cmd-list.js.test.cjs b/deps/npm/tap-snapshots/test/lib/utils/cmd-list.js.test.cjs
      index 832f8560125a3d..971580792048b4 100644
      --- a/deps/npm/tap-snapshots/test/lib/utils/cmd-list.js.test.cjs
      +++ b/deps/npm/tap-snapshots/test/lib/utils/cmd-list.js.test.cjs
      @@ -158,6 +158,7 @@ Object {
           "diff",
           "dist-tag",
           "ping",
      +    "pkg",
           "test",
           "stop",
           "start",
      diff --git a/deps/npm/tap-snapshots/test/lib/utils/config/definitions.js.test.cjs b/deps/npm/tap-snapshots/test/lib/utils/config/definitions.js.test.cjs
      index 12df9ec89f6f72..01b137b8af54ab 100644
      --- a/deps/npm/tap-snapshots/test/lib/utils/config/definitions.js.test.cjs
      +++ b/deps/npm/tap-snapshots/test/lib/utils/config/definitions.js.test.cjs
      @@ -81,6 +81,7 @@ Array [
         "legacy-peer-deps",
         "link",
         "local-address",
      +  "location",
         "loglevel",
         "logs-max",
         "long",
      @@ -218,9 +219,10 @@ exports[`test/lib/utils/config/definitions.js TAP > config description for audit
       * Default: true
       * Type: Boolean
       
      -When "true" submit audit reports alongside \`npm install\` runs to the default
      -registry and all registries configured for scopes. See the documentation for
      -[\`npm audit\`](/commands/npm-audit) for details on what is submitted.
      +When "true" submit audit reports alongside the current npm command to the
      +default registry and all registries configured for scopes. See the
      +documentation for [\`npm audit\`](/commands/npm-audit) for details on what is
      +submitted.
       `
       
       exports[`test/lib/utils/config/definitions.js TAP > config description for audit-level 1`] = `
      @@ -648,6 +650,7 @@ mistakes, unnecessary performance degradation, and malicious input.
       * Allow unpublishing all versions of a published package.
       * Allow conflicting peerDependencies to be installed in the root project.
       * Implicitly set \`--yes\` during \`npm init\`.
      +* Allow clobbering existing values in \`npm pkg\`
       
       If you don't have a clear idea of what you want to do, it is strongly
       recommended that you do not use this option!
      @@ -949,6 +952,9 @@ exports[`test/lib/utils/config/definitions.js TAP > config description for json
       
       Whether or not to output JSON data, rather than the normal output.
       
      +* In \`npm pkg set\` it enables parsing set values with JSON.parse() before
      +  saving them to your \`package.json\`.
      +
       Not supported by all npm commands.
       `
       
      @@ -1019,6 +1025,16 @@ The IP address of the local interface to use when making connections to the
       npm registry. Must be IPv4 in versions of Node prior to 0.12.
       `
       
      +exports[`test/lib/utils/config/definitions.js TAP > config description for location 1`] = `
      +#### \`location\`
      +
      +* Default: "user" unless \`--global\` is passed, which will also set this value
      +  to "global"
      +* Type: "global", "user", or "project"
      +
      +When passed to \`npm config\` this refers to which config file to use.
      +`
      +
       exports[`test/lib/utils/config/definitions.js TAP > config description for loglevel 1`] = `
       #### \`loglevel\`
       
      diff --git a/deps/npm/tap-snapshots/test/lib/utils/config/describe-all.js.test.cjs b/deps/npm/tap-snapshots/test/lib/utils/config/describe-all.js.test.cjs
      index daa071b642e944..8487b45174cc39 100644
      --- a/deps/npm/tap-snapshots/test/lib/utils/config/describe-all.js.test.cjs
      +++ b/deps/npm/tap-snapshots/test/lib/utils/config/describe-all.js.test.cjs
      @@ -49,9 +49,10 @@ to the same value as the current version.
       * Default: true
       * Type: Boolean
       
      -When "true" submit audit reports alongside \`npm install\` runs to the default
      -registry and all registries configured for scopes. See the documentation for
      -[\`npm audit\`](/commands/npm-audit) for details on what is submitted.
      +When "true" submit audit reports alongside the current npm command to the
      +default registry and all registries configured for scopes. See the
      +documentation for [\`npm audit\`](/commands/npm-audit) for details on what is
      +submitted.
       
       #### \`audit-level\`
       
      @@ -374,6 +375,7 @@ mistakes, unnecessary performance degradation, and malicious input.
       * Allow unpublishing all versions of a published package.
       * Allow conflicting peerDependencies to be installed in the root project.
       * Implicitly set \`--yes\` during \`npm init\`.
      +* Allow clobbering existing values in \`npm pkg\`
       
       If you don't have a clear idea of what you want to do, it is strongly
       recommended that you do not use this option!
      @@ -573,6 +575,9 @@ number, if not already set in package.json.
       
       Whether or not to output JSON data, rather than the normal output.
       
      +* In \`npm pkg set\` it enables parsing set values with JSON.parse() before
      +  saving them to your \`package.json\`.
      +
       Not supported by all npm commands.
       
       #### \`key\`
      @@ -632,6 +637,14 @@ Used with \`npm ls\`, limiting output to only those packages that are linked.
       The IP address of the local interface to use when making connections to the
       npm registry. Must be IPv4 in versions of Node prior to 0.12.
       
      +#### \`location\`
      +
      +* Default: "user" unless \`--global\` is passed, which will also set this value
      +  to "global"
      +* Type: "global", "user", or "project"
      +
      +When passed to \`npm config\` this refers to which config file to use.
      +
       #### \`loglevel\`
       
       * Default: "notice"
      diff --git a/deps/npm/tap-snapshots/test/lib/utils/config/index.js.test.cjs b/deps/npm/tap-snapshots/test/lib/utils/config/index.js.test.cjs
      index 1e5ca232452e02..f1cba9264ee2ff 100644
      --- a/deps/npm/tap-snapshots/test/lib/utils/config/index.js.test.cjs
      +++ b/deps/npm/tap-snapshots/test/lib/utils/config/index.js.test.cjs
      @@ -64,6 +64,9 @@ Object {
         "l": Array [
           "--long",
         ],
      +  "L": Array [
      +    "--location",
      +  ],
         "local": Array [
           "--no-global",
         ],
      diff --git a/deps/npm/tap-snapshots/test/lib/utils/error-message.js.test.cjs b/deps/npm/tap-snapshots/test/lib/utils/error-message.js.test.cjs
      index 7b02dbd9aaa650..8adb33c395df75 100644
      --- a/deps/npm/tap-snapshots/test/lib/utils/error-message.js.test.cjs
      +++ b/deps/npm/tap-snapshots/test/lib/utils/error-message.js.test.cjs
      @@ -1289,6 +1289,29 @@ Object {
       }
       `
       
      +exports[`test/lib/utils/error-message.js TAP just simple messages > must match snapshot 23`] = `
      +Object {
      +  "detail": Array [
      +    Array [
      +      "network",
      +      String(
      +        This is a problem related to network connectivity.
      +        In most cases you are behind a proxy or have bad network settings.
      +
      +        If you are behind a proxy, please make sure that the
      +        'proxy' config is set properly.  See: 'npm help config'
      +      ),
      +    ],
      +  ],
      +  "summary": Array [
      +    Array [
      +      "network",
      +      "foo",
      +    ],
      +  ],
      +}
      +`
      +
       exports[`test/lib/utils/error-message.js TAP just simple messages > must match snapshot 3`] = `
       Object {
         "detail": Array [
      diff --git a/deps/npm/tap-snapshots/test/lib/utils/exit-handler.js.test.cjs b/deps/npm/tap-snapshots/test/lib/utils/exit-handler.js.test.cjs
      index 8cea8ee17e5ead..eb383c104a6744 100644
      --- a/deps/npm/tap-snapshots/test/lib/utils/exit-handler.js.test.cjs
      +++ b/deps/npm/tap-snapshots/test/lib/utils/exit-handler.js.test.cjs
      @@ -6,15 +6,15 @@
        */
       'use strict'
       exports[`test/lib/utils/exit-handler.js TAP handles unknown error > should have expected log contents for unknown error 1`] = `
      -0 verbose stack Error: ERROR
      -1 verbose cwd {CWD}
      -2 verbose Foo 1.0.0
      -3 verbose argv "/node" "{CWD}/test/lib/utils/exit-handler.js"
      -4 verbose node v1.0.0
      -5 verbose npm  v1.0.0
      -6 error foo code ERROR
      -7 error foo ERR ERROR
      -8 error foo ERR ERROR
      -9 verbose exit 1
      +24 verbose stack Error: ERROR
      +25 verbose cwd {CWD}
      +26 verbose Foo 1.0.0
      +27 verbose argv "/node" "{CWD}/test/lib/utils/exit-handler.js"
      +28 verbose node v1.0.0
      +29 verbose npm  v1.0.0
      +30 error code ERROR
      +31 error ERR ERROR
      +32 error ERR ERROR
      +33 verbose exit 1
       
       `
      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 3987f6a732da55..17df1aa1f58ede 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
      @@ -26,10 +26,10 @@ All commands:
           edit, exec, explain, explore, find-dupes, fund, get, help,
           hook, init, install, install-ci-test, install-test, link,
           ll, login, logout, ls, org, outdated, owner, pack, ping,
      -    prefix, profile, prune, publish, rebuild, repo, restart,
      -    root, run-script, search, set, set-script, shrinkwrap, star,
      -    stars, start, stop, team, test, token, uninstall, unpublish,
      -    unstar, update, version, view, whoami
      +    pkg, prefix, profile, prune, publish, rebuild, repo,
      +    restart, root, run-script, search, set, set-script,
      +    shrinkwrap, star, stars, start, stop, team, test, token,
      +    uninstall, unpublish, unstar, update, version, view, whoami
       
       Specify configs in the ini-formatted file:
           /some/config/file/.npmrc
      @@ -62,10 +62,10 @@ All commands:
           edit, exec, explain, explore, find-dupes, fund, get, help,
           hook, init, install, install-ci-test, install-test, link,
           ll, login, logout, ls, org, outdated, owner, pack, ping,
      -    prefix, profile, prune, publish, rebuild, repo, restart,
      -    root, run-script, search, set, set-script, shrinkwrap, star,
      -    stars, start, stop, team, test, token, uninstall, unpublish,
      -    unstar, update, version, view, whoami
      +    pkg, prefix, profile, prune, publish, rebuild, repo,
      +    restart, root, run-script, search, set, set-script,
      +    shrinkwrap, star, stars, start, stop, team, test, token,
      +    uninstall, unpublish, unstar, update, version, view, whoami
       
       Specify configs in the ini-formatted file:
           /some/config/file/.npmrc
      @@ -98,10 +98,10 @@ All commands:
           edit, exec, explain, explore, find-dupes, fund, get, help,
           hook, init, install, install-ci-test, install-test, link,
           ll, login, logout, ls, org, outdated, owner, pack, ping,
      -    prefix, profile, prune, publish, rebuild, repo, restart,
      -    root, run-script, search, set, set-script, shrinkwrap, star,
      -    stars, start, stop, team, test, token, uninstall, unpublish,
      -    unstar, update, version, view, whoami
      +    pkg, prefix, profile, prune, publish, rebuild, repo,
      +    restart, root, run-script, search, set, set-script,
      +    shrinkwrap, star, stars, start, stop, team, test, token,
      +    uninstall, unpublish, unstar, update, version, view, whoami
       
       Specify configs in the ini-formatted file:
           /some/config/file/.npmrc
      @@ -134,10 +134,10 @@ All commands:
           edit, exec, explain, explore, find-dupes, fund, get, help,
           hook, init, install, install-ci-test, install-test, link,
           ll, login, logout, ls, org, outdated, owner, pack, ping,
      -    prefix, profile, prune, publish, rebuild, repo, restart,
      -    root, run-script, search, set, set-script, shrinkwrap, star,
      -    stars, start, stop, team, test, token, uninstall, unpublish,
      -    unstar, update, version, view, whoami
      +    pkg, prefix, profile, prune, publish, rebuild, repo,
      +    restart, root, run-script, search, set, set-script,
      +    shrinkwrap, star, stars, start, stop, team, test, token,
      +    uninstall, unpublish, unstar, update, version, view, whoami
       
       Specify configs in the ini-formatted file:
           /some/config/file/.npmrc
      @@ -235,7 +235,7 @@ All commands:
                           npm bugs []
                           
                           Options:
      -                    [--browser|--browser ] [--registry ]
      +                    [--no-browser|--browser ] [--registry ]
                           
                           alias: issues
                           
      @@ -267,7 +267,7 @@ All commands:
                           npm ci
                           
                           Options:
      -                    [--ignore-scripts] [--script-shell ]
      +                    [--no-audit] [--ignore-scripts] [--script-shell ]
                           
                           aliases: clean-install, ic, install-clean, isntall-clean
                           
      @@ -294,7 +294,8 @@ All commands:
                           npm config edit
                           
                           Options:
      -                    [--json] [-g|--global] [--editor ] [-l|--long]
      +                    [--json] [-g|--global] [--editor ] [-L|--location ]
      +                    [-l|--long]
                           
                           alias: c
                           
      @@ -308,9 +309,9 @@ All commands:
                           npm dedupe
                           
                           Options:
      -                    [--global-style] [--legacy-bundling] [--strict-peer-deps] [--package-lock]
      +                    [--global-style] [--legacy-bundling] [--strict-peer-deps] [--no-package-lock]
                           [--omit  [--omit  ...]] [--ignore-scripts]
      -                    [--audit] [--bin-links] [--fund] [--dry-run]
      +                    [--no-audit] [--no-bin-links] [--no-fund] [--dry-run]
                           [-w|--workspace  [-w|--workspace  ...]]
                           [-ws|--workspaces]
                           
      @@ -372,7 +373,7 @@ All commands:
                           npm docs [ [ ...]]
                           
                           Options:
      -                    [--browser|--browser ] [--registry ]
      +                    [--no-browser|--browser ] [--registry ]
                           [-w|--workspace  [-w|--workspace  ...]]
                           [-ws|--workspaces]
                           
      @@ -458,9 +459,9 @@ All commands:
                           npm find-dupes
                           
                           Options:
      -                    [--global-style] [--legacy-bundling] [--strict-peer-deps] [--package-lock]
      +                    [--global-style] [--legacy-bundling] [--strict-peer-deps] [--no-package-lock]
                           [--omit  [--omit  ...]] [--ignore-scripts]
      -                    [--audit] [--bin-links] [--fund]
      +                    [--no-audit] [--no-bin-links] [--no-fund]
                           [-w|--workspace  [-w|--workspace  ...]]
                           [-ws|--workspaces]
                           
      @@ -474,7 +475,7 @@ All commands:
                           npm fund [[<@scope>/]]
                           
                           Options:
      -                    [--json] [--browser|--browser ] [--unicode]
      +                    [--json] [--no-browser|--browser ] [--unicode]
                           [-w|--workspace  [-w|--workspace  ...]]
                           [--which ]
                           
      @@ -555,9 +556,9 @@ All commands:
                           Options:
                           [-S|--save|--no-save|--save-prod|--save-dev|--save-optional|--save-peer]
                           [-E|--save-exact] [-g|--global] [--global-style] [--legacy-bundling]
      -                    [--strict-peer-deps] [--package-lock]
      +                    [--strict-peer-deps] [--no-package-lock]
                           [--omit  [--omit  ...]] [--ignore-scripts]
      -                    [--audit] [--bin-links] [--fund] [--dry-run]
      +                    [--no-audit] [--no-bin-links] [--no-fund] [--dry-run]
                           [-w|--workspace  [-w|--workspace  ...]]
                           [-ws|--workspaces]
                           
      @@ -573,7 +574,7 @@ All commands:
                           npm install-ci-test
                           
                           Options:
      -                    [--ignore-scripts] [--script-shell ]
      +                    [--no-audit] [--ignore-scripts] [--script-shell ]
                           
                           alias: cit
                           
      @@ -598,9 +599,9 @@ All commands:
                           Options:
                           [-S|--save|--no-save|--save-prod|--save-dev|--save-optional|--save-peer]
                           [-E|--save-exact] [-g|--global] [--global-style] [--legacy-bundling]
      -                    [--strict-peer-deps] [--package-lock]
      +                    [--strict-peer-deps] [--no-package-lock]
                           [--omit  [--omit  ...]] [--ignore-scripts]
      -                    [--audit] [--bin-links] [--fund] [--dry-run]
      +                    [--no-audit] [--no-bin-links] [--no-fund] [--dry-run]
                           [-w|--workspace  [-w|--workspace  ...]]
                           [-ws|--workspaces]
                           
      @@ -619,9 +620,9 @@ All commands:
                           Options:
                           [-S|--save|--no-save|--save-prod|--save-dev|--save-optional|--save-peer]
                           [-E|--save-exact] [-g|--global] [--global-style] [--legacy-bundling]
      -                    [--strict-peer-deps] [--package-lock]
      +                    [--strict-peer-deps] [--no-package-lock]
                           [--omit  [--omit  ...]] [--ignore-scripts]
      -                    [--audit] [--bin-links] [--fund] [--dry-run]
      +                    [--no-audit] [--no-bin-links] [--no-fund] [--dry-run]
                           [-w|--workspace  [-w|--workspace  ...]]
                           [-ws|--workspaces]
                           
      @@ -762,6 +763,22 @@ All commands:
                           
                           Run "npm help ping" for more info
       
      +    pkg             npm pkg
      +
      +                    Manages your package.json
      +
      +                    Usage:
      +                    npm pkg set = [= ...]
      +                    npm pkg get [ [ ...]]
      +                    npm pkg delete  [ ...]
      +
      +                    Options:
      +                    [-f|--force] [--json]
      +                    [-w|--workspace  [-w|--workspace  ...]]
      +                    [-ws|--workspaces]
      +
      +                    Run "npm help pkg" for more info
      +
           prefix          npm prefix
                           
                           Display prefix
      @@ -825,7 +842,7 @@ All commands:
                           npm rebuild [[<@scope>/][@] ...]
                           
                           Options:
      -                    [-g|--global] [--bin-links] [--ignore-scripts]
      +                    [-g|--global] [--no-bin-links] [--ignore-scripts]
                           [-w|--workspace  [-w|--workspace  ...]]
                           [-ws|--workspaces]
                           
      @@ -841,7 +858,7 @@ All commands:
                           npm repo [ [ ...]]
                           
                           Options:
      -                    [--browser|--browser ]
      +                    [--no-browser|--browser ]
                           [-w|--workspace  [-w|--workspace  ...]]
                           [-ws|--workspaces]
                           
      @@ -895,7 +912,7 @@ All commands:
                           npm search [search terms ...]
                           
                           Options:
      -                    [-l|--long] [--json] [--color|--color ] [-p|--parseable]
      +                    [-l|--long] [--json] [--color|--no-color|--color always] [-p|--parseable]
                           [--no-description] [--searchopts ] [--searchexclude ]
                           [--registry ] [--prefer-online] [--prefer-offline] [--offline]
                           
      @@ -1078,8 +1095,8 @@ All commands:
                           
                           Options:
                           [-g|--global] [--global-style] [--legacy-bundling] [--strict-peer-deps]
      -                    [--package-lock] [--omit  [--omit  ...]]
      -                    [--ignore-scripts] [--audit] [--bin-links] [--fund] [--dry-run]
      +                    [--no-package-lock] [--omit  [--omit  ...]]
      +                    [--ignore-scripts] [--no-audit] [--no-bin-links] [--no-fund] [--dry-run]
                           [-w|--workspace  [-w|--workspace  ...]]
                           [-ws|--workspaces]
                           
      @@ -1095,7 +1112,7 @@ All commands:
                           npm version [ | major | minor | patch | premajor | preminor | prepatch | prerelease | from-git]
                           
                           Options:
      -                    [--allow-same-version] [--commit-hooks] [--git-tag-version] [--json]
      +                    [--allow-same-version] [--no-commit-hooks] [--no-git-tag-version] [--json]
                           [--preid prerelease-id] [--sign-git-tag]
                           [-w|--workspace  [-w|--workspace  ...]]
                           [-ws|--workspaces]
      diff --git a/deps/npm/tap-snapshots/test/lib/utils/update-notifier.js.test.cjs b/deps/npm/tap-snapshots/test/lib/utils/update-notifier.js.test.cjs
      index 91228650d47de7..157390997d7936 100644
      --- a/deps/npm/tap-snapshots/test/lib/utils/update-notifier.js.test.cjs
      +++ b/deps/npm/tap-snapshots/test/lib/utils/update-notifier.js.test.cjs
      @@ -6,11 +6,11 @@
        */
       'use strict'
       exports[`test/lib/utils/update-notifier.js TAP notification situations major to current > color 1`] = `
      -
      -New major version of npm available! 122.420.69 -> 123.420.69
      -Changelog: https://github.com/npm/cli/releases/tag/v123.420.69
      -Run npm install -g npm@123.420.69 to update!
      -
      +
      +New major version of npm available! 122.420.69 -> 123.420.69
      +Changelog: https://github.com/npm/cli/releases/tag/v123.420.69
      +Run npm install -g npm@123.420.69 to update!
      +
       `
       
       exports[`test/lib/utils/update-notifier.js TAP notification situations major to current > no color 1`] = `
      @@ -22,11 +22,11 @@ Run \`npm install -g npm@123.420.69\` to update!
       `
       
       exports[`test/lib/utils/update-notifier.js TAP notification situations minor to current > color 1`] = `
      -
      -New minor version of npm available! 123.419.69 -> 123.420.69
      -Changelog: https://github.com/npm/cli/releases/tag/v123.420.69
      -Run npm install -g npm@123.420.69 to update!
      -
      +
      +New minor version of npm available! 123.419.69 -> 123.420.69
      +Changelog: https://github.com/npm/cli/releases/tag/v123.420.69
      +Run npm install -g npm@123.420.69 to update!
      +
       `
       
       exports[`test/lib/utils/update-notifier.js TAP notification situations minor to current > no color 1`] = `
      @@ -38,11 +38,11 @@ Run \`npm install -g npm@123.420.69\` to update!
       `
       
       exports[`test/lib/utils/update-notifier.js TAP notification situations minor to next version > color 1`] = `
      -
      -New minor version of npm available! 123.420.70 -> 123.421.70
      -Changelog: https://github.com/npm/cli/releases/tag/v123.421.70
      -Run npm install -g npm@123.421.70 to update!
      -
      +
      +New minor version of npm available! 123.420.70 -> 123.421.70
      +Changelog: https://github.com/npm/cli/releases/tag/v123.421.70
      +Run npm install -g npm@123.421.70 to update!
      +
       `
       
       exports[`test/lib/utils/update-notifier.js TAP notification situations minor to next version > no color 1`] = `
      @@ -54,11 +54,11 @@ Run \`npm install -g npm@123.421.70\` to update!
       `
       
       exports[`test/lib/utils/update-notifier.js TAP notification situations new beta available > color 1`] = `
      -
      -New prerelease version of npm available! 124.0.0-beta.0 -> 124.0.0-beta.99999
      -Changelog: https://github.com/npm/cli/releases/tag/v124.0.0-beta.99999
      -Run npm install -g npm@124.0.0-beta.99999 to update!
      -
      +
      +New prerelease version of npm available! 124.0.0-beta.0 -> 124.0.0-beta.99999
      +Changelog: https://github.com/npm/cli/releases/tag/v124.0.0-beta.99999
      +Run npm install -g npm@124.0.0-beta.99999 to update!
      +
       `
       
       exports[`test/lib/utils/update-notifier.js TAP notification situations new beta available > no color 1`] = `
      @@ -70,11 +70,11 @@ Run \`npm install -g npm@124.0.0-beta.99999\` to update!
       `
       
       exports[`test/lib/utils/update-notifier.js TAP notification situations patch to current > color 1`] = `
      -
      -New patch version of npm available! 123.420.68 -> 123.420.69
      -Changelog: https://github.com/npm/cli/releases/tag/v123.420.69
      -Run npm install -g npm@123.420.69 to update!
      -
      +
      +New patch version of npm available! 123.420.68 -> 123.420.69
      +Changelog: https://github.com/npm/cli/releases/tag/v123.420.69
      +Run npm install -g npm@123.420.69 to update!
      +
       `
       
       exports[`test/lib/utils/update-notifier.js TAP notification situations patch to current > no color 1`] = `
      @@ -86,11 +86,11 @@ Run \`npm install -g npm@123.420.69\` to update!
       `
       
       exports[`test/lib/utils/update-notifier.js TAP notification situations patch to next version > color 1`] = `
      -
      -New patch version of npm available! 123.421.69 -> 123.421.70
      -Changelog: https://github.com/npm/cli/releases/tag/v123.421.70
      -Run npm install -g npm@123.421.70 to update!
      -
      +
      +New patch version of npm available! 123.421.69 -> 123.421.70
      +Changelog: https://github.com/npm/cli/releases/tag/v123.421.70
      +Run npm install -g npm@123.421.70 to update!
      +
       `
       
       exports[`test/lib/utils/update-notifier.js TAP notification situations patch to next version > no color 1`] = `
      diff --git a/deps/npm/test/fixtures/mock-npm.js b/deps/npm/test/fixtures/mock-npm.js
      index 1de080eb10b4a8..e3be10b4b9aa3f 100644
      --- a/deps/npm/test/fixtures/mock-npm.js
      +++ b/deps/npm/test/fixtures/mock-npm.js
      @@ -1,20 +1,19 @@
       const npmlog = require('npmlog')
      -const perf = require('../../lib/utils/perf.js')
      -perf.reset()
       const procLog = require('../../lib/utils/proc-log-listener.js')
       procLog.reset()
       
       const realLog = {}
      -for (const level of ['silly', 'verbose', 'timing', 'notice', 'warn', 'error'])
      +for (const level in npmlog.levels)
         realLog[level] = npmlog[level]
       
       const { title, execPath } = process
       
       const RealMockNpm = (t, otherMocks = {}) => {
         t.teardown(() => {
      -    for (const level of ['silly', 'verbose', 'timing', 'notice', 'warn', 'error'])
      +    npm.perfStop()
      +    npmlog.record.length = 0
      +    for (const level in npmlog.levels)
             npmlog[level] = realLog[level]
      -    perf.reset()
           procLog.reset()
           process.title = title
           process.execPath = execPath
      @@ -33,9 +32,14 @@ const RealMockNpm = (t, otherMocks = {}) => {
             })
           })
         }
      -  for (const level of ['silly', 'verbose', 'timing', 'notice', 'warn', 'error']) {
      +  for (const level in npmlog.levels) {
           npmlog[level] = (...msg) => {
             logs.push([level, ...msg])
      +
      +      const l = npmlog.level
      +      npmlog.level = 'silent'
      +      realLog[level](...msg)
      +      npmlog.level = l
           }
         }
         npm.output = (...msg) => outputs.push(msg)
      diff --git a/deps/npm/test/lib/config.js b/deps/npm/test/lib/config.js
      index 6c04293137af9e..8a1e7d85e09aa3 100644
      --- a/deps/npm/test/lib/config.js
      +++ b/deps/npm/test/lib/config.js
      @@ -47,8 +47,8 @@ const defaults = {
       const cliConfig = {
         editor: 'vi',
         json: false,
      +  location: 'user',
         long: false,
      -  global: false,
         cat: true,
         chai: true,
         dog: true,
      @@ -198,8 +198,8 @@ t.test('config list --json', t => {
             {
               editor: 'vi',
               json: true,
      +        location: 'user',
               long: false,
      -        global: false,
               cat: true,
               chai: true,
               dog: true,
      @@ -265,7 +265,7 @@ t.test('config delete multiple key', t => {
         })
       })
       
      -t.test('config delete key --global', t => {
      +t.test('config delete key --location=global', t => {
         t.plan(4)
       
         npm.config.delete = (key, where) => {
      @@ -277,13 +277,13 @@ t.test('config delete key --global', t => {
           t.equal(where, 'global', 'should save global config post-delete')
         }
       
      -  cliConfig.global = true
      +  cliConfig.location = 'global'
         config.exec(['delete', 'foo'], (err) => {
      -    t.error(err, 'npm config delete key --global')
      +    t.error(err, 'npm config delete key --location=global')
         })
       
         t.teardown(() => {
      -    cliConfig.global = false
      +    cliConfig.location = 'user'
           delete npm.config.delete
           delete npm.config.save
         })
      @@ -419,7 +419,7 @@ t.test('config set invalid key', t => {
         })
       })
       
      -t.test('config set key --global', t => {
      +t.test('config set key --location=global', t => {
         t.plan(5)
       
         npm.config.set = (key, val, where) => {
      @@ -432,13 +432,13 @@ t.test('config set key --global', t => {
           t.equal(where, 'global', 'should save global config')
         }
       
      -  cliConfig.global = true
      +  cliConfig.location = 'global'
         config.exec(['set', 'foo', 'bar'], (err) => {
      -    t.error(err, 'npm config set key --global')
      +    t.error(err, 'npm config set key --location=global')
         })
       
         t.teardown(() => {
      -    cliConfig.global = false
      +    cliConfig.location = 'user'
           delete npm.config.set
           delete npm.config.save
         })
      @@ -583,10 +583,10 @@ sign-git-commit=true`
         })
       })
       
      -t.test('config edit --global', t => {
      +t.test('config edit --location=global', t => {
         t.plan(6)
       
      -  cliConfig.global = true
      +  cliConfig.location = 'global'
         const npmrc = 'init.author.name=Foo'
         npm.config.data.set('global', {
           source: '/etc/npmrc',
      @@ -626,7 +626,7 @@ t.test('config edit --global', t => {
         })
       
         t.teardown(() => {
      -    cliConfig.global = false
      +    cliConfig.location = 'user'
           npm.config.data.delete('user')
           delete npm.config.save
         })
      diff --git a/deps/npm/test/lib/link.js b/deps/npm/test/lib/link.js
      index 736d18cab99068..96f689892ff83b 100644
      --- a/deps/npm/test/lib/link.js
      +++ b/deps/npm/test/lib/link.js
      @@ -30,7 +30,7 @@ const printLinks = async (opts) => {
         const linkedItems = [...tree.inventory.values()]
           .sort((a, b) => a.pkgid.localeCompare(b.pkgid, 'en'))
         for (const item of linkedItems) {
      -    if (item.target)
      +    if (item.isLink)
             res += `${item.path} -> ${item.target.path}\n`
         }
         return res
      diff --git a/deps/npm/test/lib/npm.js b/deps/npm/test/lib/npm.js
      index 291a58955ceedd..03bb46d8d8451c 100644
      --- a/deps/npm/test/lib/npm.js
      +++ b/deps/npm/test/lib/npm.js
      @@ -476,3 +476,28 @@ t.test('set process.title', t => {
       
         t.end()
       })
      +
      +t.test('timings', t => {
      +  const { npm, logs } = mockNpm(t)
      +  process.emit('time', 'foo')
      +  process.emit('time', 'bar')
      +  t.match(npm.timers.get('foo'), Number, 'foo timer is a number')
      +  t.match(npm.timers.get('bar'), Number, 'foo timer is a number')
      +  process.emit('timeEnd', 'foo')
      +  process.emit('timeEnd', 'bar')
      +  process.emit('timeEnd', 'baz')
      +  t.match(logs, [
      +    ['timing', 'foo', /Completed in [0-9]+ms/],
      +    ['timing', 'bar', /Completed in [0-9]+ms/],
      +    [
      +      'silly',
      +      'timing',
      +      "Tried to end timer that doesn't exist:",
      +      'baz',
      +    ],
      +  ])
      +  t.notOk(npm.timers.has('foo'), 'foo timer is gone')
      +  t.notOk(npm.timers.has('bar'), 'bar timer is gone')
      +  t.match(npm.timings, { foo: Number, bar: Number })
      +  t.end()
      +})
      diff --git a/deps/npm/test/lib/pkg.js b/deps/npm/test/lib/pkg.js
      new file mode 100644
      index 00000000000000..688df6859054af
      --- /dev/null
      +++ b/deps/npm/test/lib/pkg.js
      @@ -0,0 +1,737 @@
      +const { resolve } = require('path')
      +const { readFileSync } = require('fs')
      +const t = require('tap')
      +const { fake: mockNpm } = require('../fixtures/mock-npm')
      +
      +const redactCwd = (path) => {
      +  const normalizePath = p => p
      +    .replace(/\\+/g, '/')
      +    .replace(/\r\n/g, '\n')
      +  return normalizePath(path)
      +    .replace(new RegExp(normalizePath(process.cwd()), 'g'), '{CWD}')
      +}
      +
      +t.cleanSnapshot = (str) => redactCwd(str)
      +
      +let OUTPUT = ''
      +const config = {
      +  global: false,
      +  force: false,
      +  'pkg-cast': 'string',
      +}
      +const npm = mockNpm({
      +  localPrefix: t.testdirName,
      +  config,
      +  output: (str) => {
      +    OUTPUT += str
      +  },
      +})
      +
      +const Pkg = require('../../lib/pkg.js')
      +const pkg = new Pkg(npm)
      +
      +const readPackageJson = (path) => {
      +  path = path || npm.localPrefix
      +  return JSON.parse(readFileSync(resolve(path, 'package.json'), 'utf8'))
      +}
      +
      +t.afterEach(() => {
      +  config.global = false
      +  config.json = false
      +  npm.localPrefix = t.testdirName
      +  OUTPUT = ''
      +})
      +
      +t.test('no args', t => {
      +  pkg.exec([], err => {
      +    t.match(
      +      err,
      +      { code: 'EUSAGE' },
      +      'should throw usage error'
      +    )
      +    t.end()
      +  })
      +})
      +
      +t.test('no global mode', t => {
      +  config.global = true
      +  pkg.exec(['get', 'foo'], err => {
      +    t.match(
      +      err,
      +      { code: 'EPKGGLOBAL' },
      +      'should throw no global mode error'
      +    )
      +    t.end()
      +  })
      +})
      +
      +t.test('get no args', t => {
      +  npm.localPrefix = t.testdir({
      +    'package.json': JSON.stringify({
      +      name: 'foo',
      +      version: '1.1.1',
      +    }),
      +  })
      +
      +  pkg.exec(['get'], err => {
      +    if (err)
      +      throw err
      +
      +    t.strictSame(
      +      JSON.parse(OUTPUT),
      +      {
      +        name: 'foo',
      +        version: '1.1.1',
      +      },
      +      'should print package.json content'
      +    )
      +    t.end()
      +  })
      +})
      +
      +t.test('get single arg', t => {
      +  npm.localPrefix = t.testdir({
      +    'package.json': JSON.stringify({
      +      name: 'foo',
      +      version: '1.1.1',
      +    }),
      +  })
      +
      +  pkg.exec(['get', 'version'], err => {
      +    if (err)
      +      throw err
      +
      +    t.strictSame(
      +      JSON.parse(OUTPUT),
      +      '1.1.1',
      +      'should print retrieved package.json field'
      +    )
      +    t.end()
      +  })
      +})
      +
      +t.test('get nested arg', t => {
      +  npm.localPrefix = t.testdir({
      +    'package.json': JSON.stringify({
      +      name: 'foo',
      +      version: '1.1.1',
      +      scripts: {
      +        test: 'node test.js',
      +      },
      +    }),
      +  })
      +
      +  pkg.exec(['get', 'scripts.test'], err => {
      +    if (err)
      +      throw err
      +
      +    t.strictSame(
      +      JSON.parse(OUTPUT),
      +      'node test.js',
      +      'should print retrieved nested field'
      +    )
      +    t.end()
      +  })
      +})
      +
      +t.test('get array field', t => {
      +  const files = [
      +    'index.js',
      +    'cli.js',
      +  ]
      +  npm.localPrefix = t.testdir({
      +    'package.json': JSON.stringify({
      +      name: 'foo',
      +      version: '1.1.1',
      +      files,
      +    }),
      +  })
      +
      +  pkg.exec(['get', 'files'], err => {
      +    if (err)
      +      throw err
      +
      +    t.strictSame(
      +      JSON.parse(OUTPUT),
      +      files,
      +      'should print retrieved array field'
      +    )
      +    t.end()
      +  })
      +})
      +
      +t.test('get array item', t => {
      +  const files = [
      +    'index.js',
      +    'cli.js',
      +  ]
      +  npm.localPrefix = t.testdir({
      +    'package.json': JSON.stringify({
      +      name: 'foo',
      +      version: '1.1.1',
      +      files,
      +    }),
      +  })
      +
      +  pkg.exec(['get', 'files[0]'], err => {
      +    if (err)
      +      throw err
      +
      +    t.strictSame(
      +      JSON.parse(OUTPUT),
      +      'index.js',
      +      'should print retrieved array field'
      +    )
      +    t.end()
      +  })
      +})
      +
      +t.test('get array nested items notation', t => {
      +  const contributors = [
      +    {
      +      name: 'Ruy',
      +      url: 'http://example.com/ruy',
      +    },
      +    {
      +      name: 'Gar',
      +      url: 'http://example.com/gar',
      +    },
      +  ]
      +  npm.localPrefix = t.testdir({
      +    'package.json': JSON.stringify({
      +      name: 'foo',
      +      version: '1.1.1',
      +      contributors,
      +    }),
      +  })
      +
      +  pkg.exec(['get', 'contributors.name'], err => {
      +    if (err)
      +      throw err
      +
      +    t.strictSame(
      +      JSON.parse(OUTPUT),
      +      {
      +        'contributors[0].name': 'Ruy',
      +        'contributors[1].name': 'Gar',
      +      },
      +      'should print json result containing matching results'
      +    )
      +    t.end()
      +  })
      +})
      +
      +t.test('set no args', t => {
      +  npm.localPrefix = t.testdir({
      +    'package.json': JSON.stringify({ name: 'foo' }),
      +  })
      +  pkg.exec(['set'], err => {
      +    t.match(
      +      err,
      +      { code: 'EPKGSET' },
      +      'should throw an error if no args'
      +    )
      +
      +    t.end()
      +  })
      +})
      +
      +t.test('set missing value', t => {
      +  npm.localPrefix = t.testdir({
      +    'package.json': JSON.stringify({ name: 'foo' }),
      +  })
      +  pkg.exec(['set', 'key='], err => {
      +    t.match(
      +      err,
      +      { code: 'EPKGSET' },
      +      'should throw an error if missing value'
      +    )
      +
      +    t.end()
      +  })
      +})
      +
      +t.test('set missing key', t => {
      +  npm.localPrefix = t.testdir({
      +    'package.json': JSON.stringify({ name: 'foo' }),
      +  })
      +  pkg.exec(['set', '=value'], err => {
      +    t.match(
      +      err,
      +      { code: 'EPKGSET' },
      +      'should throw an error if missing key'
      +    )
      +
      +    t.end()
      +  })
      +})
      +
      +t.test('set single field', t => {
      +  const json = {
      +    name: 'foo',
      +    version: '1.1.1',
      +  }
      +  npm.localPrefix = t.testdir({
      +    'package.json': JSON.stringify(json),
      +  })
      +
      +  pkg.exec(['set', 'description=Awesome stuff'], err => {
      +    if (err)
      +      throw err
      +
      +    t.strictSame(
      +      readPackageJson(),
      +      {
      +        ...json,
      +        description: 'Awesome stuff',
      +      },
      +      'should add single field to package.json'
      +    )
      +    t.end()
      +  })
      +})
      +
      +t.test('push to array syntax', t => {
      +  const json = {
      +    name: 'foo',
      +    version: '1.1.1',
      +    keywords: [
      +      'foo',
      +    ],
      +  }
      +  npm.localPrefix = t.testdir({
      +    'package.json': JSON.stringify(json),
      +  })
      +
      +  pkg.exec(['set', 'keywords[]=bar', 'keywords[]=baz'], err => {
      +    if (err)
      +      throw err
      +
      +    t.strictSame(
      +      readPackageJson(),
      +      {
      +        ...json,
      +        keywords: [
      +          'foo',
      +          'bar',
      +          'baz',
      +        ],
      +      },
      +      'should append to arrays using empty bracket syntax'
      +    )
      +    t.end()
      +  })
      +})
      +
      +t.test('set multiple fields', t => {
      +  const json = {
      +    name: 'foo',
      +    version: '1.1.1',
      +  }
      +  npm.localPrefix = t.testdir({
      +    'package.json': JSON.stringify(json),
      +  })
      +
      +  pkg.exec(['set', 'bin.foo=foo.js', 'scripts.test=node test.js'], err => {
      +    if (err)
      +      throw err
      +
      +    t.strictSame(
      +      readPackageJson(),
      +      {
      +        ...json,
      +        bin: {
      +          foo: 'foo.js',
      +        },
      +        scripts: {
      +          test: 'node test.js',
      +        },
      +      },
      +      'should add single field to package.json'
      +    )
      +    t.end()
      +  })
      +})
      +
      +t.test('set = separate value', t => {
      +  const json = {
      +    name: 'foo',
      +    version: '1.1.1',
      +  }
      +  npm.localPrefix = t.testdir({
      +    'package.json': JSON.stringify(json),
      +  })
      +
      +  pkg.exec(['set', 'tap[test-env][0]=LC_ALL=sk'], err => {
      +    if (err)
      +      throw err
      +
      +    t.strictSame(
      +      readPackageJson(),
      +      {
      +        ...json,
      +        tap: {
      +          'test-env': [
      +            'LC_ALL=sk',
      +          ],
      +        },
      +      },
      +      'should add single field to package.json'
      +    )
      +    t.end()
      +  })
      +})
      +
      +t.test('set --json', async t => {
      +  config.json = true
      +  npm.localPrefix = t.testdir({
      +    'package.json': JSON.stringify({
      +      name: 'foo',
      +      version: '1.1.1',
      +    }),
      +  })
      +
      +  await new Promise((res, rej) => {
      +    pkg.exec(['set', 'private=true'], err => {
      +      if (err)
      +        rej(err)
      +
      +      t.strictSame(
      +        readPackageJson(),
      +        {
      +          name: 'foo',
      +          version: '1.1.1',
      +          private: true,
      +        },
      +        'should add boolean field to package.json'
      +      )
      +      res()
      +    })
      +  })
      +
      +  await new Promise((res, rej) => {
      +    pkg.exec(['set', 'tap.timeout=60'], err => {
      +      if (err)
      +        rej(err)
      +
      +      t.strictSame(
      +        readPackageJson(),
      +        {
      +          name: 'foo',
      +          version: '1.1.1',
      +          private: true,
      +          tap: {
      +            timeout: 60,
      +          },
      +        },
      +        'should add number field to package.json'
      +      )
      +      res()
      +    })
      +  })
      +
      +  await new Promise((res, rej) => {
      +    pkg.exec(['set', 'foo={ "bar": { "baz": "BAZ" } }'], err => {
      +      if (err)
      +        rej(err)
      +
      +      t.strictSame(
      +        readPackageJson(),
      +        {
      +          name: 'foo',
      +          version: '1.1.1',
      +          private: true,
      +          tap: {
      +            timeout: 60,
      +          },
      +          foo: {
      +            bar: {
      +              baz: 'BAZ',
      +            },
      +          },
      +        },
      +        'should add object field to package.json'
      +      )
      +      res()
      +    })
      +  })
      +
      +  await new Promise((res, rej) => {
      +    pkg.exec(['set', 'workspaces=["packages/*"]'], err => {
      +      if (err)
      +        rej(err)
      +
      +      t.strictSame(
      +        readPackageJson(),
      +        {
      +          name: 'foo',
      +          version: '1.1.1',
      +          private: true,
      +          workspaces: [
      +            'packages/*',
      +          ],
      +          tap: {
      +            timeout: 60,
      +          },
      +          foo: {
      +            bar: {
      +              baz: 'BAZ',
      +            },
      +          },
      +        },
      +        'should add object field to package.json'
      +      )
      +      res()
      +    })
      +  })
      +
      +  await new Promise((res, rej) => {
      +    pkg.exec(['set', 'description="awesome"'], err => {
      +      if (err)
      +        rej(err)
      +
      +      t.strictSame(
      +        readPackageJson(),
      +        {
      +          name: 'foo',
      +          version: '1.1.1',
      +          description: 'awesome',
      +          private: true,
      +          workspaces: [
      +            'packages/*',
      +          ],
      +          tap: {
      +            timeout: 60,
      +          },
      +          foo: {
      +            bar: {
      +              baz: 'BAZ',
      +            },
      +          },
      +        },
      +        'should add object field to package.json'
      +      )
      +      res()
      +    })
      +  })
      +})
      +
      +t.test('delete no args', t => {
      +  npm.localPrefix = t.testdir({
      +    'package.json': JSON.stringify({ name: 'foo' }),
      +  })
      +  pkg.exec(['delete'], err => {
      +    t.match(
      +      err,
      +      { code: 'EPKGDELETE' },
      +      'should throw an error if deleting no args'
      +    )
      +
      +    t.end()
      +  })
      +})
      +
      +t.test('delete invalid key', t => {
      +  npm.localPrefix = t.testdir({
      +    'package.json': JSON.stringify({ name: 'foo' }),
      +  })
      +  pkg.exec(['delete', ''], err => {
      +    t.match(
      +      err,
      +      { code: 'EPKGDELETE' },
      +      'should throw an error if deleting invalid args'
      +    )
      +
      +    t.end()
      +  })
      +})
      +
      +t.test('delete single field', t => {
      +  npm.localPrefix = t.testdir({
      +    'package.json': JSON.stringify({
      +      name: 'foo',
      +      version: '1.0.0',
      +    }),
      +  })
      +  pkg.exec(['delete', 'version'], err => {
      +    if (err)
      +      throw err
      +
      +    t.strictSame(
      +      readPackageJson(),
      +      {
      +        name: 'foo',
      +      },
      +      'should delete single field from package.json'
      +    )
      +
      +    t.end()
      +  })
      +})
      +
      +t.test('delete multiple field', t => {
      +  npm.localPrefix = t.testdir({
      +    'package.json': JSON.stringify({
      +      name: 'foo',
      +      version: '1.0.0',
      +      description: 'awesome',
      +    }),
      +  })
      +  pkg.exec(['delete', 'version', 'description'], err => {
      +    if (err)
      +      throw err
      +
      +    t.strictSame(
      +      readPackageJson(),
      +      {
      +        name: 'foo',
      +      },
      +      'should delete multiple fields from package.json'
      +    )
      +
      +    t.end()
      +  })
      +})
      +
      +t.test('delete nested field', t => {
      +  npm.localPrefix = t.testdir({
      +    'package.json': JSON.stringify({
      +      name: 'foo',
      +      version: '1.0.0',
      +      info: {
      +        foo: {
      +          bar: [
      +            {
      +              baz: 'deleteme',
      +            },
      +          ],
      +        },
      +      },
      +    }),
      +  })
      +  pkg.exec(['delete', 'info.foo.bar[0].baz'], err => {
      +    if (err)
      +      throw err
      +
      +    t.strictSame(
      +      readPackageJson(),
      +      {
      +        name: 'foo',
      +        version: '1.0.0',
      +        info: {
      +          foo: {
      +            bar: [
      +              {},
      +            ],
      +          },
      +        },
      +      },
      +      'should delete nested fields from package.json'
      +    )
      +
      +    t.end()
      +  })
      +})
      +
      +t.test('workspaces', async t => {
      +  npm.localPrefix = t.testdir({
      +    'package.json': JSON.stringify({
      +      name: 'root',
      +      version: '1.0.0',
      +      workspaces: [
      +        'packages/*',
      +      ],
      +    }),
      +    packages: {
      +      a: {
      +        'package.json': JSON.stringify({
      +          name: 'a',
      +          version: '1.0.0',
      +        }),
      +      },
      +      b: {
      +        'package.json': JSON.stringify({
      +          name: 'b',
      +          version: '1.2.3',
      +        }),
      +      },
      +    },
      +  })
      +
      +  await new Promise((res, rej) => {
      +    pkg.execWorkspaces(['get', 'name', 'version'], [], err => {
      +      if (err)
      +        rej(err)
      +
      +      t.strictSame(
      +        JSON.parse(OUTPUT),
      +        {
      +          a: {
      +            name: 'a',
      +            version: '1.0.0',
      +          },
      +          b: {
      +            name: 'b',
      +            version: '1.2.3',
      +          },
      +        },
      +        'should return expected result for configured workspaces'
      +      )
      +      res()
      +    })
      +  })
      +
      +  await new Promise((res, rej) => {
      +    pkg.execWorkspaces(['set', 'funding=http://example.com'], [], err => {
      +      if (err)
      +        rej(err)
      +
      +      t.strictSame(
      +        readPackageJson(resolve(npm.localPrefix, 'packages/a')),
      +        {
      +          name: 'a',
      +          version: '1.0.0',
      +          funding: 'http://example.com',
      +        },
      +        'should add field to workspace a'
      +      )
      +
      +      t.strictSame(
      +        readPackageJson(resolve(npm.localPrefix, 'packages/b')),
      +        {
      +          name: 'b',
      +          version: '1.2.3',
      +          funding: 'http://example.com',
      +        },
      +        'should add field to workspace b'
      +      )
      +      res()
      +    })
      +  })
      +
      +  await new Promise((res, rej) => {
      +    pkg.execWorkspaces(['delete', 'version'], [], err => {
      +      if (err)
      +        rej(err)
      +
      +      t.strictSame(
      +        readPackageJson(resolve(npm.localPrefix, 'packages/a')),
      +        {
      +          name: 'a',
      +          funding: 'http://example.com',
      +        },
      +        'should delete version field from workspace a'
      +      )
      +
      +      t.strictSame(
      +        readPackageJson(resolve(npm.localPrefix, 'packages/b')),
      +        {
      +          name: 'b',
      +          funding: 'http://example.com',
      +        },
      +        'should delete version field from workspace b'
      +      )
      +      res()
      +    })
      +  })
      +})
      diff --git a/deps/npm/test/lib/publish.js b/deps/npm/test/lib/publish.js
      index 56590478fc1ae4..4aa3e5592751e0 100644
      --- a/deps/npm/test/lib/publish.js
      +++ b/deps/npm/test/lib/publish.js
      @@ -762,3 +762,103 @@ t.test('private workspaces', (t) => {
       
         t.end()
       })
      +
      +t.test('runs correct lifecycle scripts', t => {
      +  const testDir = t.testdir({
      +    'package.json': JSON.stringify({
      +      name: 'my-cool-pkg',
      +      version: '1.0.0',
      +      scripts: {
      +        prepublishOnly: 'echo test prepublishOnly',
      +        prepublish: 'echo test prepublish', // should NOT run this one
      +        publish: 'echo test publish',
      +        postpublish: 'echo test postpublish',
      +      },
      +    }, null, 2),
      +  })
      +
      +  const scripts = []
      +  const Publish = t.mock('../../lib/publish.js', {
      +    '@npmcli/run-script': (args) => {
      +      scripts.push(args)
      +    },
      +    '../../lib/utils/tar.js': {
      +      getContents: () => ({
      +        id: 'someid',
      +      }),
      +      logTar: () => {
      +        t.pass('logTar is called')
      +      },
      +    },
      +    libnpmpublish: {
      +      publish: () => {
      +        t.pass('publish called')
      +      },
      +    },
      +  })
      +  const npm = mockNpm({
      +    output: () => {
      +      t.pass('output is called')
      +    },
      +  })
      +  npm.config.getCredentialsByURI = (uri) => {
      +    t.same(uri, npm.config.get('registry'), 'gets credentials for expected registry')
      +    return { token: 'some.registry.token' }
      +  }
      +  const publish = new Publish(npm)
      +  publish.exec([testDir], (er) => {
      +    if (er)
      +      throw er
      +    t.same(
      +      scripts.map(s => s.event),
      +      ['prepublishOnly', 'publish', 'postpublish'],
      +      'runs only expected scripts, in order'
      +    )
      +    t.end()
      +  })
      +})
      +
      +t.test('does not run scripts on --ignore-scripts', t => {
      +  const testDir = t.testdir({
      +    'package.json': JSON.stringify({
      +      name: 'my-cool-pkg',
      +      version: '1.0.0',
      +    }, null, 2),
      +  })
      +
      +  const Publish = t.mock('../../lib/publish.js', {
      +    '@npmcli/run-script': () => {
      +      t.fail('should not call run-script')
      +    },
      +    '../../lib/utils/tar.js': {
      +      getContents: () => ({
      +        id: 'someid',
      +      }),
      +      logTar: () => {
      +        t.pass('logTar is called')
      +      },
      +    },
      +    libnpmpublish: {
      +      publish: () => {
      +        t.pass('publish called')
      +      },
      +    },
      +  })
      +  const npm = mockNpm({
      +    config: { 'ignore-scripts': true },
      +    output: () => {
      +      t.pass('output is called')
      +    },
      +  })
      +  npm.config.getCredentialsByURI = (uri) => {
      +    t.same(uri, npm.config.get('registry'), 'gets credentials for expected registry')
      +    return { token: 'some.registry.token' }
      +  }
      +  const publish = new Publish(npm)
      +  publish.exec([testDir], (er) => {
      +    if (er)
      +      throw er
      +    t.pass('got to callback')
      +    t.end()
      +  })
      +})
      diff --git a/deps/npm/test/lib/utils/config/definition.js b/deps/npm/test/lib/utils/config/definition.js
      index 45f4c977a77a03..a17a1a09a2240b 100644
      --- a/deps/npm/test/lib/utils/config/definition.js
      +++ b/deps/npm/test/lib/utils/config/definition.js
      @@ -95,6 +95,13 @@ t.test('basic definition', async t => {
           description: 'test description',
         })
         t.equal(hasShort.usage, '-t|--key ')
      +  const multiHasShort = new Definition('key', {
      +    default: 'test default',
      +    short: 't',
      +    type: [null, String],
      +    description: 'test description',
      +  })
      +  t.equal(multiHasShort.usage, '-t|--key ')
         const hardCodedTypes = new Definition('key', {
           default: 'test default',
           type: ['string1', 'string2'],
      diff --git a/deps/npm/test/lib/utils/config/definitions.js b/deps/npm/test/lib/utils/config/definitions.js
      index 8724f0e3bd3ebd..63d9bbd195ab28 100644
      --- a/deps/npm/test/lib/utils/config/definitions.js
      +++ b/deps/npm/test/lib/utils/config/definitions.js
      @@ -463,7 +463,7 @@ t.test('search options', t => {
         t.end()
       })
       
      -t.test('noProxy', t => {
      +t.test('noProxy - array', t => {
         const obj = { noproxy: ['1.2.3.4,2.3.4.5', '3.4.5.6'] }
         const flat = {}
         definitions.noproxy.flatten('noproxy', obj, flat)
      @@ -471,6 +471,14 @@ t.test('noProxy', t => {
         t.end()
       })
       
      +t.test('noProxy - string', t => {
      +  const obj = { noproxy: '1.2.3.4,2.3.4.5,3.4.5.6' }
      +  const flat = {}
      +  definitions.noproxy.flatten('noproxy', obj, flat)
      +  t.strictSame(flat, { noProxy: '1.2.3.4,2.3.4.5,3.4.5.6' })
      +  t.end()
      +})
      +
       t.test('maxSockets', t => {
         const obj = { maxsockets: 123 }
         const flat = {}
      @@ -797,3 +805,26 @@ t.test('save-exact', t => {
         t.strictSame(flat, { savePrefix: '~1.2.3' })
         t.end()
       })
      +
      +t.test('location', t => {
      +  const obj = {
      +    global: true,
      +    location: 'user',
      +  }
      +  const flat = {}
      +  definitions.location.flatten('location', obj, flat)
      +  // global = true sets location in both places to global
      +  t.strictSame(flat, { location: 'global' })
      +  t.strictSame(obj, { global: true, location: 'global' })
      +
      +  obj.global = false
      +  obj.location = 'user'
      +  delete flat.global
      +  delete flat.location
      +
      +  definitions.location.flatten('location', obj, flat)
      +  // global = false leaves location unaltered
      +  t.strictSame(flat, { location: 'user' })
      +  t.strictSame(obj, { global: false, location: 'user' })
      +  t.end()
      +})
      diff --git a/deps/npm/test/lib/utils/error-message.js b/deps/npm/test/lib/utils/error-message.js
      index 4f94645a4542d2..3fdfb8cc250898 100644
      --- a/deps/npm/test/lib/utils/error-message.js
      +++ b/deps/npm/test/lib/utils/error-message.js
      @@ -97,6 +97,7 @@ t.test('just simple messages', t => {
           'ETOOMANYARGS',
           'ETARGET',
           'E403',
      +    'ERR_SOCKET_TIMEOUT',
         ]
         t.plan(codes.length)
         codes.forEach(code => {
      diff --git a/deps/npm/test/lib/utils/exit-handler.js b/deps/npm/test/lib/utils/exit-handler.js
      index 06014b67a97548..981ac9a32b6845 100644
      --- a/deps/npm/test/lib/utils/exit-handler.js
      +++ b/deps/npm/test/lib/utils/exit-handler.js
      @@ -1,13 +1,12 @@
       /* eslint-disable no-extend-native */
       /* eslint-disable no-global-assign */
      -const EventEmitter = require('events')
      -const writeFileAtomic = require('write-file-atomic')
       const t = require('tap')
      +const EventEmitter = require('events')
      +const os = require('os')
      +const fs = require('fs')
      +const path = require('path')
       
      -// NOTE: Although these unit tests may look like the rest on the surface,
      -// they are in fact very special due to the amount of things hooking directly
      -// to global process and variables defined in the module scope. That makes
      -// for tests that are very interdependent and their order are important.
      +const { real: mockNpm } = require('../../fixtures/mock-npm')
       
       // generic error to be used in tests
       const err = Object.assign(new Error('ERROR'), { code: 'ERROR' })
      @@ -23,69 +22,23 @@ const redactCwd = (path) => {
       
       t.cleanSnapshot = (str) => redactCwd(str)
       
      -// internal modules mocks
       const cacheFolder = t.testdir({})
      -const config = {
      -  values: {
      -    cache: cacheFolder,
      -    timing: true,
      -  },
      -  loaded: true,
      -  updateNotification: null,
      -  get (key) {
      -    return this.values[key]
      -  },
      -}
      -
      -const npm = {
      -  version: '1.0.0',
      -  config,
      -  shelloutCommands: ['exec', 'run-script'],
      -}
      +const logFile = path.resolve(cacheFolder, '_logs', 'expecteddate-debug.log')
      +const timingFile = path.resolve(cacheFolder, '_timing.json')
       
      -const npmlog = {
      -  disableProgress: () => null,
      -  log (level, ...args) {
      -    this.record.push({
      -      id: this.record.length,
      -      level,
      -      message: args.reduce((res, i) => `${res} ${i.message ? i.message : i}`, ''),
      -      prefix: level !== 'verbose' ? 'foo' : '',
      -    })
      -  },
      -  error (...args) {
      -    this.log('error', ...args)
      -  },
      -  info (...args) {
      -    this.log('info', ...args)
      -  },
      -  level: 'silly',
      -  levels: {
      -    silly: 0,
      -    verbose: 1,
      -    info: 2,
      -    error: 3,
      -    silent: 4,
      -  },
      -  notice (...args) {
      -    this.log('notice', ...args)
      -  },
      -  record: [],
      -  verbose (...args) {
      -    this.log('verbose', ...args)
      -  },
      -}
      +const { npm } = mockNpm(t)
       
      -// overrides OS type/release for cross platform snapshots
      -const os = require('os')
      -os.type = () => 'Foo'
      -os.release = () => '1.0.0'
      +t.before(async () => {
      +  npm.version = '1.0.0'
      +  await npm.load()
      +  npm.config.set('cache', cacheFolder)
      +})
       
      -// bootstrap tap before cutting off process ref
      -t.test('ok', (t) => {
      +t.test('bootstrap tap before cutting off process ref', (t) => {
         t.ok('ok')
         t.end()
       })
      +
       // cut off process from script so that it won't quit the test runner
       // while trying to run through the myriad of cases
       const _process = process
      @@ -95,9 +48,11 @@ process = Object.assign(
           argv: ['/node', ..._process.argv.slice(1)],
           cwd: _process.cwd,
           env: _process.env,
      -    exit () {},
      -    exitCode: 0,
           version: 'v1.0.0',
      +    exit: (code) => {
      +      process.exitCode = code || process.exitCode || 0
      +      process.emit('exit', process.exitCode)
      +    },
           stdout: { write (_, cb) {
             cb()
           } },
      @@ -105,19 +60,40 @@ process = Object.assign(
           hrtime: _process.hrtime,
         }
       )
      -// needs to put process back in its place
      -// in order for tap to exit properly
      +
      +const osType = os.type
      +const osRelease = os.release
      +// overrides OS type/release for cross platform snapshots
      +os.type = () => 'Foo'
      +os.release = () => '1.0.0'
      +
      +// generates logfile name with mocked date
      +const _toISOString = Date.prototype.toISOString
      +Date.prototype.toISOString = () => 'expecteddate'
      +
      +const consoleError = console.error
      +const errors = []
      +console.error = (err) => {
      +  errors.push(err)
      +}
       t.teardown(() => {
      +  os.type = osType
      +  os.release = osRelease
      +  // needs to put process back in its place in order for tap to exit properly
         process = _process
      +  Date.prototype.toISOString = _toISOString
      +  console.error = consoleError
       })
       
       t.afterEach(() => {
      +  errors.length = 0
      +  npm.log.level = 'silent'
         // clear out the 'A complete log' message
      -  npmlog.record.length = 0
      +  npm.log.record.length = 0
      +  delete process.exitCode
       })
       
       const mocks = {
      -  npmlog,
         '../../../lib/utils/error-message.js': (err) => ({
           ...err,
           summary: [['ERR', err.message]],
      @@ -125,102 +101,57 @@ const mocks = {
         }),
       }
       
      -let exitHandler = t.mock('../../../lib/utils/exit-handler.js', mocks)
      +const exitHandler = t.mock('../../../lib/utils/exit-handler.js', mocks)
       exitHandler.setNpm(npm)
       
      -t.test('default exit code', (t) => {
      -  t.plan(1)
      -
      -  // manually simulate timing handlers
      -  process.emit('timing', 'foo', 1)
      -  process.emit('timing', 'foo', 2)
      -
      -  // generates logfile name with mocked date
      -  const _toISOString = Date.prototype.toISOString
      -  Date.prototype.toISOString = () => 'expecteddate'
      -
      -  npmlog.level = 'silent'
      -  const _exit = process.exit
      -  process.exit = (code) => {
      -    t.equal(code, 1, 'should default to error code 1')
      -  }
      -
      -  // skip console.error logs
      -  const _error = console.error
      -  console.error = () => null
      -
      +t.test('exit handler never called - loglevel silent', (t) => {
      +  npm.log.level = 'silent'
         process.emit('exit', 1)
      +  const logData = fs.readFileSync(logFile, 'utf8')
      +  t.match(logData, 'Exit handler never called!')
      +  t.match(errors, [''], 'logs one empty string to console.error')
      +  t.end()
      +})
       
      -  t.teardown(() => {
      -    npmlog.level = 'silly'
      -    process.exit = _exit
      -    console.error = _error
      -    Date.prototype.toISOString = _toISOString
      -  })
      +t.test('exit handler never called - loglevel notice', (t) => {
      +  npm.log.level = 'notice'
      +  process.emit('exit', 1)
      +  const logData = fs.readFileSync(logFile, 'utf8')
      +  t.match(logData, 'Exit handler never called!')
      +  t.match(errors, ['', ''], 'logs two empty strings to console.error')
      +  t.end()
       })
       
       t.test('handles unknown error', (t) => {
         t.plan(2)
       
      -  const _toISOString = Date.prototype.toISOString
      -  Date.prototype.toISOString = () => 'expecteddate'
      -
      -  const sync = writeFileAtomic.sync
      -  writeFileAtomic.sync = (filename, content) => {
      -    t.equal(
      -      redactCwd(filename),
      -      '{CWD}/test/lib/utils/tap-testdir-exit-handler/_logs/expecteddate-debug.log',
      -      'should use expected log filename'
      -    )
      -    t.matchSnapshot(
      -      content,
      -      'should have expected log contents for unknown error'
      -    )
      -  }
      -
      -  exitHandler(err)
      +  npm.log.level = 'notice'
       
      -  t.teardown(() => {
      -    writeFileAtomic.sync = sync
      -    Date.prototype.toISOString = _toISOString
      +  process.once('timeEnd', (msg) => {
      +    t.equal(msg, 'npm', 'should trigger timeEnd for npm')
         })
      +
      +  exitHandler(err)
      +  const logData = fs.readFileSync(logFile, 'utf8')
      +  t.matchSnapshot(
      +    logData,
      +    'should have expected log contents for unknown error'
      +  )
         t.end()
       })
       
      -t.test('npm.config not ready', (t) => {
      +t.test('fail to write logfile', (t) => {
         t.plan(1)
       
      -  config.loaded = false
      -
      -  const _error = console.error
      -  console.error = (msg) => {
      -    t.match(
      -      msg,
      -      /Error: Exit prior to config file resolving./,
      -      'should exit with config error msg'
      -    )
      -  }
      -
      -  exitHandler()
      -
         t.teardown(() => {
      -    console.error = _error
      -    config.loaded = true
      +    npm.config.set('cache', cacheFolder)
         })
      -})
      -
      -t.test('fail to write logfile', (t) => {
      -  t.plan(1)
       
         const badDir = t.testdir({
           _logs: 'is a file',
         })
       
      -  config.values.cache = badDir
      -
      -  t.teardown(() => {
      -    config.values.cache = cacheFolder
      -  })
      +  npm.config.set('cache', badDir)
       
         t.doesNotThrow(
           () => exitHandler(err),
      @@ -231,241 +162,166 @@ t.test('fail to write logfile', (t) => {
       t.test('console.log output using --json', (t) => {
         t.plan(1)
       
      -  config.values.json = true
      -
      -  const _error = console.error
      -  console.error = (jsonOutput) => {
      -    t.same(
      -      JSON.parse(jsonOutput),
      -      {
      -        error: {
      -          code: 'EBADTHING', // should default error code to E[A-Z]+
      -          summary: 'Error: EBADTHING Something happened',
      -          detail: 'Error: EBADTHING Something happened',
      -        },
      -      },
      -      'should output expected json output'
      -    )
      -  }
      -
      -  exitHandler(new Error('Error: EBADTHING Something happened'))
      -
      +  npm.config.set('json', true)
         t.teardown(() => {
      -    console.error = _error
      -    delete config.values.json
      +    npm.config.set('json', false)
         })
      +
      +  exitHandler(new Error('Error: EBADTHING Something happened'))
      +  t.same(
      +    JSON.parse(errors[0]),
      +    {
      +      error: {
      +        code: 'EBADTHING', // should default error code to E[A-Z]+
      +        summary: 'Error: EBADTHING Something happened',
      +        detail: 'Error: EBADTHING Something happened',
      +      },
      +    },
      +    'should output expected json output'
      +  )
       })
       
       t.test('throw a non-error obj', (t) => {
      -  t.plan(3)
      +  t.plan(2)
       
         const weirdError = {
           code: 'ESOMETHING',
           message: 'foo bar',
         }
       
      -  const _logError = npmlog.error
      -  npmlog.error = (title, err) => {
      -    t.equal(title, 'weird error', 'should name it a weird error')
      -    t.same(err, weirdError, 'should log given weird error')
      -  }
      -
      -  const _exit = process.exit
      -  process.exit = (code) => {
      -    t.equal(code, 1, 'should exit with code 1')
      -  }
      -
      -  exitHandler(weirdError)
      -
      -  t.teardown(() => {
      -    process.exit = _exit
      -    npmlog.error = _logError
      +  process.once('exit', code => {
      +    t.equal(code, 1, 'exits with exitCode 1')
         })
      +  exitHandler(weirdError)
      +  t.match(
      +    npm.log.record.find(r => r.level === 'error'),
      +    { message: 'foo bar' }
      +  )
       })
       
       t.test('throw a string error', (t) => {
      -  t.plan(3)
      -
      +  t.plan(2)
         const error = 'foo bar'
       
      -  const _logError = npmlog.error
      -  npmlog.error = (title, err) => {
      -    t.equal(title, '', 'should have an empty name ref')
      -    t.same(err, 'foo bar', 'should log string error')
      -  }
      -
      -  const _exit = process.exit
      -  process.exit = (code) => {
      -    t.equal(code, 1, 'should exit with code 1')
      -  }
      -
      -  exitHandler(error)
      -
      -  t.teardown(() => {
      -    process.exit = _exit
      -    npmlog.error = _logError
      +  process.once('exit', code => {
      +    t.equal(code, 1, 'exits with exitCode 1')
         })
      +  exitHandler(error)
      +  t.match(
      +    npm.log.record.find(r => r.level === 'error'),
      +    { message: 'foo bar' }
      +  )
       })
       
       t.test('update notification', (t) => {
      -  t.plan(2)
      -
         const updateMsg = 'you should update npm!'
         npm.updateNotification = updateMsg
      -
      -  const _notice = npmlog.notice
      -  npmlog.notice = (prefix, msg) => {
      -    t.equal(prefix, '', 'should have no prefix')
      -    t.equal(msg, updateMsg, 'should show update message')
      -  }
      -
      -  exitHandler(err)
      +  npm.log.level = 'silent'
       
         t.teardown(() => {
      -    npmlog.notice = _notice
           delete npm.updateNotification
         })
      +
      +  exitHandler()
      +  t.match(
      +    npm.log.record.find(r => r.level === 'notice'),
      +    { message: 'you should update npm!' }
      +  )
      +  t.end()
       })
       
      -t.test('on exit handler', (t) => {
      -  t.plan(2)
      +t.test('npm.config not ready', (t) => {
      +  t.plan(1)
       
      -  const _exit = process.exit
      -  process.exit = (code) => {
      -    t.equal(code, 1, 'should default to error code 1')
      -  }
      +  const { npm: unloaded } = mockNpm(t)
       
      -  process.once('timeEnd', (msg) => {
      -    t.equal(msg, 'npm', 'should trigger timeEnd for npm')
      +  t.teardown(() => {
      +    exitHandler.setNpm(npm)
         })
       
      -  // skip console.error logs
      -  const _error = console.error
      -  console.error = () => null
      +  exitHandler.setNpm(unloaded)
       
      -  process.emit('exit', 1)
      -
      -  t.teardown(() => {
      -    console.error = _error
      -    process.exit = _exit
      -  })
      +  exitHandler()
      +  t.match(
      +    errors[0],
      +    /Error: Exit prior to config file resolving./,
      +    'should exit with config error msg'
      +  )
      +  t.end()
       })
       
      -t.test('it worked', (t) => {
      -  t.plan(2)
      +t.test('timing', (t) => {
      +  npm.config.set('timing', true)
       
      -  config.values.timing = false
      -
      -  const _exit = process.exit
      -  process.exit = (code) => {
      -    process.exit = _exit
      -    t.notOk(code, 'should exit with no code')
      +  t.teardown(() => {
      +    fs.unlinkSync(timingFile)
      +    npm.config.set('timing', false)
      +  })
       
      -    const _info = npmlog.info
      -    npmlog.info = (msg) => {
      -      npmlog.info = _info
      -      t.equal(msg, 'ok', 'should log ok if "it worked"')
      -    }
      +  exitHandler()
      +  const timingData = JSON.parse(fs.readFileSync(timingFile, 'utf8'))
      +  t.match(timingData, { version: '1.0.0', 'config:load:defaults': Number })
      +  t.end()
      +})
       
      -    process.emit('exit', 0)
      -  }
      +t.test('timing - with error', (t) => {
      +  npm.config.set('timing', true)
       
         t.teardown(() => {
      -    process.exit = _exit
      -    config.values.timing = true
      +    fs.unlinkSync(timingFile)
      +    npm.config.set('timing', false)
         })
       
      -  exitHandler()
      +  exitHandler(err)
      +  const timingData = JSON.parse(fs.readFileSync(timingFile, 'utf8'))
      +  t.match(timingData, { version: '1.0.0', 'config:load:defaults': Number })
      +  t.end()
       })
       
       t.test('uses code from errno', (t) => {
         t.plan(1)
       
      -  exitHandler = t.mock('../../../lib/utils/exit-handler.js', mocks)
      -  exitHandler.setNpm(npm)
      -
      -  npmlog.level = 'silent'
      -  const _exit = process.exit
      -  process.exit = (code) => {
      -    t.equal(code, 127, 'should use set errno')
      -  }
      -
      +  process.once('exit', code => {
      +    t.equal(code, 127, 'should set exitCode from errno')
      +  })
         exitHandler(Object.assign(
           new Error('Error with errno'),
           {
             errno: 127,
           }
         ))
      -
      -  t.teardown(() => {
      -    npmlog.level = 'silly'
      -    process.exit = _exit
      -  })
       })
       
      -t.test('uses exitCode as code if using a number', (t) => {
      +t.test('uses code from number', (t) => {
         t.plan(1)
       
      -  exitHandler = t.mock('../../../lib/utils/exit-handler.js', mocks)
      -  exitHandler.setNpm(npm)
      -
      -  npmlog.level = 'silent'
      -  const _exit = process.exit
      -  process.exit = (code) => {
      -    t.equal(code, 404, 'should use code if a number')
      -  }
      -
      +  process.once('exit', code => {
      +    t.equal(code, 404, 'should set exitCode from a number')
      +  })
         exitHandler(Object.assign(
           new Error('Error with code type number'),
           {
             code: 404,
           }
         ))
      -
      -  t.teardown(() => {
      -    npmlog.level = 'silly'
      -    process.exit = _exit
      -  })
       })
       
       t.test('call exitHandler with no error', (t) => {
         t.plan(1)
      -
      -  exitHandler = t.mock('../../../lib/utils/exit-handler.js', mocks)
      -  exitHandler.setNpm(npm)
      -
      -  const _exit = process.exit
      -  process.exit = (code) => {
      -    t.equal(code, undefined, 'should exit with code undefined')
      -  }
      -
      -  t.teardown(() => {
      -    process.exit = _exit
      +  process.once('exit', code => {
      +    t.equal(code, 0, 'should end up with exitCode 0 (default)')
         })
      -
      -  exitHandler()
      -})
      -
      -t.test('exit handler called twice', (t) => {
      -  t.plan(2)
      -
      -  const _verbose = npmlog.verbose
      -  npmlog.verbose = (key, value) => {
      -    t.equal(key, 'stack', 'should log stack in verbose level')
      -    t.match(
      -      value,
      -      /Error: Exit handler called more than once./,
      -      'should have expected error msg'
      -    )
      -    npmlog.verbose = _verbose
      -  }
      -
         exitHandler()
       })
       
       t.test('defaults to log error msg if stack is missing', (t) => {
      -  t.plan(1)
      +  const { npm: unloaded } = mockNpm(t)
       
      +  t.teardown(() => {
      +    exitHandler.setNpm(npm)
      +  })
      +
      +  exitHandler.setNpm(unloaded)
         const noStackErr = Object.assign(
           new Error('Error with no stack'),
           {
      @@ -475,89 +331,63 @@ t.test('defaults to log error msg if stack is missing', (t) => {
         )
         delete noStackErr.stack
       
      -  npm.config.loaded = false
      -
      -  const _error = console.error
      -  console.error = (msg) => {
      -    console.error = _error
      -    npm.config.loaded = true
      -    t.equal(msg, 'Error with no stack', 'should use error msg')
      -  }
      -
         exitHandler(noStackErr)
      +  t.equal(errors[0], 'Error with no stack', 'should use error msg')
      +  t.end()
       })
       
       t.test('exits cleanly when emitting exit event', (t) => {
         t.plan(1)
       
      -  npmlog.level = 'silent'
      -  const _exit = process.exit
      -  process.exit = (code) => {
      -    process.exit = _exit
      -    t.same(code, null, 'should exit with code null')
      -  }
      -
      -  t.teardown(() => {
      -    process.exit = _exit
      -    npmlog.level = 'silly'
      -  })
      -
      +  npm.log.level = 'silent'
         process.emit('exit')
      +  t.match(
      +    npm.log.record.find(r => r.level === 'info'),
      +    { prefix: 'ok', message: '' }
      +  )
      +  t.end()
       })
       
       t.test('do no fancy handling for shellouts', t => {
      -  const { exit } = process
         const { command } = npm
      -  const { log } = npmlog
         const LOG_RECORD = []
      +  npm.command = 'exec'
      +
         t.teardown(() => {
      -    npmlog.log = log
      -    process.exit = exit
           npm.command = command
         })
      -
      -  npmlog.log = function (level, ...args) {
      -    log.call(this, level, ...args)
      -    LOG_RECORD.push(npmlog.record[npmlog.record.length - 1])
      -  }
      -
      -  npm.command = 'exec'
      -
      -  let EXPECT_EXIT = 0
      -  process.exit = code => {
      -    t.equal(code, EXPECT_EXIT, 'got expected exit code')
      -    EXPECT_EXIT = 0
      -  }
         t.beforeEach(() => LOG_RECORD.length = 0)
       
      -  const loudNoises = () => LOG_RECORD
      +  const loudNoises = () => npm.log.record
           .filter(({ level }) => ['warn', 'error'].includes(level))
       
         t.test('shellout with a numeric error code', t => {
      -    EXPECT_EXIT = 5
      +    t.plan(2)
      +    process.once('exit', code => {
      +      t.equal(code, 5, 'got expected exit code')
      +    })
           exitHandler(Object.assign(new Error(), { code: 5 }))
      -    t.equal(EXPECT_EXIT, 0, 'called process.exit')
      -    // should log no warnings or errors, verbose/silly is fine.
           t.strictSame(loudNoises(), [], 'no noisy warnings')
      -    t.end()
         })
       
         t.test('shellout without a numeric error code (something in npm)', t => {
      -    EXPECT_EXIT = 1
      +    t.plan(2)
      +    process.once('exit', code => {
      +      t.equal(code, 1, 'got expected exit code')
      +    })
           exitHandler(Object.assign(new Error(), { code: 'banana stand' }))
      -    t.equal(EXPECT_EXIT, 0, 'called process.exit')
           // should log some warnings and errors, because something weird happened
           t.strictNotSame(loudNoises(), [], 'bring the noise')
           t.end()
         })
       
         t.test('shellout with code=0 (extra weird?)', t => {
      -    EXPECT_EXIT = 1
      +    t.plan(2)
      +    process.once('exit', code => {
      +      t.equal(code, 1, 'got expected exit code')
      +    })
           exitHandler(Object.assign(new Error(), { code: 0 }))
      -    t.equal(EXPECT_EXIT, 0, 'called process.exit')
      -    // should log some warnings and errors, because something weird happened
           t.strictNotSame(loudNoises(), [], 'bring the noise')
      -    t.end()
         })
       
         t.end()
      diff --git a/deps/npm/test/lib/utils/perf.js b/deps/npm/test/lib/utils/perf.js
      deleted file mode 100644
      index 840dcb6e32399b..00000000000000
      --- a/deps/npm/test/lib/utils/perf.js
      +++ /dev/null
      @@ -1,38 +0,0 @@
      -const t = require('tap')
      -const logs = []
      -const npmlog = require('npmlog')
      -npmlog.silly = (...msg) => logs.push(['silly', ...msg])
      -npmlog.timing = (...msg) => logs.push(['timing', ...msg])
      -
      -t.test('time some stuff', t => {
      -  const timings = {}
      -  process.on('timing', (name, value) => {
      -    timings[name] = (timings[name] || 0) + value
      -  })
      -  require('../../../lib/utils/perf.js')
      -  process.emit('time', 'foo')
      -  process.emit('time', 'bar')
      -  setTimeout(() => {
      -    process.emit('timeEnd', 'foo')
      -    process.emit('timeEnd', 'bar')
      -    process.emit('time', 'foo')
      -    setTimeout(() => {
      -      process.emit('timeEnd', 'foo')
      -      process.emit('timeEnd', 'baz')
      -      t.match(logs, [
      -        ['timing', 'foo', /Completed in [0-9]+ms/],
      -        ['timing', 'bar', /Completed in [0-9]+ms/],
      -        ['timing', 'foo', /Completed in [0-9]+ms/],
      -        [
      -          'silly',
      -          'timing',
      -          "Tried to end timer that doesn't exist:",
      -          'baz',
      -        ],
      -      ])
      -      t.match(timings, { foo: Number, bar: Number })
      -      t.equal(timings.foo > timings.bar, true, 'foo should be > bar')
      -      t.end()
      -    }, 100)
      -  }, 100)
      -})
      diff --git a/deps/npm/test/lib/utils/queryable.js b/deps/npm/test/lib/utils/queryable.js
      new file mode 100644
      index 00000000000000..bde3ea66238f28
      --- /dev/null
      +++ b/deps/npm/test/lib/utils/queryable.js
      @@ -0,0 +1,965 @@
      +const { inspect } = require('util')
      +const t = require('tap')
      +const Queryable = require('../../../lib/utils/queryable.js')
      +
      +t.test('retrieve single nested property', async t => {
      +  const fixture = {
      +    foo: {
      +      bar: 'bar',
      +      baz: 'baz',
      +    },
      +    lorem: {
      +      ipsum: 'ipsum',
      +    },
      +  }
      +  const q = new Queryable(fixture)
      +  const query = 'foo.bar'
      +  t.strictSame(q.query(query), { [query]: 'bar' },
      +    'should retrieve property value when querying for dot-sep name')
      +})
      +
      +t.test('query', async t => {
      +  const fixture = {
      +    o: 'o',
      +    single: [
      +      'item',
      +    ],
      +    w: [
      +      'a',
      +      'b',
      +      'c',
      +    ],
      +    list: [
      +      {
      +        name: 'first',
      +      },
      +      {
      +        name: 'second',
      +      },
      +    ],
      +    foo: {
      +      bar: 'bar',
      +      baz: 'baz',
      +    },
      +    lorem: {
      +      ipsum: 'ipsum',
      +      dolor: [
      +        'a',
      +        'b',
      +        'c',
      +        {
      +          sit: [
      +            'amet',
      +          ],
      +        },
      +      ],
      +    },
      +    a: [
      +      [
      +        [
      +          {
      +            b: [
      +              [
      +                {
      +                  c: 'd',
      +                },
      +              ],
      +            ],
      +          },
      +        ],
      +      ],
      +    ],
      +  }
      +  const q = new Queryable(fixture)
      +  t.strictSame(
      +    q.query(['foo.baz', 'lorem.dolor[0]']),
      +    {
      +      'foo.baz': 'baz',
      +      'lorem.dolor[0]': 'a',
      +    },
      +    'should retrieve property values when querying for multiple dot-sep names')
      +  t.strictSame(
      +    q.query('lorem.dolor[3].sit[0]'),
      +    {
      +      'lorem.dolor[3].sit[0]': 'amet',
      +    },
      +    'should retrieve property from nested array items')
      +  t.strictSame(
      +    q.query('a[0][0][0].b[0][0].c'),
      +    {
      +      'a[0][0][0].b[0][0].c': 'd',
      +    },
      +    'should retrieve property from deep nested array items')
      +  t.strictSame(
      +    q.query('o'),
      +    {
      +      o: 'o',
      +    },
      +    'should retrieve single level property value')
      +  t.strictSame(
      +    q.query('list.name'),
      +    {
      +      'list[0].name': 'first',
      +      'list[1].name': 'second',
      +    },
      +    'should automatically expand arrays')
      +  t.strictSame(
      +    q.query(['list.name']),
      +    {
      +      'list[0].name': 'first',
      +      'list[1].name': 'second',
      +    },
      +    'should automatically expand multiple arrays')
      +  t.strictSame(
      +    q.query('w'),
      +    {
      +      w: ['a', 'b', 'c'],
      +    },
      +    'should return arrays')
      +  t.strictSame(
      +    q.query('single'),
      +    {
      +      single: 'item',
      +    },
      +    'should return single item')
      +  t.strictSame(
      +    q.query('missing'),
      +    undefined,
      +    'should return undefined')
      +  t.strictSame(
      +    q.query('missing[bar]'),
      +    undefined,
      +    'should return undefined also')
      +  t.throws(() => q.query('lorem.dolor[]'),
      +    { code: 'EINVALIDSYNTAX' },
      +    'should throw if using empty brackets notation'
      +  )
      +  t.throws(() => q.query('lorem.dolor[].sit[0]'),
      +    { code: 'EINVALIDSYNTAX' },
      +    'should throw if using nested empty brackets notation'
      +  )
      +
      +  const qq = new Queryable({
      +    foo: {
      +      bar: 'bar',
      +    },
      +  })
      +  t.strictSame(
      +    qq.query(''),
      +    {
      +      '': {
      +        foo: {
      +          bar: 'bar',
      +        },
      +      },
      +    },
      +    'should return an object with results in an empty key'
      +  )
      +})
      +
      +t.test('missing key', async t => {
      +  const fixture = {
      +    foo: {
      +      bar: 'bar',
      +    },
      +  }
      +  const q = new Queryable(fixture)
      +  const query = 'foo.missing'
      +  t.equal(q.query(query), undefined,
      +    'should retrieve no results')
      +})
      +
      +t.test('no data object', async t => {
      +  t.throws(
      +    () => new Queryable(),
      +    { code: 'ENOQUERYABLEOBJ' },
      +    'should throw ENOQUERYABLEOBJ error'
      +  )
      +  t.throws(
      +    () => new Queryable(1),
      +    { code: 'ENOQUERYABLEOBJ' },
      +    'should throw ENOQUERYABLEOBJ error'
      +  )
      +})
      +
      +t.test('get values', async t => {
      +  const q = new Queryable({
      +    foo: {
      +      bar: 'bar',
      +    },
      +  })
      +  t.equal(q.get('foo.bar'), 'bar', 'should retrieve value')
      +  t.equal(q.get('missing'), undefined, 'should return undefined')
      +})
      +
      +t.test('set property values', async t => {
      +  const fixture = {
      +    foo: {
      +      bar: 'bar',
      +    },
      +  }
      +  const q = new Queryable(fixture)
      +  q.set('foo.baz', 'baz')
      +  t.strictSame(
      +    q.toJSON(),
      +    {
      +      foo: {
      +        bar: 'bar',
      +        baz: 'baz',
      +      },
      +    },
      +    'should add new property and its assigned value'
      +  )
      +  q.set('foo[lorem.ipsum]', 'LOREM IPSUM')
      +  t.strictSame(
      +    q.toJSON(),
      +    {
      +      foo: {
      +        bar: 'bar',
      +        baz: 'baz',
      +        'lorem.ipsum': 'LOREM IPSUM',
      +      },
      +    },
      +    'should be able to set square brackets props'
      +  )
      +  q.set('a.b[c.d]', 'omg')
      +  t.strictSame(
      +    q.toJSON(),
      +    {
      +      foo: {
      +        bar: 'bar',
      +        baz: 'baz',
      +        'lorem.ipsum': 'LOREM IPSUM',
      +      },
      +      a: {
      +        b: {
      +          'c.d': 'omg',
      +        },
      +      },
      +    },
      +    'should be able to nest square brackets props'
      +  )
      +  q.set('a.b[e][f.g][1.0.0]', 'multiple')
      +  t.strictSame(
      +    q.toJSON(),
      +    {
      +      foo: {
      +        bar: 'bar',
      +        baz: 'baz',
      +        'lorem.ipsum': 'LOREM IPSUM',
      +      },
      +      a: {
      +        b: {
      +          'c.d': 'omg',
      +          e: {
      +            'f.g': {
      +              '1.0.0': 'multiple',
      +            },
      +          },
      +        },
      +      },
      +    },
      +    'should be able to nest multiple square brackets props'
      +  )
      +  q.set('a.b[e][f.g][2.0.0].author.name', 'Ruy Adorno')
      +  t.strictSame(
      +    q.toJSON(),
      +    {
      +      foo: {
      +        bar: 'bar',
      +        baz: 'baz',
      +        'lorem.ipsum': 'LOREM IPSUM',
      +      },
      +      a: {
      +        b: {
      +          'c.d': 'omg',
      +          e: {
      +            'f.g': {
      +              '1.0.0': 'multiple',
      +              '2.0.0': {
      +                author: {
      +                  name: 'Ruy Adorno',
      +                },
      +              },
      +            },
      +          },
      +        },
      +      },
      +    },
      +    'should be able to use dot-sep notation after square bracket props'
      +  )
      +  q.set('a.b[e][f.g][2.0.0].author[url]', 'https://npmjs.com')
      +  t.strictSame(
      +    q.toJSON(),
      +    {
      +      foo: {
      +        bar: 'bar',
      +        baz: 'baz',
      +        'lorem.ipsum': 'LOREM IPSUM',
      +      },
      +      a: {
      +        b: {
      +          'c.d': 'omg',
      +          e: {
      +            'f.g': {
      +              '1.0.0': 'multiple',
      +              '2.0.0': {
      +                author: {
      +                  name: 'Ruy Adorno',
      +                  url: 'https://npmjs.com',
      +                },
      +              },
      +            },
      +          },
      +        },
      +      },
      +    },
      +    'should be able to have multiple, separated, square brackets props'
      +  )
      +  q.set('a.b[e][f.g][2.0.0].author[foo][bar].lorem.ipsum[dolor][sit][amet].omg', 'O_O')
      +  t.strictSame(
      +    q.toJSON(),
      +    {
      +      foo: {
      +        bar: 'bar',
      +        baz: 'baz',
      +        'lorem.ipsum': 'LOREM IPSUM',
      +      },
      +      a: {
      +        b: {
      +          'c.d': 'omg',
      +          e: {
      +            'f.g': {
      +              '1.0.0': 'multiple',
      +              '2.0.0': {
      +                author: {
      +                  name: 'Ruy Adorno',
      +                  url: 'https://npmjs.com',
      +                  foo: {
      +                    bar: {
      +                      lorem: {
      +                        ipsum: {
      +                          dolor: {
      +                            sit: {
      +                              amet: {
      +                                omg: 'O_O',
      +                              },
      +                            },
      +                          },
      +                        },
      +                      },
      +                    },
      +                  },
      +                },
      +              },
      +            },
      +          },
      +        },
      +      },
      +    },
      +    'many many times...'
      +  )
      +  t.throws(
      +    () => q.set('foo.bar.nest', 'should throw'),
      +    { code: 'EOVERRIDEVALUE' },
      +    'should throw if trying to override a literal value with an object'
      +  )
      +  q.set('foo.bar.nest', 'use the force!', { force: true })
      +  t.strictSame(
      +    q.toJSON().foo,
      +    {
      +      bar: {
      +        nest: 'use the force!',
      +      },
      +      baz: 'baz',
      +      'lorem.ipsum': 'LOREM IPSUM',
      +    },
      +    'should allow overriding literal values when using force option'
      +  )
      +
      +  const qq = new Queryable({})
      +  qq.set('foo.bar.baz', 'BAZ')
      +  t.strictSame(
      +    qq.toJSON(),
      +    {
      +      foo: {
      +        bar: {
      +          baz: 'BAZ',
      +        },
      +      },
      +    },
      +    'should add new props to qq object'
      +  )
      +  qq.set('foo.bar.bario', 'bario')
      +  t.strictSame(
      +    qq.toJSON(),
      +    {
      +      foo: {
      +        bar: {
      +          baz: 'BAZ',
      +          bario: 'bario',
      +        },
      +      },
      +    },
      +    'should add new props to a previously existing object'
      +  )
      +  qq.set('lorem', 'lorem')
      +  t.strictSame(
      +    qq.toJSON(),
      +    {
      +      foo: {
      +        bar: {
      +          baz: 'BAZ',
      +          bario: 'bario',
      +        },
      +      },
      +      lorem: 'lorem',
      +    },
      +    'should append new props added to object later'
      +  )
      +  qq.set('foo.bar[foo.bar]', 'foo.bar.with.dots')
      +  t.strictSame(
      +    qq.toJSON(),
      +    {
      +      foo: {
      +        bar: {
      +          'foo.bar': 'foo.bar.with.dots',
      +          baz: 'BAZ',
      +          bario: 'bario',
      +        },
      +      },
      +      lorem: 'lorem',
      +    },
      +    'should append new props added to object later'
      +  )
      +})
      +
      +t.test('set arrays', async t => {
      +  const q = new Queryable({})
      +
      +  q.set('foo[1]', 'b')
      +  t.strictSame(
      +    q.toJSON(),
      +    {
      +      foo: [
      +        undefined,
      +        'b',
      +      ],
      +    },
      +    'should be able to set items in an array using index references'
      +  )
      +
      +  q.set('foo[0]', 'a')
      +  t.strictSame(
      +    q.toJSON(),
      +    {
      +      foo: [
      +        'a',
      +        'b',
      +      ],
      +    },
      +    'should be able to set a previously missing item to an array'
      +  )
      +
      +  q.set('foo[2]', 'c')
      +  t.strictSame(
      +    q.toJSON(),
      +    {
      +      foo: [
      +        'a',
      +        'b',
      +        'c',
      +      ],
      +    },
      +    'should be able to append more items to an array'
      +  )
      +
      +  q.set('foo[2]', 'C')
      +  t.strictSame(
      +    q.toJSON(),
      +    {
      +      foo: [
      +        'a',
      +        'b',
      +        'C',
      +      ],
      +    },
      +    'should be able to override array items'
      +  )
      +
      +  t.throws(
      +    () => q.set('foo[2].bar', 'bar'),
      +    { code: 'EOVERRIDEVALUE' },
      +    'should throw if trying to override an array literal item with an obj'
      +  )
      +
      +  q.set('foo[2].bar', 'bar', { force: true })
      +  t.strictSame(
      +    q.toJSON(),
      +    {
      +      foo: [
      +        'a',
      +        'b',
      +        { bar: 'bar' },
      +      ],
      +    },
      +    'should be able to override an array string item with an obj'
      +  )
      +
      +  q.set('foo[3].foo', 'surprise surprise, another foo')
      +  t.strictSame(
      +    q.toJSON(),
      +    {
      +      foo: [
      +        'a',
      +        'b',
      +        { bar: 'bar' },
      +        {
      +          foo: 'surprise surprise, another foo',
      +        },
      +      ],
      +    },
      +    'should be able to append more items to an array'
      +  )
      +
      +  q.set('foo[3].foo', 'FOO')
      +  t.strictSame(
      +    q.toJSON(),
      +    {
      +      foo: [
      +        'a',
      +        'b',
      +        { bar: 'bar' },
      +        {
      +          foo: 'FOO',
      +        },
      +      ],
      +    },
      +    'should be able to override property of an obj inside an array'
      +  )
      +
      +  const qq = new Queryable({})
      +  qq.set('foo[0].bar[1].baz.bario[0][0][0]', 'something')
      +  t.strictSame(
      +    qq.toJSON(),
      +    {
      +      foo: [
      +        {
      +          bar: [
      +            undefined,
      +            {
      +              baz: {
      +                bario: [[['something']]],
      +              },
      +            },
      +          ],
      +        },
      +      ],
      +    },
      +    'should append as many arrays as necessary'
      +  )
      +  qq.set('foo[0].bar[1].baz.bario[0][1][0]', 'something else')
      +  t.strictSame(
      +    qq.toJSON(),
      +    {
      +      foo: [
      +        {
      +          bar: [
      +            undefined,
      +            {
      +              baz: {
      +                bario: [[
      +                  ['something'],
      +                  ['something else'],
      +                ]],
      +              },
      +            },
      +          ],
      +        },
      +      ],
      +    },
      +    'should append as many arrays as necessary'
      +  )
      +  qq.set('foo', null)
      +  t.strictSame(
      +    qq.toJSON(),
      +    {
      +      foo: null,
      +    },
      +    'should be able to set a value to null'
      +  )
      +  qq.set('foo.bar', 'bar')
      +  t.strictSame(
      +    qq.toJSON(),
      +    {
      +      foo: {
      +        bar: 'bar',
      +      },
      +    },
      +    'should be able to replace a null value with properties'
      +  )
      +
      +  const qqq = new Queryable({
      +    arr: [
      +      'a',
      +      'b',
      +    ],
      +  })
      +
      +  qqq.set('arr[]', 'c')
      +  t.strictSame(
      +    qqq.toJSON(),
      +    {
      +      arr: [
      +        'a',
      +        'b',
      +        'c',
      +      ],
      +    },
      +    'should be able to append to array using empty bracket notation'
      +  )
      +
      +  qqq.set('arr[].foo', 'foo')
      +  t.strictSame(
      +    qqq.toJSON(),
      +    {
      +      arr: [
      +        'a',
      +        'b',
      +        'c',
      +        {
      +          foo: 'foo',
      +        },
      +      ],
      +    },
      +    'should be able to append objects to array using empty bracket notation'
      +  )
      +
      +  qqq.set('arr[].bar.name', 'BAR')
      +  t.strictSame(
      +    qqq.toJSON(),
      +    {
      +      arr: [
      +        'a',
      +        'b',
      +        'c',
      +        {
      +          foo: 'foo',
      +        },
      +        {
      +          bar: {
      +            name: 'BAR',
      +          },
      +        },
      +      ],
      +    },
      +    'should be able to append more objects to array using empty brackets'
      +  )
      +
      +  qqq.set('foo.bar.baz[].lorem.ipsum', 'something')
      +  t.strictSame(
      +    qqq.toJSON(),
      +    {
      +      arr: [
      +        'a',
      +        'b',
      +        'c',
      +        {
      +          foo: 'foo',
      +        },
      +        {
      +          bar: {
      +            name: 'BAR',
      +          },
      +        },
      +      ],
      +      foo: {
      +        bar: {
      +          baz: [
      +            {
      +              lorem: {
      +                ipsum: 'something',
      +              },
      +            },
      +          ],
      +        },
      +      },
      +    },
      +    'should be able to append to array using empty brackets in nested objs'
      +  )
      +
      +  qqq.set('foo.bar.baz[].lorem.array[]', 'new item')
      +  t.strictSame(
      +    qqq.toJSON(),
      +    {
      +      arr: [
      +        'a',
      +        'b',
      +        'c',
      +        {
      +          foo: 'foo',
      +        },
      +        {
      +          bar: {
      +            name: 'BAR',
      +          },
      +        },
      +      ],
      +      foo: {
      +        bar: {
      +          baz: [
      +            {
      +              lorem: {
      +                ipsum: 'something',
      +              },
      +            },
      +            {
      +              lorem: {
      +                array: [
      +                  'new item',
      +                ],
      +              },
      +            },
      +          ],
      +        },
      +      },
      +    },
      +    'should be able to append to array using empty brackets in nested objs'
      +  )
      +
      +  const qqqq = new Queryable({
      +    arr: [
      +      'a',
      +      'b',
      +    ],
      +  })
      +  t.throws(
      +    () => qqqq.set('arr.foo', 'foo'),
      +    { code: 'ENOADDPROP' },
      +    'should throw an override error'
      +  )
      +
      +  qqqq.set('arr.foo', 'foo', { force: true })
      +  t.strictSame(
      +    qqqq.toJSON(),
      +    {
      +      arr: {
      +        0: 'a',
      +        1: 'b',
      +        foo: 'foo',
      +      },
      +    },
      +    'should be able to override arrays with objects when using force=true'
      +  )
      +
      +  qqqq.set('bar[]', 'item', { force: true })
      +  t.strictSame(
      +    qqqq.toJSON(),
      +    {
      +      arr: {
      +        0: 'a',
      +        1: 'b',
      +        foo: 'foo',
      +      },
      +      bar: [
      +        'item',
      +      ],
      +    },
      +    'should be able to create new array with item when using force=true'
      +  )
      +
      +  qqqq.set('bar[]', 'something else', { force: true })
      +  t.strictSame(
      +    qqqq.toJSON(),
      +    {
      +      arr: {
      +        0: 'a',
      +        1: 'b',
      +        foo: 'foo',
      +      },
      +      bar: [
      +        'item',
      +        'something else',
      +      ],
      +    },
      +    'should be able to append items to arrays when using force=true'
      +  )
      +
      +  const qqqqq = new Queryable({
      +    arr: [
      +      null,
      +    ],
      +  })
      +  qqqqq.set('arr[]', 'b')
      +  t.strictSame(
      +    qqqqq.toJSON(),
      +    {
      +      arr: [
      +        null,
      +        'b',
      +      ],
      +    },
      +    'should be able to append items with empty items'
      +  )
      +  qqqqq.set('arr[0]', 'a')
      +  t.strictSame(
      +    qqqqq.toJSON(),
      +    {
      +      arr: [
      +        'a',
      +        'b',
      +      ],
      +    },
      +    'should be able to replace empty items in an array'
      +  )
      +  qqqqq.set('lorem.ipsum', 3)
      +  t.strictSame(
      +    qqqqq.toJSON(),
      +    {
      +      arr: [
      +        'a',
      +        'b',
      +      ],
      +      lorem: {
      +        ipsum: 3,
      +      },
      +    },
      +    'should be able to replace empty items in an array'
      +  )
      +  t.throws(
      +    () => qqqqq.set('lorem[]', 4),
      +    { code: 'ENOAPPEND' },
      +    'should throw error if using empty square bracket in an non-array item'
      +  )
      +  qqqqq.set('lorem[0]', 3)
      +  t.strictSame(
      +    qqqqq.toJSON(),
      +    {
      +      arr: [
      +        'a',
      +        'b',
      +      ],
      +      lorem: {
      +        0: 3,
      +        ipsum: 3,
      +      },
      +    },
      +    'should be able add indexes as props when finding an object'
      +  )
      +  qqqqq.set('lorem.1', 3)
      +  t.strictSame(
      +    qqqqq.toJSON(),
      +    {
      +      arr: [
      +        'a',
      +        'b',
      +      ],
      +      lorem: {
      +        0: 3,
      +        1: 3,
      +        ipsum: 3,
      +      },
      +    },
      +    'should be able add numeric props to an obj'
      +  )
      +})
      +
      +t.test('delete values', async t => {
      +  const q = new Queryable({
      +    foo: {
      +      bar: {
      +        lorem: 'lorem',
      +      },
      +    },
      +  })
      +  q.delete('foo.bar.lorem')
      +  t.strictSame(
      +    q.toJSON(),
      +    {
      +      foo: {
      +        bar: {},
      +      },
      +    },
      +    'should delete queried item'
      +  )
      +  q.delete('foo')
      +  t.strictSame(
      +    q.toJSON(),
      +    {},
      +    'should delete nested items'
      +  )
      +  q.set('foo.a.b.c[0]', 'value')
      +  q.delete('foo.a.b.c[0]')
      +  t.strictSame(
      +    q.toJSON(),
      +    {
      +      foo: {
      +        a: {
      +          b: {
      +            c: [],
      +          },
      +        },
      +      },
      +    },
      +    'should delete array item'
      +  )
      +  // creates an array that has an implicit empty first item
      +  q.set('foo.a.b.c[1][0].foo.bar[0][0]', 'value')
      +  q.delete('foo.a.b.c[1]')
      +  t.strictSame(
      +    q.toJSON(),
      +    {
      +      foo: {
      +        a: {
      +          b: {
      +            c: [null],
      +          },
      +        },
      +      },
      +    },
      +    'should delete array item'
      +  )
      +})
      +
      +t.test('logger', async t => {
      +  const q = new Queryable({})
      +  q.set('foo.bar[0].baz', 'baz')
      +  t.strictSame(
      +    inspect(q, { depth: 10 }),
      +    inspect({
      +      foo: {
      +        bar: [
      +          {
      +            baz: 'baz',
      +          },
      +        ],
      +      },
      +    }, { depth: 10 }),
      +    'should retrieve expected data'
      +  )
      +})
      +
      +t.test('bracket lovers', async t => {
      +  const q = new Queryable({})
      +  q.set('[iLoveBrackets]', 'seriously?')
      +  t.strictSame(
      +    q.toJSON(),
      +    {
      +      '[iLoveBrackets]': 'seriously?',
      +    },
      +    'should be able to set top-level props using square brackets notation'
      +  )
      +
      +  t.equal(q.get('[iLoveBrackets]'), 'seriously?',
      +    'should bypass square bracket in top-level properties')
      +
      +  q.set('[0]', '-.-')
      +  t.strictSame(
      +    q.toJSON(),
      +    {
      +      '[iLoveBrackets]': 'seriously?',
      +      '[0]': '-.-',
      +    },
      +    'any top-level item can not be parsed with square bracket notation'
      +  )
      +})