diff --git a/deps/npm/AUTHORS b/deps/npm/AUTHORS
index a257559bbf593f..2b3e48e7651636 100644
--- a/deps/npm/AUTHORS
+++ b/deps/npm/AUTHORS
@@ -770,3 +770,5 @@ Yash Singh
Danielle Church
Seth Thomas
Andreas
+Felipe Santos
+Luigi Pinca
diff --git a/deps/npm/CHANGELOG.md b/deps/npm/CHANGELOG.md
index bbc9785efcd46b..ce79e9368a6e58 100644
--- a/deps/npm/CHANGELOG.md
+++ b/deps/npm/CHANGELOG.md
@@ -1,3 +1,125 @@
+## v7.11.2 (2021-04-29)
+
+### BUG FIXES
+
+* [`c371f183e`](https://github.com/npm/cli/commit/c371f183ebe833c2439e98b679f14e7a59f22c34)
+ [#3137](https://github.com/npm/cli/issues/3137)
+ [#3140](https://github.com/npm/cli/issues/3140)
+ fix(ls): do not warn on missing optional deps
+ ([@isaacs](https://github.com/isaacs))
+* [`861f606c7`](https://github.com/npm/cli/commit/861f606c7609d177c644814a171581afbb72f6db)
+ [#3156](https://github.com/npm/cli/issues/3156)
+ fix(build): make prune rule work on case-sensitive file systems
+ ([@lpinca](https://github.com/lpinca))
+
+### DEPENDENCIES
+
+* [`fb79d89a0`](https://github.com/npm/cli/commit/fb79d89a07ef03e76633db275463f701d3dae42f)
+ `tap@15.0.6`
+* [`ce3820043`](https://github.com/npm/cli/commit/ce38200437e9ed527df973794909b2699909bc9b)
+ `@npmcli/arborist@2.4.1`
+ * fix: prevent and eliminate unnecessary duplicates
+ * fix: support resolvable partial intersecting peerSets
+
+### DOCUMENTATION
+
+* [`e479f1dac`](https://github.com/npm/cli/commit/e479f1dac9a7639304d20116583034861635b2b1)
+ [#3146](https://github.com/npm/cli/issues/3146)
+ mention `directories.bin` in `bin`
+ ([@felipecrs](https://github.com/felipecrs))
+
+## v7.11.1 (2021-04-23)
+
+### DEPENDENCIES
+
+* [`7925cca24`](https://github.com/npm/cli/commit/7925cca24543d9e1a8297844b3e53e11057643ef)
+ `pacote@11.3.3`:
+ * fix(registry): normalize manfest
+* [`b61eac693`](https://github.com/npm/cli/commit/b61eac693df82c52b955e6c18ec4dcf4cedea8a3)
+ [#3130](https://github.com/npm/cli/issues/3130)
+ `@npmcli/config@2.2.0`
+* [`c74e67fc6`](https://github.com/npm/cli/commit/c74e67fc6572bb001d74c7486c05d211a0e03de8)
+ [#3130](https://github.com/npm/cli/issues/3130)
+ `npm-registry-fetch@10.1.1`
+
+### DOCUMENTATION
+
+* [`efdd7dd44`](https://github.com/npm/cli/commit/efdd7dd4427a0ee856c18aab1df2d3d30a307997)
+ Remove unused and incorrectly documented `--always-auth` config definition
+ ([@isaacs](https://github.com/isaacs))
+
+## v7.11.0 (2021-04-22)
+
+### FEATURES
+
+* [`4c1f16d2c`](https://github.com/npm/cli/commit/4c1f16d2c29a7a56c19b97f2820e6305a6075083)
+ [#3095](https://github.com/npm/cli/issues/3095)
+ feat(init): add workspaces support
+ ([@ruyadorno](https://github.com/ruyadorno))
+
+### BUG FIXES
+
+* [`42ca59eee`](https://github.com/npm/cli/commit/42ca59eeedd3e402aa1c606941f7f52864e6039b)
+ [#3086](https://github.com/npm/cli/issues/3086)
+ fix(ls): do not exit with error when all problems are extraneous deps
+ ([@nlf](https://github.com/nlf))
+* [`2aecec591`](https://github.com/npm/cli/commit/2aecec591df6866e27d0b17dc49cef8f7d738d77)
+ [#2724](https://github.com/npm/cli/issues/2724)
+ [#3119](https://github.com/npm/cli/issues/3119)
+ fix(ls): make --long work when missing deps
+ ([@ruyadorno](https://github.com/ruyadorno))
+* [`42e0587a9`](https://github.com/npm/cli/commit/42e0587a9ea6940a5d5be5903370ad1113feef21)
+ [#3115](https://github.com/npm/cli/issues/3115)
+ fix(pack): refuse to pack invalid packument
+ ([@wraithgar](https://github.com/wraithgar))
+* [`1c4eff7b5`](https://github.com/npm/cli/commit/1c4eff7b513b8e84876818ede014d3ab19d203c6)
+ [#3126](https://github.com/npm/cli/issues/3126)
+ fix(logout): use isBasicAuth attribute
+ ([@wraithgar](https://github.com/wraithgar))
+### DOCUMENTATION
+
+
+* [`c93f1c39e`](https://github.com/npm/cli/commit/c93f1c39e326feff0857712a10ef6183fbafe1ab)
+ [#3101](https://github.com/npm/cli/issues/3101)
+ chore(docs): update view docs
+ ([@wraithgar](https://github.com/wraithgar))
+* [`c4ff4bc11`](https://github.com/npm/cli/commit/c4ff4bc113c3a5b6ee5d74ab0b1adee95169ed32)
+ [npm/statusboard#313](https://github.com/npm/statusboard/issues/313)
+ [#3109](https://github.com/npm/cli/issues/3109)
+ fix(usage): fix refs to ws shorthand
+ ([@ruyadorno](https://github.com/ruyadorno))
+
+
+### DEPENDENCIES
+
+* [`83166ebcc`](https://github.com/npm/cli/commit/83166ebcc4ba5e3bf215f08151437d96637f4f33)
+ `npm-registry-fetch@10.1.0`
+ * feat(auth): set isBasicAuth
+* [`e02bda6da`](https://github.com/npm/cli/commit/e02bda6da68b8e8f490bf270cb5d6adec81685ea)
+ `npm-registry-fetch@10.0.0`
+ * feat(auth) load/send based on URI, not registry
+* [`a0382deba`](https://github.com/npm/cli/commit/a0382deba346b09834e75db89e1fd4527f1f07dd)
+ `@npmcli/run-script@1.8.5`
+ * fix: windows ComSpec env variable name
+* [`7f82ef5a8`](https://github.com/npm/cli/commit/7f82ef5a84d70e28983ed43ba1d8aced0fb4ba45)
+ `pacote@11.3.2`
+* [`35e49b94f`](https://github.com/npm/cli/commit/35e49b94fba478a63df6cc9b62816eafe5f1fbdd)
+ `@npmcli/arborist@2.4.0`
+* [`95faf8ce6`](https://github.com/npm/cli/commit/95faf8ce6c007082a02c160977da194c08ee9d82)
+ `libnpmaccess@4.0.2`
+* [`17fffc0e4`](https://github.com/npm/cli/commit/17fffc0e42b2a9e7b84691093e45ba511906cbfa)
+ `libnpmhook@6.0.2`
+* [`1b5a213aa`](https://github.com/npm/cli/commit/1b5a213aaf39652661ba72ba2e8751f049b170fb)
+ `libnpmorg@2.0.2`
+* [`9f83e6484`](https://github.com/npm/cli/commit/9f83e6484aa163d066f318df42ec89c8234b614e)
+ `libnpmpublish@4.0.1`
+* [`251f788c5`](https://github.com/npm/cli/commit/251f788c554a198ab42682453fa5504f8abe93fe)
+ `libnpmsearch@3.1.1`
+* [`35873a989`](https://github.com/npm/cli/commit/35873a989fe67041ddcf30a0a278ed77ace5ee3c)
+ `libnpmteam@2.0.3`
+* [`23e12b4d8`](https://github.com/npm/cli/commit/23e12b4d8f63d765a48036e7bb08f53319c73304)
+ `npm-profile@5.0.3`
+
## v7.10.0 (2021-04-15)
### FEATURES
diff --git a/deps/npm/docs/content/commands/npm-adduser.md b/deps/npm/docs/content/commands/npm-adduser.md
index d0ddd68c2529a4..9ad4c27c6d8e54 100644
--- a/deps/npm/docs/content/commands/npm-adduser.md
+++ b/deps/npm/docs/content/commands/npm-adduser.md
@@ -7,7 +7,7 @@ description: Add a registry user account
### Synopsis
```bash
-npm adduser [--registry=url] [--scope=@orgname] [--always-auth] [--auth-type=legacy]
+npm adduser [--registry=url] [--scope=@orgname] [--auth-type=legacy]
aliases: login, add-user
```
@@ -58,23 +58,6 @@ npm adduser --registry=http://myregistry.example.com --scope=@myco
This will set a registry for the given scope and login or create a user for
that registry at the same time.
-#### always-auth
-
-Default: false
-
-If specified, save configuration indicating that all requests to the given
-registry should include authorization information. Useful for private
-registries. Can be used with `--registry` and / or `--scope`, e.g.
-
-```bash
-npm adduser --registry=http://private-registry.example.com --always-auth
-```
-
-This will ensure that all requests to that registry (including for tarballs)
-include an authorization header. This setting may be necessary for use with
-private registries where metadata and package tarballs are stored on hosts with
-different hostnames. See `always-auth` in [`config`](/using-npm/config) for more details on always-auth. Registry-specific configuration of `always-auth` takes precedence over any global configuration.
-
#### auth-type
* Default: `'legacy'`
diff --git a/deps/npm/docs/content/commands/npm-exec.md b/deps/npm/docs/content/commands/npm-exec.md
index 88b98e3bce466a..2364da32c76de9 100644
--- a/deps/npm/docs/content/commands/npm-exec.md
+++ b/deps/npm/docs/content/commands/npm-exec.md
@@ -11,7 +11,7 @@ npm exec -- [@] [args...]
npm exec --package=[@] -- [args...]
npm exec -c ' [args...]'
npm exec --package=foo -c ' [args...]'
-npm exec [-ws] [-w [@] [args...]
npx -p [@] [args...]
@@ -184,7 +184,7 @@ in this example we're using **eslint** to lint any js file found within each
workspace folder:
```
-npm exec -ws -- eslint ./*.js
+npm exec --ws -- eslint ./*.js
```
#### Filtering workspaces
@@ -275,7 +275,7 @@ children workspaces)
#### workspaces
-* Alias: `-ws`
+* Alias: `--ws`
* Type: Boolean
* Default: `false`
@@ -291,3 +291,4 @@ project.
* [npm restart](/commands/npm-restart)
* [npm stop](/commands/npm-stop)
* [npm config](/commands/npm-config)
+* [npm workspaces](/using-npm/workspaces)
diff --git a/deps/npm/docs/content/commands/npm-init.md b/deps/npm/docs/content/commands/npm-init.md
index 4b0b8c4c43e73e..8288034a3f19a2 100644
--- a/deps/npm/docs/content/commands/npm-init.md
+++ b/deps/npm/docs/content/commands/npm-init.md
@@ -8,8 +8,9 @@ description: Create a package.json file
```bash
npm init [--force|-f|--yes|-y|--scope]
-npm init <@scope> (same as `npx <@scope>/create`)
-npm init [<@scope>/] (same as `npx [<@scope>/]create-`)
+npm init <@scope> (same as `npm exec <@scope>/create`)
+npm init [<@scope>/] (same as `npm exec [<@scope>/]create-`)
+npm init [-w ] [args...]
```
### Description
@@ -18,19 +19,16 @@ npm init [<@scope>/] (same as `npx [<@scope>/]create-`)
package.
`initializer` in this case is an npm package named `create-`,
-which will be installed by [`npx`](https://npm.im/npx), and then have its
+which will be installed by [`npm-exec`](/commands/npm-exec), and then have its
main bin executed -- presumably creating or updating `package.json` and
running any other initialization-related operations.
-The init command is transformed to a corresponding `npx` operation as
+The init command is transformed to a corresponding `npm exec` operation as
follows:
-* `npm init foo` -> `npx create-foo`
-* `npm init @usr/foo` -> `npx @usr/create-foo`
-* `npm init @usr` -> `npx @usr/create`
-
-Any additional options will be passed directly to the command, so `npm init
-foo -- --hello` will map to `npx create-foo --hello`.
+* `npm init foo` -> `npm exec create-foo`
+* `npm init @usr/foo` -> `npm exec @usr/create-foo`
+* `npm init @usr` -> `npm exec @usr/create`
If the initializer is omitted (by just calling `npm init`), init will fall
back to legacy init behavior. It will ask you a bunch of questions, and
@@ -40,6 +38,18 @@ strictly additive, so it will keep any fields and values that were already
set. You can also use `-y`/`--yes` to skip the questionnaire altogether. If
you pass `--scope`, it will create a scoped package.
+#### Forwarding additional options
+
+Any additional options will be passed directly to the command, so `npm init
+foo -- --hello` will map to `npm exec -- create-foo --hello`.
+
+To better illustrate how options are forwarded, here's a more evolved
+example showing options passed to both the **npm cli** and a create package,
+both following commands are equivalent:
+
+- `npm init foo -y --registry= -- --hello -a`
+- `npm exec -y --registry= -- create-foo --hello -a`
+
### Examples
Create a new React-based project using
@@ -71,6 +81,68 @@ Generate it without having it ask any questions:
$ npm init -y
```
+### Workspaces support
+
+It's possible to create a new workspace within your project by using the
+`workspace` config option. When using `npm init -w ` the cli will
+create the folders and boilerplate expected while also adding a reference
+to your project `package.json` `"workspaces": []` property in order to make
+sure that new generated **workspace** is properly set up as such.
+
+Given a project with no workspaces, e.g:
+
+```
+.
++-- package.json
+```
+
+You may generate a new workspace using the legacy init:
+
+```bash
+$ npm init -w packages/a
+```
+
+That will generate a new folder and `package.json` file, while also updating
+your top-level `package.json` to add the reference to this new workspace:
+
+```
+.
++-- package.json
+`-- packages
+ `-- a
+ `-- package.json
+```
+
+The workspaces init also supports the `npm init -w `
+syntax, following the same set of rules explained earlier in the initial
+**Description** section of this page. Similar to the previous example of
+creating a new React-based project using
+[`create-react-app`](https://npm.im/create-react-app), the following syntax
+will make sure to create the new react app as a nested **workspace** within your
+project and configure your `package.json` to recognize it as such:
+
+```bash
+npm init -w packages/my-react-app react-app .
+```
+
+This will make sure to generate your react app as expected, one important
+consideration to have in mind is that `npm exec` is going to be run in the
+context of the newly created folder for that workspace, and that's the reason
+why in this example the initializer uses the initializer name followed with a
+dot to represent the current directory in that context, e.g: `react-app .`:
+
+```
+.
++-- package.json
+`-- packages
+ +-- a
+ | `-- package.json
+ `-- my-react-app
+ +-- README
+ +-- package.json
+ `-- ...
+```
+
### A note on caching
The npm cli utilizes its internal package cache when using the package
@@ -93,6 +165,33 @@ requested from the server. To force full offline mode, use `offline`.
Forces full offline mode. Any packages not locally cached will result in
an error.
+#### workspace
+
+* Alias: `-w`
+* Type: Array
+* Default: `[]`
+
+Enable running `npm init` in the context of workspaces, creating any missing
+folders, generating files and adding/updating the `"workspaces"` property of
+the project `package.json`.
+
+the provided names or paths provided.
+
+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
+children workspaces)
+
+#### workspaces
+
+* Alias: `-ws`
+* Type: Boolean
+* Default: `false`
+
+Run `npm init` in the context of all configured workspaces for the
+current project.
+
### See Also
* [init-package-json module](http://npm.im/init-package-json)
@@ -100,3 +199,4 @@ an error.
* [npm version](/commands/npm-version)
* [npm scope](/using-npm/scope)
* [npm exec](/commands/npm-exec)
+* [npm workspaces](/using-npm/workspaces)
diff --git a/deps/npm/docs/content/commands/npm-run-script.md b/deps/npm/docs/content/commands/npm-run-script.md
index 076dfd7addcc35..6786312e0bf84a 100644
--- a/deps/npm/docs/content/commands/npm-run-script.md
+++ b/deps/npm/docs/content/commands/npm-run-script.md
@@ -189,7 +189,7 @@ children workspaces)
#### workspaces
-* Alias: `-ws`
+* Alias: `--ws`
* Type: Boolean
* Default: `false`
@@ -204,3 +204,4 @@ project.
* [npm restart](/commands/npm-restart)
* [npm stop](/commands/npm-stop)
* [npm config](/commands/npm-config)
+* [npm workspaces](/using-npm/workspaces)
diff --git a/deps/npm/docs/content/commands/npm-view.md b/deps/npm/docs/content/commands/npm-view.md
index 90d5218856c8e9..8f7e886ed192a4 100644
--- a/deps/npm/docs/content/commands/npm-view.md
+++ b/deps/npm/docs/content/commands/npm-view.md
@@ -94,6 +94,25 @@ this:
npm view connect versions
```
+### Configuration
+
+#### json
+
+Show information in JSON format. See [`Output`](#output) below.
+
+#### workspaces
+
+Enables workspaces context while searching the `package.json` in the
+current folder. Information about packages named in each workspace will
+be viewed.
+
+#### workspace
+
+Enables workspaces context and limits results to only those specified by
+this config item. Only the information about packages named in the
+workspaces given here will be viewed.
+
+
### Output
If only a single string field for a single version is output, then it
diff --git a/deps/npm/docs/content/configuring-npm/package-json.md b/deps/npm/docs/content/configuring-npm/package-json.md
index f3a186f436e029..f5519f62bb32ef 100644
--- a/deps/npm/docs/content/configuring-npm/package-json.md
+++ b/deps/npm/docs/content/configuring-npm/package-json.md
@@ -386,6 +386,8 @@ Please make sure that your file(s) referenced in `bin` starts with
`#!/usr/bin/env node`, otherwise the scripts are started without the node
executable!
+Note that you can also set the executable files using [directories.bin](#directoriesbin).
+
### 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 b2e8baf014977d..76ac4192f1351e 100644
--- a/deps/npm/docs/content/using-npm/config.md
+++ b/deps/npm/docs/content/using-npm/config.md
@@ -165,14 +165,6 @@ upon by the current project.
Prevents throwing an error when `npm version` is used to set the new version
to the same value as the current version.
-#### `always-auth`
-
-* Default: false
-* Type: Boolean
-
-Force npm to always require authentication when accessing the registry, even
-for `GET` requests.
-
#### `audit`
* Default: true
@@ -1087,7 +1079,8 @@ installation of packages specified according to the pattern
* Default: '/bin/sh' on POSIX systems, 'cmd.exe' on Windows
* Type: null or String
-The shell to use for scripts run with the `npm run` command.
+The shell to use for scripts run with the `npm exec`, `npm run` and `npm
+init ` commands.
#### `searchexclude`
diff --git a/deps/npm/docs/output/commands/npm-adduser.html b/deps/npm/docs/output/commands/npm-adduser.html
index a079dfed71e291..494844708146c8 100644
--- a/deps/npm/docs/output/commands/npm-adduser.html
+++ b/deps/npm/docs/output/commands/npm-adduser.html
@@ -141,11 +141,11 @@ npm-adduser
Synopsis
-
npm adduser [--registry=url] [--scope=@orgname] [--always-auth] [--auth-type=legacy]
+npm adduser [--registry=url] [--scope=@orgname] [--auth-type=legacy]
aliases: login, add-user
@@ -177,17 +177,6 @@ scope
This will set a registry for the given scope and login or create a user for
that registry at the same time.
-
always-auth
-
Default: false
-
If specified, save configuration indicating that all requests to the given
-registry should include authorization information. Useful for private
-registries. Can be used with --registry and / or --scope, e.g.
-
npm adduser --registry=http://private-registry.example.com --always-auth
-
-
This will ensure that all requests to that registry (including for tarballs)
-include an authorization header. This setting may be necessary for use with
-private registries where metadata and package tarballs are stored on hosts with
-different hostnames. See always-auth in config for more details on always-auth. Registry-specific configuration of always-auth takes precedence over any global configuration.
auth-type
- Default:
'legacy'
diff --git a/deps/npm/docs/output/commands/npm-exec.html b/deps/npm/docs/output/commands/npm-exec.html
index f8f882a2c54a48..528f5a571cfef4 100644
--- a/deps/npm/docs/output/commands/npm-exec.html
+++ b/deps/npm/docs/output/commands/npm-exec.html
@@ -149,7 +149,7 @@ Table of contents
npm exec --package=<pkg>[@<version>] -- <cmd> [args...]
npm exec -c '<cmd> [args...]'
npm exec --package=foo -c '<cmd> [args...]'
-npm exec [-ws] [-w <workspace-name] [args...]
+npm exec [--ws] [-w <workspace-name] [args...]
npx <pkg>[@<specifier>] [args...]
npx -p <pkg>[@<specifier>] <cmd> [args...]
@@ -276,7 +276,7 @@ Workspaces support
the configured workspaces when using the workspaces configuration options,
in this example we’re using eslint to lint any js file found within each
workspace folder:
-
npm exec -ws -- eslint ./*.js
+npm exec --ws -- eslint ./*.js
Filtering workspaces
It’s also possible to execute a command in a single workspace using the
@@ -348,7 +348,7 @@
workspace
workspaces
-- Alias:
-ws
+- Alias:
--ws
- Type: Boolean
- Default:
false
@@ -363,6 +363,7 @@ See Also
npm restart
npm stop
npm config
+npm workspaces
diff --git a/deps/npm/docs/output/commands/npm-init.html b/deps/npm/docs/output/commands/npm-init.html
index 62dc20093b2e94..1aa0408baff8f5 100644
--- a/deps/npm/docs/output/commands/npm-init.html
+++ b/deps/npm/docs/output/commands/npm-init.html
@@ -141,29 +141,29 @@ npm-init
Synopsis
npm init [--force|-f|--yes|-y|--scope]
-npm init <@scope> (same as `npx <@scope>/create`)
-npm init [<@scope>/]<name> (same as `npx [<@scope>/]create-<name>`)
+npm init <@scope> (same as `npm exec <@scope>/create`)
+npm init [<@scope>/]<name> (same as `npm exec [<@scope>/]create-<name>`)
+npm init [-w <dir>] [args...]
Description
npm init <initializer> can be used to set up a new or existing npm
package.
initializer in this case is an npm package named create-<initializer>,
-which will be installed by npx, and then have its
+which will be installed by npm-exec, and then have its
main bin executed – presumably creating or updating package.json and
running any other initialization-related operations.
-
The init command is transformed to a corresponding npx operation as
+
The init command is transformed to a corresponding npm exec operation as
follows:
-npm init foo -> npx create-foo
-npm init @usr/foo -> npx @usr/create-foo
-npm init @usr -> npx @usr/create
+npm init foo -> npm exec create-foo
+npm init @usr/foo -> npm exec @usr/create-foo
+npm init @usr -> npm exec @usr/create
-
Any additional options will be passed directly to the command, so npm init foo -- --hello will map to npx create-foo --hello.
If the initializer is omitted (by just calling npm init), init will fall
back to legacy init behavior. It will ask you a bunch of questions, and
then write a package.json for you. It will attempt to make reasonable
@@ -171,6 +171,15 @@
Description
strictly additive, so it will keep any fields and values that were already
set. You can also use
-y/
--yes to skip the questionnaire altogether. If
you pass
--scope, it will create a scoped package.
+
Forwarding additional options
+
Any additional options will be passed directly to the command, so npm init foo -- --hello will map to npm exec -- create-foo --hello.
+
To better illustrate how options are forwarded, here’s a more evolved
+example showing options passed to both the npm cli and a create package,
+both following commands are equivalent:
+
+npm init foo -y --registry=<url> -- --hello -a
+npm exec -y --registry=<url> -- create-foo --hello -a
+
Examples
Create a new React-based project using
create-react-app:
@@ -189,6 +198,51 @@
Examples
Generate it without having it ask any questions:
$ npm init -y
+
Workspaces support
+
It’s possible to create a new workspace within your project by using the
+workspace config option. When using npm init -w <dir> the cli will
+create the folders and boilerplate expected while also adding a reference
+to your project package.json "workspaces": [] property in order to make
+sure that new generated workspace is properly set up as such.
+
Given a project with no workspaces, e.g:
+
.
++-- package.json
+
+
You may generate a new workspace using the legacy init:
+
$ npm init -w packages/a
+
+
That will generate a new folder and package.json file, while also updating
+your top-level package.json to add the reference to this new workspace:
+
.
++-- package.json
+`-- packages
+ `-- a
+ `-- package.json
+
+
The workspaces init also supports the npm init <initializer> -w <dir>
+syntax, following the same set of rules explained earlier in the initial
+Description section of this page. Similar to the previous example of
+creating a new React-based project using
+create-react-app, the following syntax
+will make sure to create the new react app as a nested workspace within your
+project and configure your package.json to recognize it as such:
+
npm init -w packages/my-react-app react-app .
+
+
This will make sure to generate your react app as expected, one important
+consideration to have in mind is that npm exec is going to be run in the
+context of the newly created folder for that workspace, and that’s the reason
+why in this example the initializer uses the initializer name followed with a
+dot to represent the current directory in that context, e.g: react-app .:
+
.
++-- package.json
+`-- packages
+ +-- a
+ | `-- package.json
+ `-- my-react-app
+ +-- README
+ +-- package.json
+ `-- ...
+
A note on caching
The npm cli utilizes its internal package cache when using the package
name specified. You can use the following to change how and when the
@@ -203,6 +257,31 @@
prefer-offline
offline
Forces full offline mode. Any packages not locally cached will result in
an error.
+
workspace
+
+- Alias:
-w
+- Type: Array
+- Default:
[]
+
+
Enable running npm init in the context of workspaces, creating any missing
+folders, generating files and adding/updating the "workspaces" property of
+the project package.json.
+
the provided names or paths provided.
+
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
+children workspaces)
+
+
workspaces
+
+- Alias:
-ws
+- Type: Boolean
+- Default:
false
+
+
Run npm init in the context of all configured workspaces for the
+current project.
See Also
diff --git a/deps/npm/docs/output/commands/npm-ls.html b/deps/npm/docs/output/commands/npm-ls.html
index 5e2f75138a62b9..ede5cb042907a6 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.10.0 /path/to/npm
+npm@7.11.2 /path/to/npm
└─┬ init-package-json@0.0.4
└── promzard@0.1.5
diff --git a/deps/npm/docs/output/commands/npm-run-script.html b/deps/npm/docs/output/commands/npm-run-script.html
index 6fc343dfbaf5f9..1e47bfec108529 100644
--- a/deps/npm/docs/output/commands/npm-run-script.html
+++ b/deps/npm/docs/output/commands/npm-run-script.html
@@ -282,7 +282,7 @@ workspace
workspaces
-- Alias:
-ws
+- Alias:
--ws
- Type: Boolean
- Default:
false
@@ -296,6 +296,7 @@ See Also
npm restart
npm stop
npm config
+npm workspaces
diff --git a/deps/npm/docs/output/commands/npm-view.html b/deps/npm/docs/output/commands/npm-view.html
index d3a1251673c2b6..7489b17b1cd009 100644
--- a/deps/npm/docs/output/commands/npm-view.html
+++ b/deps/npm/docs/output/commands/npm-view.html
@@ -141,7 +141,7 @@ npm-view
Synopsis
@@ -198,6 +198,17 @@
Description
this:
npm view connect versions
+
Configuration
+
json
+
Show information in JSON format. See Output below.
+
workspaces
+
Enables workspaces context while searching the package.json in the
+current folder. Information about packages named in each workspace will
+be viewed.
+
workspace
+
Enables workspaces context and limits results to only those specified by
+this config item. Only the information about packages named in the
+workspaces given here will be viewed.
Output
If only a single string field for a single version is output, then it
will not be colorized or quoted, to enable piping the output to
diff --git a/deps/npm/docs/output/commands/npm.html b/deps/npm/docs/output/commands/npm.html
index dde689df3ee387..311c581f681df4 100644
--- a/deps/npm/docs/output/commands/npm.html
+++ b/deps/npm/docs/output/commands/npm.html
@@ -148,7 +148,7 @@
Table of contents
npm <command> [args]
Version
-
7.10.0
+
7.11.2
Description
npm is the package manager for the Node JavaScript platform. It puts
modules in place so that node can find them, and manages dependency
diff --git a/deps/npm/docs/output/configuring-npm/package-json.html b/deps/npm/docs/output/configuring-npm/package-json.html
index 9c58ebf85f6a59..84956dede7d296 100644
--- a/deps/npm/docs/output/configuring-npm/package-json.html
+++ b/deps/npm/docs/output/configuring-npm/package-json.html
@@ -435,6 +435,7 @@
bin
Please make sure that your file(s) referenced in bin starts with
#!/usr/bin/env node, otherwise the scripts are started without the node
executable!
+
Note that you can also set the executable files using directories.bin.
man
Specify either a single file or an array of filenames to put in place for
the man program to find.
diff --git a/deps/npm/docs/output/using-npm/config.html b/deps/npm/docs/output/using-npm/config.html
index 5599777347b3a1..4435ce53bbaaca 100644
--- a/deps/npm/docs/output/using-npm/config.html
+++ b/deps/npm/docs/output/using-npm/config.html
@@ -141,7 +141,7 @@
config
Description
@@ -279,13 +279,6 @@
allow-same-version
Prevents throwing an error when npm version is used to set the new version
to the same value as the current version.
-
always-auth
-
-- Default: false
-- Type: Boolean
-
-
Force npm to always require authentication when accessing the registry, even
-for GET requests.
audit
- Default: true
@@ -1055,7 +1048,7 @@ script-shell
- Default: ‘/bin/sh’ on POSIX systems, ‘cmd.exe’ on Windows
- Type: null or String
-
The shell to use for scripts run with the npm run command.
+
The shell to use for scripts run with the npm exec, npm run and npm init <pkg> commands.
searchexclude
- Default: “”
diff --git a/deps/npm/lib/adduser.js b/deps/npm/lib/adduser.js
index f35b9829fe946e..fb1e323512b6d0 100644
--- a/deps/npm/lib/adduser.js
+++ b/deps/npm/lib/adduser.js
@@ -21,7 +21,6 @@ class AddUser extends BaseCommand {
return [
'registry',
'scope',
- 'always-auth',
]
}
diff --git a/deps/npm/lib/exec.js b/deps/npm/lib/exec.js
index f8c76eeed4c515..3da672f9915fdd 100644
--- a/deps/npm/lib/exec.js
+++ b/deps/npm/lib/exec.js
@@ -1,18 +1,6 @@
-const { promisify } = require('util')
-const read = promisify(require('read'))
-const chalk = require('chalk')
-const mkdirp = require('mkdirp-infer-owner')
-const readPackageJson = require('read-package-json-fast')
-const Arborist = require('@npmcli/arborist')
-const runScript = require('@npmcli/run-script')
-const { resolve, delimiter } = require('path')
-const ciDetect = require('@npmcli/ci-detect')
-const crypto = require('crypto')
-const pacote = require('pacote')
-const npa = require('npm-package-arg')
-const fileExists = require('./utils/file-exists.js')
-const PATH = require('./utils/path.js')
+const libexec = require('libnpmexec')
const BaseCommand = require('./base-command.js')
+const getLocationMsg = require('./exec/get-workspace-location-msg.js')
const getWorkspaces = require('./workspaces/get-workspaces.js')
// it's like this:
@@ -40,13 +28,6 @@ const getWorkspaces = require('./workspaces/get-workspaces.js')
// runScript({ pkg, event: 'npx', ... })
// process.env.npm_lifecycle_event = 'npx'
-const nocolor = {
- reset: s => s,
- bold: s => s,
- dim: s => s,
- green: s => s,
-}
-
class Exec extends BaseCommand {
/* istanbul ignore next - see test/lib/load-all-commands.js */
static get description () {
@@ -86,276 +67,50 @@ class Exec extends BaseCommand {
// When commands go async and we can dump the boilerplate exec methods this
// can be named correctly
async _exec (_args, { locationMsg, path, runPath }) {
+ const args = [..._args]
+ const cache = this.npm.config.get('cache')
const call = this.npm.config.get('call')
- const shell = this.npm.config.get('shell')
- // dereferenced because we manipulate it later
- const packages = [...this.npm.config.get('package')]
+ const color = this.npm.config.get('color')
+ const {
+ flatOptions,
+ localBin,
+ log,
+ globalBin,
+ output,
+ } = this.npm
+ const scriptShell = this.npm.config.get('script-shell') || undefined
+ const packages = this.npm.config.get('package')
+ const yes = this.npm.config.get('yes')
if (call && _args.length)
throw this.usage
- const args = [..._args]
- const pathArr = [...PATH]
-
- // nothing to maybe install, skip the arborist dance
- if (!call && !args.length && !packages.length) {
- return await this.run({
- args,
- call,
- locationMsg,
- shell,
- path,
- pathArr,
- runPath,
- })
- }
-
- const needPackageCommandSwap = args.length && !packages.length
- // if there's an argument and no package has been explicitly asked for
- // check the local and global bin paths for a binary named the same as
- // the argument and run it if it exists, otherwise fall through to
- // the behavior of treating the single argument as a package name
- if (needPackageCommandSwap) {
- let binExists = false
- if (await fileExists(`${this.npm.localBin}/${args[0]}`)) {
- pathArr.unshift(this.npm.localBin)
- binExists = true
- } else if (await fileExists(`${this.npm.globalBin}/${args[0]}`)) {
- pathArr.unshift(this.npm.globalBin)
- binExists = true
- }
-
- if (binExists) {
- return await this.run({
- args,
- call,
- locationMsg,
- path,
- pathArr,
- runPath,
- shell,
- })
- }
-
- packages.push(args[0])
- }
-
- // If we do `npm exec foo`, and have a `foo` locally, then we'll
- // always use that, so we don't really need to fetch the manifest.
- // So: run npa on each packages entry, and if it is a name with a
- // rawSpec==='', then try to readPackageJson at
- // node_modules/${name}/package.json, and only pacote fetch if
- // that fails.
- const manis = await Promise.all(packages.map(async p => {
- const spec = npa(p, path)
- if (spec.type === 'tag' && spec.rawSpec === '') {
- // fall through to the pacote.manifest() approach
- try {
- const pj = resolve(path, 'node_modules', spec.name)
- return await readPackageJson(pj)
- } catch (er) {}
- }
- // Force preferOnline to true so we are making sure to pull in the latest
- // This is especially useful if the user didn't give us a version, and
- // they expect to be running @latest
- return await pacote.manifest(p, {
- ...this.npm.flatOptions,
- preferOnline: true,
- })
- }))
-
- if (needPackageCommandSwap)
- args[0] = this.getBinFromManifest(manis[0])
-
- // figure out whether we need to install stuff, or if local is fine
- const localArb = new Arborist({
- ...this.npm.flatOptions,
- path,
- })
- const tree = await localArb.loadActual()
-
- // do we have all the packages in manifest list?
- const needInstall = manis.some(mani => this.manifestMissing(tree, mani))
-
- if (needInstall) {
- const installDir = this.cacheInstallDir(packages)
- await mkdirp(installDir)
- const arb = new Arborist({
- ...this.npm.flatOptions,
- log: this.npm.log,
- path: installDir,
- })
- const tree = await arb.loadActual()
-
- // at this point, we have to ensure that we get the exact same
- // version, because it's something that has only ever been installed
- // by npm exec in the cache install directory
- const add = manis.filter(mani => this.manifestMissing(tree, {
- ...mani,
- _from: `${mani.name}@${mani.version}`,
- }))
- .map(mani => mani._from)
- .sort((a, b) => a.localeCompare(b))
-
- // no need to install if already present
- if (add.length) {
- if (!this.npm.config.get('yes')) {
- // set -n to always say no
- if (this.npm.config.get('yes') === false)
- throw new Error('canceled')
-
- if (!process.stdin.isTTY || ciDetect()) {
- this.npm.log.warn('exec', `The following package${
- add.length === 1 ? ' was' : 's were'
- } not found and will be installed: ${
- add.map((pkg) => pkg.replace(/@$/, '')).join(', ')
- }`)
- } else {
- const addList = add.map(a => ` ${a.replace(/@$/, '')}`)
- .join('\n') + '\n'
- const prompt = `Need to install the following packages:\n${
- addList
- }Ok to proceed? `
- const confirm = await read({ prompt, default: 'y' })
- if (confirm.trim().toLowerCase().charAt(0) !== 'y')
- throw new Error('canceled')
- }
- }
- await arb.reify({
- ...this.npm.flatOptions,
- log: this.npm.log,
- add,
- })
- }
- pathArr.unshift(resolve(installDir, 'node_modules/.bin'))
- }
-
- return await this.run({
+ return libexec({
+ ...flatOptions,
args,
call,
+ cache,
+ color,
+ localBin,
locationMsg,
+ log,
+ globalBin,
+ output,
+ packages,
path,
- pathArr,
runPath,
- shell,
+ scriptShell,
+ yes,
})
}
- async run ({ args, call, locationMsg, path, pathArr, runPath, shell }) {
- // turn list of args into command string
- const script = call || args.shift() || shell
-
- // do the fakey runScript dance
- // still should work if no package.json in cwd
- const realPkg = await readPackageJson(`${path}/package.json`)
- .catch(() => ({}))
- const pkg = {
- ...realPkg,
- scripts: {
- ...(realPkg.scripts || {}),
- npx: script,
- },
- }
-
- this.npm.log.disableProgress()
- try {
- if (script === shell) {
- if (process.stdin.isTTY) {
- if (ciDetect())
- return this.npm.log.warn('exec', 'Interactive mode disabled in CI environment')
-
- const color = this.npm.config.get('color')
- const colorize = color ? chalk : nocolor
-
- locationMsg = locationMsg || ` at location:\n${colorize.dim(runPath)}`
-
- this.npm.output(`${
- colorize.reset('\nEntering npm script environment')
- }${
- colorize.reset(locationMsg)
- }${
- colorize.bold('\nType \'exit\' or ^D when finished\n')
- }`)
- }
- }
- return await runScript({
- ...this.npm.flatOptions,
- pkg,
- banner: false,
- // we always run in cwd, not --prefix
- path: runPath,
- stdioString: true,
- event: 'npx',
- args,
- env: {
- PATH: pathArr.join(delimiter),
- },
- stdio: 'inherit',
- })
- } finally {
- this.npm.log.enableProgress()
- }
- }
-
- manifestMissing (tree, mani) {
- // if the tree doesn't have a child by that name/version, return true
- // true means we need to install it
- const child = tree.children.get(mani.name)
- // if no child, we have to load it
- if (!child)
- return true
-
- // if no version/tag specified, allow whatever's there
- if (mani._from === `${mani.name}@`)
- return false
-
- // otherwise the version has to match what we WOULD get
- return child.version !== mani.version
- }
-
- getBinFromManifest (mani) {
- // if we have a bin matching (unscoped portion of) packagename, use that
- // otherwise if there's 1 bin or all bin value is the same (alias), use
- // that, otherwise fail
- const bin = mani.bin || {}
- if (new Set(Object.values(bin)).size === 1)
- return Object.keys(bin)[0]
-
- // XXX probably a util to parse this better?
- const name = mani.name.replace(/^@[^/]+\//, '')
- if (bin[name])
- return name
-
- // XXX need better error message
- throw Object.assign(new Error('could not determine executable to run'), {
- pkgid: mani._id,
- })
- }
-
- cacheInstallDir (packages) {
- // only packages not found in ${prefix}/node_modules
- return resolve(this.npm.config.get('cache'), '_npx', this.getHash(packages))
- }
-
- getHash (packages) {
- return crypto.createHash('sha512')
- .update(packages.sort((a, b) => a.localeCompare(b)).join('\n'))
- .digest('hex')
- .slice(0, 16)
- }
-
async _execWorkspaces (args, filters) {
const workspaces =
await getWorkspaces(filters, { path: this.npm.localPrefix })
- const getLocationMsg = async path => {
- const color = this.npm.config.get('color')
- const colorize = color ? chalk : nocolor
- const { _id } = await readPackageJson(`${path}/package.json`)
- return ` in workspace ${colorize.green(_id)} at location:\n${colorize.dim(path)}`
- }
+ const color = this.npm.config.get('color')
for (const workspacePath of workspaces.values()) {
- const locationMsg = await getLocationMsg(workspacePath)
+ const locationMsg = await getLocationMsg({ color, path: workspacePath })
await this._exec(args, {
locationMsg,
path: workspacePath,
@@ -364,4 +119,5 @@ class Exec extends BaseCommand {
}
}
}
+
module.exports = Exec
diff --git a/deps/npm/lib/exec/get-workspace-location-msg.js b/deps/npm/lib/exec/get-workspace-location-msg.js
new file mode 100644
index 00000000000000..813b11e7892223
--- /dev/null
+++ b/deps/npm/lib/exec/get-workspace-location-msg.js
@@ -0,0 +1,25 @@
+const chalk = require('chalk')
+const readPackageJson = require('read-package-json-fast')
+
+const nocolor = {
+ dim: s => s,
+ green: s => s,
+}
+
+const getLocationMsg = async ({ color, path }) => {
+ const colorize = color ? chalk : nocolor
+ const { _id } =
+ await readPackageJson(`${path}/package.json`)
+ .catch(() => ({}))
+
+ const workspaceMsg = _id
+ ? ` in workspace ${colorize.green(_id)}`
+ : ` in a ${colorize.green('new')} workspace`
+ const locationMsg = ` at location:\n${
+ colorize.dim(path)
+ }`
+
+ return `${workspaceMsg}${locationMsg}`
+}
+
+module.exports = getLocationMsg
diff --git a/deps/npm/lib/init.js b/deps/npm/lib/init.js
index 81c6733885a68e..7d7f6bab37668f 100644
--- a/deps/npm/lib/init.js
+++ b/deps/npm/lib/init.js
@@ -1,6 +1,14 @@
+const fs = require('fs')
+const { relative, resolve } = require('path')
+const mkdirp = require('mkdirp-infer-owner')
const initJson = require('init-package-json')
const npa = require('npm-package-arg')
+const rpj = require('read-package-json-fast')
+const libexec = require('libnpmexec')
+const parseJSON = require('json-parse-even-better-errors')
+const mapWorkspaces = require('@npmcli/map-workspaces')
+const getLocationMsg = require('./exec/get-workspace-location-msg.js')
const BaseCommand = require('./base-command.js')
class Init extends BaseCommand {
@@ -9,6 +17,11 @@ class Init extends BaseCommand {
return 'Create a package.json file'
}
+ /* istanbul ignore next - see test/lib/load-all-commands.js */
+ static get params () {
+ return ['workspace', 'workspaces']
+ }
+
/* istanbul ignore next - see test/lib/load-all-commands.js */
static get name () {
return 'init'
@@ -27,42 +40,107 @@ class Init extends BaseCommand {
this.init(args).then(() => cb()).catch(cb)
}
+ execWorkspaces (args, filters, cb) {
+ this.initWorkspaces(args, filters).then(() => cb()).catch(cb)
+ }
+
async init (args) {
- // the new npx style way
+ // npm exec style
+ if (args.length)
+ return (await this.execCreate({ args, path: process.cwd() }))
+
+ // no args, uses classic init-package-json boilerplate
+ await this.template()
+ }
+
+ async initWorkspaces (args, filters) {
+ // reads package.json for the top-level folder first, by doing this we
+ // ensure the command throw if no package.json is found before trying
+ // to create a workspace package.json file or its folders
+ const pkg = await rpj(resolve(this.npm.localPrefix, 'package.json'))
+ const wPath = filterArg => resolve(this.npm.localPrefix, filterArg)
+
+ // npm-exec style, runs in the context of each workspace filter
if (args.length) {
- const initerName = args[0]
- let packageName = initerName
- if (/^@[^/]+$/.test(initerName))
- packageName = initerName + '/create'
- else {
- const req = npa(initerName)
- if (req.type === 'git' && req.hosted) {
- const { user, project } = req.hosted
- packageName = initerName
- .replace(user + '/' + project, user + '/create-' + project)
- } else if (req.registry) {
- packageName = req.name.replace(/^(@[^/]+\/)?/, '$1create-')
- if (req.rawSpec)
- packageName += '@' + req.rawSpec
- } else {
- throw Object.assign(new Error(
- 'Unrecognized initializer: ' + initerName +
- '\nFor more package binary executing power check out `npx`:' +
- '\nhttps://www.npmjs.com/package/npx'
- ), { code: 'EUNSUPPORTED' })
- }
+ for (const filterArg of filters) {
+ const path = wPath(filterArg)
+ await mkdirp(path)
+ await this.execCreate({ args, path })
+ await this.setWorkspace({ pkg, workspacePath: path })
+ }
+ return
+ }
+
+ // no args, uses classic init-package-json boilerplate
+ for (const filterArg of filters) {
+ const path = wPath(filterArg)
+ await mkdirp(path)
+ await this.template(path)
+ await this.setWorkspace({ pkg, workspacePath: path })
+ }
+ }
+
+ async execCreate ({ args, path }) {
+ const [initerName, ...otherArgs] = args
+ let packageName = initerName
+
+ if (/^@[^/]+$/.test(initerName))
+ packageName = initerName + '/create'
+ else {
+ const req = npa(initerName)
+ if (req.type === 'git' && req.hosted) {
+ const { user, project } = req.hosted
+ packageName = initerName
+ .replace(user + '/' + project, user + '/create-' + project)
+ } else if (req.registry) {
+ packageName = req.name.replace(/^(@[^/]+\/)?/, '$1create-')
+ if (req.rawSpec)
+ packageName += '@' + req.rawSpec
+ } else {
+ throw Object.assign(new Error(
+ 'Unrecognized initializer: ' + initerName +
+ '\nFor more package binary executing power check out `npx`:' +
+ '\nhttps://www.npmjs.com/package/npx'
+ ), { code: 'EUNSUPPORTED' })
}
- this.npm.config.set('package', [])
- const newArgs = [packageName, ...args.slice(1)]
- return new Promise((res, rej) => {
- this.npm.commands.exec(newArgs, er => er ? rej(er) : res())
- })
}
- // the old way
- const dir = process.cwd()
+ const newArgs = [packageName, ...otherArgs]
+ const cache = this.npm.config.get('cache')
+ const { color } = this.npm.flatOptions
+ const {
+ flatOptions,
+ localBin,
+ log,
+ globalBin,
+ output,
+ } = this.npm
+ const locationMsg = await getLocationMsg({ color, path })
+ const runPath = path
+ const scriptShell = this.npm.config.get('script-shell') || undefined
+ const yes = this.npm.config.get('yes')
+
+ await libexec({
+ ...flatOptions,
+ args: newArgs,
+ cache,
+ color,
+ localBin,
+ locationMsg,
+ log,
+ globalBin,
+ output,
+ path,
+ runPath,
+ scriptShell,
+ yes,
+ })
+ }
+
+ async template (path = process.cwd()) {
this.npm.log.pause()
this.npm.log.disableProgress()
+
const initFile = this.npm.config.get('init-module')
if (!this.npm.config.get('yes') && !this.npm.config.get('force')) {
this.npm.output([
@@ -78,9 +156,10 @@ class Init extends BaseCommand {
'Press ^C at any time to quit.',
].join('\n'))
}
+
// XXX promisify init-package-json
await new Promise((res, rej) => {
- initJson(dir, initFile, this.npm.config, (er, data) => {
+ initJson(path, initFile, this.npm.config, (er, data) => {
this.npm.log.resume()
this.npm.log.enableProgress()
this.npm.log.silly('package data', data)
@@ -97,5 +176,56 @@ class Init extends BaseCommand {
})
})
}
+
+ async setWorkspace ({ pkg, workspacePath }) {
+ const workspaces = await mapWorkspaces({ cwd: this.npm.localPrefix, pkg })
+
+ // skip setting workspace if current package.json glob already satisfies it
+ for (const wPath of workspaces.values()) {
+ if (wPath === workspacePath)
+ return
+ }
+
+ // if a create-pkg didn't generate a package.json at the workspace
+ // folder level, it might not be recognized as a workspace by
+ // mapWorkspaces, so we're just going to avoid touching the
+ // top-level package.json
+ try {
+ fs.statSync(resolve(workspacePath, 'package.json'))
+ } catch (err) {
+ return
+ }
+
+ let manifest
+ try {
+ manifest =
+ fs.readFileSync(resolve(this.npm.localPrefix, 'package.json'), 'utf-8')
+ } catch (error) {
+ throw new Error('package.json not found')
+ }
+
+ try {
+ manifest = parseJSON(manifest)
+ } catch (error) {
+ throw new Error(`Invalid package.json: ${error}`)
+ }
+
+ if (!manifest.workspaces)
+ manifest.workspaces = []
+
+ manifest.workspaces.push(relative(this.npm.localPrefix, workspacePath))
+
+ // format content
+ const {
+ [Symbol.for('indent')]: indent,
+ [Symbol.for('newline')]: newline,
+ } = manifest
+
+ const content = (JSON.stringify(manifest, null, indent) + '\n')
+ .replace(/\n/g, newline)
+
+ fs.writeFileSync(resolve(this.npm.localPrefix, 'package.json'), content)
+ }
}
+
module.exports = Init
diff --git a/deps/npm/lib/logout.js b/deps/npm/lib/logout.js
index adc19a923af9ab..0887ec397bf1ae 100644
--- a/deps/npm/lib/logout.js
+++ b/deps/npm/lib/logout.js
@@ -41,7 +41,7 @@ class Logout extends BaseCommand {
method: 'DELETE',
ignoreBody: true,
})
- } else if (auth.username || auth.password)
+ } else if (auth.isBasicAuth)
log.verbose('logout', `clearing user credentials for ${reg}`)
else {
const msg = `not logged in to ${reg}, so can't log out!`
diff --git a/deps/npm/lib/ls.js b/deps/npm/lib/ls.js
index 65b3ddfe7611b7..ccd8b2ff9dea71 100644
--- a/deps/npm/lib/ls.js
+++ b/deps/npm/lib/ls.js
@@ -166,7 +166,10 @@ class LS extends BaseCommand {
)
}
- if (problems.size) {
+ const shouldThrow = problems.size &&
+ ![...problems].every(problem => problem.startsWith('extraneous:'))
+
+ if (shouldThrow) {
throw Object.assign(
new Error([...problems].join(EOL)),
{ code: 'ELSPROBLEMS' }
@@ -302,7 +305,7 @@ const getJsonOutputItem = (node, { global, long }) => {
if (node.isRoot && hasPackageJson)
item.name = node.package.name || node.name
- if (long) {
+ if (long && !node[_missing]) {
item.name = item[_name]
const { dependencies, ...packageInfo } = node.package
Object.assign(item, packageInfo)
@@ -411,9 +414,11 @@ const augmentNodesWithMetadata = ({
path: node.path,
isLink: node.isLink,
realpath: node.realpath,
+ [_type]: node[_type],
[_invalid]: node[_invalid],
[_missing]: node[_missing],
- [_dedupe]: true,
+ // if it's missing, it's not deduped, it's just missing
+ [_dedupe]: !node[_missing],
}
} else {
// keeps track of already seen nodes in order to check for dedupes
diff --git a/deps/npm/lib/pack.js b/deps/npm/lib/pack.js
index 8e61efabb36e4d..5c0da6be7b6e04 100644
--- a/deps/npm/lib/pack.js
+++ b/deps/npm/lib/pack.js
@@ -45,22 +45,34 @@ class Pack extends BaseCommand {
args = ['.']
const unicode = this.npm.config.get('unicode')
+ const dryRun = this.npm.config.get('dry-run')
- // clone the opts because pacote mutates it with resolved/integrity
- const tarballs = await Promise.all(args.map(async (arg) => {
+ // Get the manifests and filenames first so we can bail early on manifest
+ // errors before making any tarballs
+ const manifests = []
+ for (const arg of args) {
const spec = npa(arg)
- const dryRun = this.npm.config.get('dry-run')
const manifest = await pacote.manifest(spec, this.npm.flatOptions)
+ if (!manifest._id)
+ throw new Error('Invalid package, must have name and version')
+
const filename = `${manifest.name}-${manifest.version}.tgz`
.replace(/^@/, '').replace(/\//, '-')
+ manifests.push({ arg, filename, manifest })
+ }
+
+ // Load tarball names up for printing afterward to isolate from the
+ // noise generated during packing
+ const tarballs = []
+ for (const { arg, filename, manifest } of manifests) {
const tarballData = await libpack(arg, this.npm.flatOptions)
const pkgContents = await getContents(manifest, tarballData)
if (!dryRun)
await writeFile(filename, tarballData)
- return pkgContents
- }))
+ tarballs.push(pkgContents)
+ }
for (const tar of tarballs) {
logTar(tar, { log, unicode })
diff --git a/deps/npm/lib/utils/config/definitions.js b/deps/npm/lib/utils/config/definitions.js
index db1f25e9517def..3a50175d5db649 100644
--- a/deps/npm/lib/utils/config/definitions.js
+++ b/deps/npm/lib/utils/config/definitions.js
@@ -199,16 +199,6 @@ define('also', {
},
})
-define('always-auth', {
- default: false,
- type: Boolean,
- description: `
- Force npm to always require authentication when accessing the registry,
- even for \`GET\` requests.
- `,
- flatten,
-})
-
define('audit', {
default: true,
type: Boolean,
@@ -1660,7 +1650,8 @@ define('script-shell', {
`,
type: [null, String],
description: `
- The shell to use for scripts run with the \`npm run\` command.
+ The shell to use for scripts run with the \`npm exec\`,
+ \`npm run\` and \`npm init \` commands.
`,
flatten (key, obj, flatOptions) {
flatOptions.scriptShell = obj[key] || undefined
diff --git a/deps/npm/man/man1/npm-adduser.1 b/deps/npm/man/man1/npm-adduser.1
index 9daa39292d4fc7..aa7d0e5e527a51 100644
--- a/deps/npm/man/man1/npm-adduser.1
+++ b/deps/npm/man/man1/npm-adduser.1
@@ -5,7 +5,7 @@
.P
.RS 2
.nf
-npm adduser [\-\-registry=url] [\-\-scope=@orgname] [\-\-always\-auth] [\-\-auth\-type=legacy]
+npm adduser [\-\-registry=url] [\-\-scope=@orgname] [\-\-auth\-type=legacy]
aliases: login, add\-user
.fi
@@ -54,24 +54,6 @@ npm adduser \-\-registry=http://myregistry\.example\.com \-\-scope=@myco
.P
This will set a registry for the given scope and login or create a user for
that registry at the same time\.
-.SS always\-auth
-.P
-Default: false
-.P
-If specified, save configuration indicating that all requests to the given
-registry should include authorization information\. Useful for private
-registries\. Can be used with \fB\-\-registry\fP and / or \fB\-\-scope\fP, e\.g\.
-.P
-.RS 2
-.nf
-npm adduser \-\-registry=http://private\-registry\.example\.com \-\-always\-auth
-.fi
-.RE
-.P
-This will ensure that all requests to that registry (including for tarballs)
-include an authorization header\. This setting may be necessary for use with
-private registries where metadata and package tarballs are stored on hosts with
-different hostnames\. See \fBalways\-auth\fP in npm help \fBconfig\fP for more details on always\-auth\. Registry\-specific configuration of \fBalways\-auth\fP takes precedence over any global configuration\.
.SS auth\-type
.RS 0
.IP \(bu 2
diff --git a/deps/npm/man/man1/npm-exec.1 b/deps/npm/man/man1/npm-exec.1
index 3711534c58e912..1ac663ff18ef50 100644
--- a/deps/npm/man/man1/npm-exec.1
+++ b/deps/npm/man/man1/npm-exec.1
@@ -9,7 +9,7 @@ npm exec \-\- [@] [args\.\.\.]
npm exec \-\-package=[@] \-\- [args\.\.\.]
npm exec \-c ' [args\.\.\.]'
npm exec \-\-package=foo \-c ' [args\.\.\.]'
-npm exec [\-ws] [\-w [@] [args\.\.\.]
npx \-p [@] [args\.\.\.]
@@ -205,7 +205,7 @@ workspace folder:
.P
.RS 2
.nf
-npm exec \-ws \-\- eslint \./*\.js
+npm exec \-\-ws \-\- eslint \./*\.js
.fi
.RE
.SS Filtering workspaces
@@ -317,7 +317,7 @@ children workspaces)
.SS workspaces
.RS 0
.IP \(bu 2
-Alias: \fB\-ws\fP
+Alias: \fB\-\-ws\fP
.IP \(bu 2
Type: Boolean
.IP \(bu 2
@@ -343,5 +343,7 @@ npm help restart
npm help stop
.IP \(bu 2
npm help config
+.IP \(bu 2
+npm help workspaces
.RE
diff --git a/deps/npm/man/man1/npm-init.1 b/deps/npm/man/man1/npm-init.1
index b3be3f35e6f6c2..b4b09e598d247b 100644
--- a/deps/npm/man/man1/npm-init.1
+++ b/deps/npm/man/man1/npm-init.1
@@ -6,8 +6,9 @@
.RS 2
.nf
npm init [\-\-force|\-f|\-\-yes|\-y|\-\-scope]
-npm init <@scope> (same as `npx <@scope>/create`)
-npm init [<@scope>/] (same as `npx [<@scope>/]create\-`)
+npm init <@scope> (same as `npm exec <@scope>/create`)
+npm init [<@scope>/] (same as `npm exec [<@scope>/]create\-`)
+npm init [\-w ] [args\.\.\.]
.fi
.RE
.SS Description
@@ -16,25 +17,22 @@ npm init [<@scope>/] (same as `npx [<@scope>/]create\-`)
package\.
.P
\fBinitializer\fP in this case is an npm package named \fBcreate\-\fP,
-which will be installed by \fBnpx\fP \fIhttps://npm\.im/npx\fR, and then have its
+which will be installed by npm help \fBnpm\-exec\fP, and then have its
main bin executed \-\- presumably creating or updating \fBpackage\.json\fP and
running any other initialization\-related operations\.
.P
-The init command is transformed to a corresponding \fBnpx\fP operation as
+The init command is transformed to a corresponding \fBnpm exec\fP operation as
follows:
.RS 0
.IP \(bu 2
-\fBnpm init foo\fP \-> \fBnpx create\-foo\fP
+\fBnpm init foo\fP \-> \fBnpm exec create\-foo\fP
.IP \(bu 2
-\fBnpm init @usr/foo\fP \-> \fBnpx @usr/create\-foo\fP
+\fBnpm init @usr/foo\fP \-> \fBnpm exec @usr/create\-foo\fP
.IP \(bu 2
-\fBnpm init @usr\fP \-> \fBnpx @usr/create\fP
+\fBnpm init @usr\fP \-> \fBnpm exec @usr/create\fP
.RE
.P
-Any additional options will be passed directly to the command, so \fBnpm init
-foo \-\- \-\-hello\fP will map to \fBnpx create\-foo \-\-hello\fP\|\.
-.P
If the initializer is omitted (by just calling \fBnpm init\fP), init will fall
back to legacy init behavior\. It will ask you a bunch of questions, and
then write a package\.json for you\. It will attempt to make reasonable
@@ -42,6 +40,21 @@ guesses based on existing fields, dependencies, and options selected\. It is
strictly additive, so it will keep any fields and values that were already
set\. You can also use \fB\-y\fP/\fB\-\-yes\fP to skip the questionnaire altogether\. If
you pass \fB\-\-scope\fP, it will create a scoped package\.
+.SS Forwarding additional options
+.P
+Any additional options will be passed directly to the command, so \fBnpm init
+foo \-\- \-\-hello\fP will map to \fBnpm exec \-\- create\-foo \-\-hello\fP\|\.
+.P
+To better illustrate how options are forwarded, here's a more evolved
+example showing options passed to both the \fBnpm cli\fR and a create package,
+both following commands are equivalent:
+.RS 0
+.IP \(bu 2
+\fBnpm init foo \-y \-\-registry= \-\- \-\-hello \-a\fP
+.IP \(bu 2
+\fBnpm exec \-y \-\-registry= \-\- create\-foo \-\-hello \-a\fP
+
+.RE
.SS Examples
.P
Create a new React\-based project using
@@ -80,6 +93,77 @@ Generate it without having it ask any questions:
$ npm init \-y
.fi
.RE
+.SS Workspaces support
+.P
+It's possible to create a new workspace within your project by using the
+\fBworkspace\fP config option\. When using \fBnpm init \-w \fP the cli will
+create the folders and boilerplate expected while also adding a reference
+to your project \fBpackage\.json\fP \fB"workspaces": []\fP property in order to make
+sure that new generated \fBworkspace\fR is properly set up as such\.
+.P
+Given a project with no workspaces, e\.g:
+.P
+.RS 2
+.nf
+\|\.
++\-\- package\.json
+.fi
+.RE
+.P
+You may generate a new workspace using the legacy init:
+.P
+.RS 2
+.nf
+$ npm init \-w packages/a
+.fi
+.RE
+.P
+That will generate a new folder and \fBpackage\.json\fP file, while also updating
+your top\-level \fBpackage\.json\fP to add the reference to this new workspace:
+.P
+.RS 2
+.nf
+\|\.
++\-\- package\.json
+`\-\- packages
+ `\-\- a
+ `\-\- package\.json
+.fi
+.RE
+.P
+The workspaces init also supports the \fBnpm init \-w \fP
+syntax, following the same set of rules explained earlier in the initial
+\fBDescription\fR section of this page\. Similar to the previous example of
+creating a new React\-based project using
+\fBcreate\-react\-app\fP \fIhttps://npm\.im/create\-react\-app\fR, the following syntax
+will make sure to create the new react app as a nested \fBworkspace\fR within your
+project and configure your \fBpackage\.json\fP to recognize it as such:
+.P
+.RS 2
+.nf
+npm init \-w packages/my\-react\-app react\-app \.
+.fi
+.RE
+.P
+This will make sure to generate your react app as expected, one important
+consideration to have in mind is that \fBnpm exec\fP is going to be run in the
+context of the newly created folder for that workspace, and that's the reason
+why in this example the initializer uses the initializer name followed with a
+dot to represent the current directory in that context, e\.g: \fBreact\-app \.\fP:
+.P
+.RS 2
+.nf
+\|\.
++\-\- package\.json
+`\-\- packages
+ +\-\- a
+ | `\-\- package\.json
+ `\-\- my\-react\-app
+ +\-\- README
+ +\-\- package\.json
+ `\-\- \.\.\.
+.fi
+.RE
.SS A note on caching
.P
The npm cli utilizes its internal package cache when using the package
@@ -98,6 +182,47 @@ requested from the server\. To force full offline mode, use \fBoffline\fP\|\.
.P
Forces full offline mode\. Any packages not locally cached will result in
an error\.
+.SS workspace
+.RS 0
+.IP \(bu 2
+Alias: \fB\-w\fP
+.IP \(bu 2
+Type: Array
+.IP \(bu 2
+Default: \fB[]\fP
+
+.RE
+.P
+Enable running \fBnpm init\fP in the context of workspaces, creating any missing
+folders, generating files and adding/updating the \fB"workspaces"\fP property of
+the project \fBpackage\.json\fP\|\.
+.P
+the provided names or paths provided\.
+.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
+children workspaces)
+
+.RE
+.SS workspaces
+.RS 0
+.IP \(bu 2
+Alias: \fB\-ws\fP
+.IP \(bu 2
+Type: Boolean
+.IP \(bu 2
+Default: \fBfalse\fP
+
+.RE
+.P
+Run \fBnpm init\fP in the context of all configured workspaces for the
+current project\.
.SS See Also
.RS 0
.IP \(bu 2
@@ -110,5 +235,7 @@ npm help version
npm help scope
.IP \(bu 2
npm help exec
+.IP \(bu 2
+npm help workspaces
.RE
diff --git a/deps/npm/man/man1/npm-ls.1 b/deps/npm/man/man1/npm-ls.1
index 6f1041b8dcb83d..2d4720ad8a4a97 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\.10\.0 /path/to/npm
+npm@7\.11\.2 /path/to/npm
└─┬ init\-package\-json@0\.0\.4
└── promzard@0\.1\.5
.fi
diff --git a/deps/npm/man/man1/npm-run-script.1 b/deps/npm/man/man1/npm-run-script.1
index b108b5491feedc..53b88e6fab99fd 100644
--- a/deps/npm/man/man1/npm-run-script.1
+++ b/deps/npm/man/man1/npm-run-script.1
@@ -221,7 +221,7 @@ children workspaces)
.SS workspaces
.RS 0
.IP \(bu 2
-Alias: \fB\-ws\fP
+Alias: \fB\-\-ws\fP
.IP \(bu 2
Type: Boolean
.IP \(bu 2
@@ -245,5 +245,7 @@ npm help restart
npm help stop
.IP \(bu 2
npm help config
+.IP \(bu 2
+npm help workspaces
.RE
diff --git a/deps/npm/man/man1/npm-view.1 b/deps/npm/man/man1/npm-view.1
index 5ecf79851399a9..498821fbb6ba9a 100644
--- a/deps/npm/man/man1/npm-view.1
+++ b/deps/npm/man/man1/npm-view.1
@@ -111,6 +111,20 @@ this:
npm view connect versions
.fi
.RE
+.SS Configuration
+.SS json
+.P
+Show information in JSON format\. See \fBOutput\fP \fI#output\fR below\.
+.SS workspaces
+.P
+Enables workspaces context while searching the \fBpackage\.json\fP in the
+current folder\. Information about packages named in each workspace will
+be viewed\.
+.SS workspace
+.P
+Enables workspaces context and limits results to only those specified by
+this config item\. Only the information about packages named in the
+workspaces given here will be viewed\.
.SS Output
.P
If only a single string field for a single version is output, then it
diff --git a/deps/npm/man/man1/npm.1 b/deps/npm/man/man1/npm.1
index 595b8e68477b82..8dbeca5362bba8 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\.10\.0
+7\.11\.2
.SS Description
.P
npm is the package manager for the Node JavaScript platform\. It puts
diff --git a/deps/npm/man/man5/package-json.5 b/deps/npm/man/man5/package-json.5
index 9943296b25c353..a882e445ca0031 100644
--- a/deps/npm/man/man5/package-json.5
+++ b/deps/npm/man/man5/package-json.5
@@ -437,6 +437,8 @@ would be the same as this:
Please make sure that your file(s) referenced in \fBbin\fP starts with
\fB#!/usr/bin/env node\fP, otherwise the scripts are started without the node
executable!
+.P
+Note that you can also set the executable files using directories\.bin \fI#directoriesbin\fR\|\.
.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 211651fed6412f..522e974fc07089 100644
--- a/deps/npm/man/man7/config.7
+++ b/deps/npm/man/man7/config.7
@@ -217,17 +217,6 @@ Type: Boolean
.P
Prevents throwing an error when \fBnpm version\fP is used to set the new version
to the same value as the current version\.
-.SS \fBalways\-auth\fP
-.RS 0
-.IP \(bu 2
-Default: false
-.IP \(bu 2
-Type: Boolean
-
-.RE
-.P
-Force npm to always require authentication when accessing the registry, even
-for \fBGET\fP requests\.
.SS \fBaudit\fP
.RS 0
.IP \(bu 2
@@ -1455,7 +1444,8 @@ Type: null or String
.RE
.P
-The shell to use for scripts run with the \fBnpm run\fP command\.
+The shell to use for scripts run with the \fBnpm exec\fP, \fBnpm run\fP and \fBnpm
+init \fP commands\.
.SS \fBsearchexclude\fP
.RS 0
.IP \(bu 2
diff --git a/deps/npm/node_modules/@npmcli/arborist/bin/lib/logging.js b/deps/npm/node_modules/@npmcli/arborist/bin/lib/logging.js
index a7d20a1f536470..9420bca3c320cd 100644
--- a/deps/npm/node_modules/@npmcli/arborist/bin/lib/logging.js
+++ b/deps/npm/node_modules/@npmcli/arborist/bin/lib/logging.js
@@ -20,13 +20,21 @@ const levelMap = new Map(levels.reduce((set, level, index) => {
}, []))
const { inspect, format } = require('util')
+const colors = process.stderr.isTTY
+const magenta = colors ? msg => `\x1B[35m${msg}\x1B[39m` : m => m
if (loglevel !== 'silent') {
process.on('log', (level, ...args) => {
if (levelMap.get(level) < levelMap.get(loglevel))
return
- const pref = `${process.pid} ${level} `
+ const pref = `${process.pid} ${magenta(level)} `
if (level === 'warn' && args[0] === 'ERESOLVE')
- args[2] = inspect(args[2], { depth: 10 })
+ args[2] = inspect(args[2], { depth: 10, colors })
+ else {
+ args = args.map(a => {
+ return typeof a === 'string' ? a
+ : inspect(a, { depth: 10, colors })
+ })
+ }
const msg = pref + format(...args).trim().split('\n').join(`\n${pref}`)
console.error(msg)
})
diff --git a/deps/npm/node_modules/@npmcli/arborist/bin/lib/timers.js b/deps/npm/node_modules/@npmcli/arborist/bin/lib/timers.js
index 3b73c0bf6ddd32..e72217c1e4ed9c 100644
--- a/deps/npm/node_modules/@npmcli/arborist/bin/lib/timers.js
+++ b/deps/npm/node_modules/@npmcli/arborist/bin/lib/timers.js
@@ -1,4 +1,5 @@
const timers = Object.create(null)
+const { format } = require('util')
process.on('time', name => {
if (timers[name])
@@ -6,17 +7,20 @@ process.on('time', name => {
timers[name] = process.hrtime()
})
+const dim = process.stderr.isTTY ? msg => `\x1B[2m${msg}\x1B[22m` : m => m
+const red = process.stderr.isTTY ? msg => `\x1B[31m${msg}\x1B[39m` : m => m
process.on('timeEnd', name => {
if (!timers[name])
throw new Error('timer not started! ' + name)
const res = process.hrtime(timers[name])
delete timers[name]
- console.error(`${process.pid} ${name}`, res[0] * 1e3 + res[1] / 1e6)
+ const msg = format(`${process.pid} ${name}`, res[0] * 1e3 + res[1] / 1e6)
+ console.error(dim(msg))
})
process.on('exit', () => {
for (const name of Object.keys(timers)) {
- console.error('Dangling timer: ', name)
+ console.error(red('Dangling timer:'), name)
process.exitCode = 1
}
})
diff --git a/deps/npm/node_modules/@npmcli/arborist/bin/virtual.js b/deps/npm/node_modules/@npmcli/arborist/bin/virtual.js
index 7f90f20cf38176..3352802c2de873 100644
--- a/deps/npm/node_modules/@npmcli/arborist/bin/virtual.js
+++ b/deps/npm/node_modules/@npmcli/arborist/bin/virtual.js
@@ -8,7 +8,8 @@ require('./lib/timers.js')
const start = process.hrtime()
new Arborist(options).loadVirtual().then(tree => {
const end = process.hrtime(start)
- print(tree)
+ if (!options.quiet)
+ print(tree)
if (options.save)
tree.meta.save()
console.error(`read ${tree.inventory.size} deps in ${end[0] * 1000 + end[1] / 1e6}ms`)
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 f836fc04d8826f..7ee8dae35be1b5 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
@@ -47,6 +47,7 @@ const _flagsSuspect = Symbol.for('flagsSuspect')
const _workspaces = Symbol.for('workspaces')
const _prune = Symbol('prune')
const _preferDedupe = Symbol('preferDedupe')
+const _pruneDedupable = Symbol('pruneDedupable')
const _legacyBundling = Symbol('legacyBundling')
const _parseSettings = Symbol('parseSettings')
const _initTree = Symbol('initTree')
@@ -1188,6 +1189,16 @@ This is a one-time fix-up, please be patient...
}
}
+ // There is something present already, and we're not happy about it
+ // See if the thing we WOULD be happy with is also going to satisfy
+ // the other dependents on the current node.
+ const current = edge.to
+ const dep = await this[_nodeFromEdge](edge, null, null, required)
+ if (dep.canReplace(current)) {
+ await this[_nodeFromEdge](edge, node.parent, null, required)
+ continue
+ }
+
// at this point we know that there is a dep there, and
// we don't like it. always fail strictly, always allow forcibly or
// in non-strict mode if it's not our fault. don't warn here, because
@@ -1332,6 +1343,21 @@ This is a one-time fix-up, please be patient...
// this is an overridden peer dep
this[_warnPeerConflict](edge)
}
+
+ // if we get a KEEP in a update scenario, then we MAY have something
+ // already duplicating this unnecessarily! For example:
+ // ```
+ // root
+ // +-- x (dep: y@1.x)
+ // | +-- y@1.0.0
+ // +-- y@1.1.0
+ // ```
+ // Now say we do `reify({update:['y']})`, and the latest version is
+ // 1.1.0, which we already have in the root. We'll try to place y@1.1.0
+ // first in x, then in the root, ending with KEEP, because we already
+ // have it. In that case, we ought to REMOVE the nm/x/nm/y node, because
+ // it is an unnecessary duplicate.
+ this[_pruneDedupable](target, true)
return []
}
@@ -1387,8 +1413,8 @@ This is a one-time fix-up, please be patient...
// MAY end up putting a better/identical node further up the tree in
// a way that causes an unnecessary duplication. If so, remove the
// now-unnecessary node.
- if (edge.valid && edge.to.parent !== target && newDep.canReplace(edge.to))
- edge.to.parent = null
+ if (edge.valid && edge.to && edge.to !== newDep)
+ this[_pruneDedupable](edge.to, false)
// visit any dependents who are upset by this change
// if it's an angry overridden peer edge, however, make sure we
@@ -1404,30 +1430,8 @@ 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 !== newDep &&
- node.isDescendantOf(target) &&
- !node.inShrinkwrap &&
- !node.inBundle &&
- node.canReplaceWith(newDep)) {
- // don't prune if the dupe is necessary!
- // root (a, d)
- // +-- a (b, c2)
- // | +-- b (c2) <-- place c2 for b, lands at root
- // +-- d (e)
- // +-- e (c1, d)
- // +-- c1
- // +-- f (c2)
- // +-- c2 <-- pruning this would be bad
-
- const mask = node.parent !== target &&
- node.parent &&
- node.parent.parent &&
- node.parent.parent !== target &&
- node.parent.parent.resolve(newDep.name)
-
- if (!mask || mask === newDep || node.canReplaceWith(mask))
- node.parent = null
- }
+ if (node.isDescendantOf(target))
+ this[_pruneDedupable](node, false)
}
}
@@ -1460,6 +1464,21 @@ This is a one-time fix-up, please be patient...
return placed
}
+ // prune all the nodes in a branch of the tree that can be safely removed
+ // This is only the most basic duplication detection; it finds if there
+ // is another satisfying node further up the tree, and if so, dedupes.
+ // Even in legacyBundling mode, we do this amount of deduplication.
+ [_pruneDedupable] (node, descend = true) {
+ if (node.canDedupe(this[_preferDedupe])) {
+ node.root = null
+ return
+ }
+ if (descend) {
+ for (const child of node.children.values())
+ this[_pruneDedupable](child)
+ }
+ }
+
[_pruneForReplacement] (node, oldDeps) {
// gather up all the invalid edgesOut, and any now-extraneous
// deps that the new node doesn't depend on but the old one did.
@@ -1612,32 +1631,137 @@ This is a one-time fix-up, please be patient...
// placed here as well. the virtualRoot already has the appropriate
// overrides applied.
if (peerEntryEdge) {
- const peerSet = getPeerSet(current)
- OUTER: for (const p of peerSet) {
- // if any have a non-peer dep from the target, or a peer dep if
- // the target is root, then cannot safely replace and dupe deeper.
+ const currentPeerSet = getPeerSet(current)
+
+ // We are effectively replacing currentPeerSet with newPeerSet
+ // If there are any non-peer deps coming into the currentPeerSet,
+ // which are currently valid, and are from the target, then that
+ // means that we have to ensure that they're not going to be made
+ // invalid by putting the newPeerSet in place.
+ // If the edge comes from somewhere deeper than the target, then
+ // that's fine, because we'll create an invalid edge, detect it,
+ // and duplicate the node further into the tree.
+ // loop through the currentPeerSet checking for valid edges on
+ // the members of the peer set which will be made invalid.
+ const targetEdges = new Set()
+ for (const p of currentPeerSet) {
for (const edge of p.edgesIn) {
- if (peerSet.has(edge.from))
+ // edge from within the peerSet, ignore
+ if (currentPeerSet.has(edge.from))
continue
+ // only care about valid edges from target.
+ // edges from elsewhere can dupe if offended, invalid edges
+ // are already being fixed or will be later.
+ if (edge.from !== target || !edge.valid)
+ continue
+ targetEdges.add(edge)
+ }
+ }
- // only respect valid edges, however, since we're likely trying
- // to fix the very one that's currently broken! If the virtual
- // root's replacement is ok, and doesn't have any invalid edges
- // indicating that it was an overridden peer, then ignore the
- // conflict and continue. If it WAS an override, then we need
- // to get the conflict here so that we can decide whether to
- // accept the current dep node, clobber it, or fail the install.
- if (edge.from === target && edge.valid) {
- const rep = dep.parent.children.get(edge.name)
- const override = rep && ([...rep.edgesIn].some(e => !e.valid))
- if (!rep || !rep.satisfies(edge) || override) {
+ for (const edge of targetEdges) {
+ // see if we intend to replace this one anyway
+ const rep = dep.parent.children.get(edge.name)
+ const current = edge.to
+ if (!rep) {
+ // this isn't one we're replacing. but it WAS included in the
+ // peerSet for some reason, so make sure that it's still
+ // ok with the replacements in the new peerSet
+ for (const curEdge of current.edgesOut.values()) {
+ const newRepDep = dep.parent.children.get(curEdge.name)
+ if (curEdge.valid && newRepDep && !newRepDep.satisfies(curEdge)) {
canReplace = false
- break OUTER
+ break
}
}
+ continue
+ }
+
+ // was this replacement already an override of some sort?
+ const override = [...rep.edgesIn].some(e => !e.valid)
+ // if we have a rep, and it's ok to put in this location, and
+ // it's not already part of an override in the peerSet, then
+ // we can continue with it.
+ if (rep.satisfies(edge) && !override)
+ continue
+ // Otherwise, we cannot replace.
+ canReplace = false
+ break
+ }
+ // if we're going to be replacing the peerSet, we have to remove
+ // and re-resolve any members of the old peerSet that are not
+ // present in the new one, and which will have invalid edges.
+ // We know that they're not depended upon by the target, or else
+ // they would have caused a conflict, so they'll get landed deeper
+ // in the tree, if possible.
+ if (canReplace) {
+ let needNesting = false
+ OUTER: for (const node of currentPeerSet) {
+ const rep = dep.parent.children.get(node.name)
+ // has a replacement, already addressed above
+ if (rep)
+ continue
+
+ // ok, it has been placed here to dedupe, see if it needs to go
+ // back deeper within the tree.
+ for (const edge of node.edgesOut.values()) {
+ const repDep = dep.parent.children.get(edge.name)
+ // not in new peerSet, maybe fine.
+ if (!repDep)
+ continue
+
+ // new thing will be fine, no worries
+ if (repDep.satisfies(edge))
+ continue
+
+ // uhoh, we'll have to nest them.
+ needNesting = true
+ break OUTER
+ }
+ }
+
+ // to nest, just delete everything without a target dep
+ // that's in the current peerSet, and add their dependants
+ // to the _depsQueue for evaluation. Some of these MAY end
+ // up in the same location again, and that's fine.
+ if (needNesting) {
+ // avoid mutating the tree while we're examining it
+ const dependants = new Set()
+ const reresolve = new Set()
+ OUTER: for (const node of currentPeerSet) {
+ const rep = dep.parent.children.get(node.name)
+ if (rep)
+ continue
+ // create a separate set for each one, so we can skip any
+ // that might somehow have an incoming target edge
+ const deps = new Set()
+ for (const edge of node.edgesIn) {
+ // a target dep, skip this dep entirely, already addressed
+ // ignoring for coverage, because it really ought to be
+ // impossible, but I can't prove it yet, so this is here
+ // for safety.
+ /* istanbul ignore if - should be impossible */
+ if (edge.from === target)
+ continue OUTER
+ // ignore this edge, it'll either be replaced or re-resolved
+ if (currentPeerSet.has(edge.from))
+ continue
+ // ok, we care about this one.
+ deps.add(edge.from)
+ }
+ reresolve.add(node)
+ for (const d of deps)
+ dependants.add(d)
+ }
+ for (const dependant of dependants) {
+ this[_depsQueue].push(dependant)
+ this[_depsSeen].delete(dependant)
+ }
+ for (const node of reresolve)
+ node.root = null
}
}
}
+
if (canReplace) {
const ret = this[_canPlacePeers](dep, target, edge, REPLACE, peerEntryEdge, peerPath, isSource)
/* istanbul ignore else - extremely rare that the peer set would
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 09a6f700547f21..93b9aa38298208 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/index.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/index.js
@@ -54,7 +54,7 @@ class Arborist extends Base {
...options,
path: options.path || '.',
cache: options.cache || `${homedir()}/.npm/_cacache`,
- packumentCache: new Map(),
+ packumentCache: options.packumentCache || new Map(),
log: options.log || procLog,
}
this.cache = resolve(this.options.cache)
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 3a38905b77433d..2a222249d7a482 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
@@ -93,7 +93,8 @@ module.exports = cls => class VirtualLoader extends cls {
this.virtualTree = root
const {links, nodes} = this[resolveNodes](s, root)
await this[resolveLinks](links, nodes)
- this[assignBundles](nodes)
+ if (!(s.originalLockfileVersion >= 2))
+ this[assignBundles](nodes)
if (this[flagsSuspect])
this[reCalcDepFlags](nodes.values())
return root
@@ -220,22 +221,24 @@ 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)
+ if (!location || node.target && !node.target.location)
continue
const { name, parent, package: { inBundle }} = node
+
if (!parent)
continue
// read inBundle from package because 'package' here is
// actually a v2 lockfile metadata entry.
- // If the *parent* is also bundled, though, then we assume
- // that it's being pulled in just by virtue of that.
+ // If the *parent* is also bundled, though, or if the parent has
+ // no dependency on it, then we assume that it's being pulled in
+ // just by virtue of its parent or a transitive dep being bundled.
const { package: ppkg } = parent
const { inBundle: parentBundled } = ppkg
- if (inBundle && !parentBundled) {
+ if (inBundle && !parentBundled && parent.edgesOut.has(node.name)) {
if (!ppkg.bundleDependencies)
ppkg.bundleDependencies = [name]
- else if (!ppkg.bundleDependencies.includes(name))
+ else
ppkg.bundleDependencies.push(name)
}
}
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 9c52d009d6fd8d..390d3ce42aecd2 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/rebuild.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/rebuild.js
@@ -115,10 +115,6 @@ module.exports = cls => class Builder extends cls {
await this[_runScripts]('preinstall')
if (this[_binLinks] && type !== 'links')
await this[_linkAllBins]()
- if (!this[_ignoreScripts]) {
- await this[_runScripts]('install')
- await this[_runScripts]('postinstall')
- }
// links should also run prepare scripts and only link bins after that
if (type === 'links') {
@@ -128,6 +124,11 @@ module.exports = cls => class Builder extends cls {
await this[_linkAllBins]()
}
+ if (!this[_ignoreScripts]) {
+ await this[_runScripts]('install')
+ await this[_runScripts]('postinstall')
+ }
+
process.emit('timeEnd', `build:${type}`)
}
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 aaaa3d61c862b9..64f08756263c72 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js
@@ -49,7 +49,8 @@ const _loadTrees = Symbol.for('loadTrees')
const _diffTrees = Symbol.for('diffTrees')
const _createSparseTree = Symbol.for('createSparseTree')
const _loadShrinkwrapsAndUpdateTrees = Symbol.for('loadShrinkwrapsAndUpdateTrees')
-const _shrinkwrapUnpacked = Symbol('shrinkwrapUnpacked')
+const _shrinkwrapInflated = Symbol('shrinkwrapInflated')
+const _bundleUnpacked = Symbol('bundleUnpacked')
const _reifyNode = Symbol.for('reifyNode')
const _extractOrLink = Symbol('extractOrLink')
// defined by rebuild mixin
@@ -108,7 +109,7 @@ module.exports = cls => class Reifier extends cls {
this.diff = null
this[_retiredPaths] = {}
- this[_shrinkwrapUnpacked] = new Set()
+ this[_shrinkwrapInflated] = new Set()
this[_retiredUnchanged] = {}
this[_sparseTreeDirs] = new Set()
this[_sparseTreeRoots] = new Set()
@@ -316,6 +317,7 @@ module.exports = cls => class Reifier extends cls {
// find all the nodes that need to change between the actual
// and ideal trees.
this.diff = Diff.calculate({
+ shrinkwrapInflated: this[_shrinkwrapInflated],
filterNodes,
actual: this.actualTree,
ideal: this.idealTree,
@@ -423,7 +425,8 @@ module.exports = cls => class Reifier extends cls {
const dirs = this.diff.leaves
.filter(diff => {
return (diff.action === 'ADD' || diff.action === 'CHANGE') &&
- !this[_sparseTreeDirs].has(diff.ideal.path)
+ !this[_sparseTreeDirs].has(diff.ideal.path) &&
+ !diff.ideal.isLink
})
.map(diff => diff.ideal.path)
@@ -457,9 +460,9 @@ module.exports = cls => class Reifier extends cls {
// we need to unpack them, read that shrinkwrap file, and then update
// the tree by calling loadVirtual with the node as the root.
[_loadShrinkwrapsAndUpdateTrees] () {
- const seen = this[_shrinkwrapUnpacked]
+ const seen = this[_shrinkwrapInflated]
const shrinkwraps = this.diff.leaves
- .filter(d => (d.action === 'CHANGE' || d.action === 'ADD') &&
+ .filter(d => (d.action === 'CHANGE' || d.action === 'ADD' || !d.action) &&
d.ideal.hasShrinkwrap && !seen.has(d.ideal) &&
!this[_trashList].has(d.ideal.path))
@@ -472,7 +475,7 @@ module.exports = cls => class Reifier extends cls {
return promiseAllRejectLate(shrinkwraps.map(diff => {
const node = diff.ideal
seen.add(node)
- return this[_reifyNode](node)
+ return diff.action ? this[_reifyNode](node) : node
}))
.then(nodes => promiseAllRejectLate(nodes.map(node => new Arborist({
...this.options,
@@ -503,7 +506,7 @@ module.exports = cls => class Reifier extends cls {
const { npmVersion, nodeVersion } = this.options
const p = Promise.resolve()
- .then(() => {
+ .then(async () => {
// when we reify an optional node, check the engine and platform
// first. be sure to ignore the --force and --engine-strict flags,
// since we always want to skip any optional packages we can't install.
@@ -513,11 +516,11 @@ module.exports = cls => class Reifier extends cls {
checkEngine(node.package, npmVersion, nodeVersion, false)
checkPlatform(node.package, false)
}
+ await this[_checkBins](node)
+ await this[_extractOrLink](node)
+ await this[_warnDeprecated](node)
+ await this[_loadAncientPackageDetails](node)
})
- .then(() => this[_checkBins](node))
- .then(() => this[_extractOrLink](node))
- .then(() => this[_warnDeprecated](node))
- .then(() => this[_loadAncientPackageDetails](node))
return this[_handleOptionalFailure](node, p)
.then(() => {
@@ -563,10 +566,11 @@ module.exports = cls => class Reifier extends cls {
})
}
- [_symlink] (node) {
+ async [_symlink] (node) {
const dir = dirname(node.path)
const target = node.realpath
const rel = relative(dir, target)
+ await mkdirp(dir)
return symlink(rel, node.path, 'junction')
}
@@ -633,8 +637,10 @@ module.exports = cls => class Reifier extends cls {
[_loadBundlesAndUpdateTrees] (
depth = 0, bundlesByDepth = this[_getBundlesByDepth]()
) {
- if (depth === 0)
+ if (depth === 0) {
+ this[_bundleUnpacked] = new Set()
process.emit('time', 'reify:loadBundles')
+ }
const maxBundleDepth = bundlesByDepth.get('maxBundleDepth')
if (depth > maxBundleDepth) {
// if we did something, then prune the tree and update the diffs
@@ -650,13 +656,17 @@ module.exports = cls => class Reifier extends cls {
// shallower bundle overwriting them with a bundled meta-dep.
const set = (bundlesByDepth.get(depth) || [])
.filter(node => node.root === this.idealTree &&
+ node.target !== node.root &&
!this[_trashList].has(node.path))
if (!set.length)
return this[_loadBundlesAndUpdateTrees](depth + 1, bundlesByDepth)
// extract all the nodes with bundles
- return promiseAllRejectLate(set.map(node => this[_reifyNode](node)))
+ return promiseAllRejectLate(set.map(node => {
+ this[_bundleUnpacked].add(node)
+ return this[_reifyNode](node)
+ }))
// then load their unpacked children and move into the ideal tree
.then(nodes =>
promiseAllRejectLate(nodes.map(node => new this.constructor({
@@ -678,8 +688,13 @@ module.exports = cls => class Reifier extends cls {
tree: this.diff,
visit: diff => {
const node = diff.ideal
- if (node && !node.isProjectRoot && node.package.bundleDependencies &&
- node.package.bundleDependencies.length) {
+ if (!node)
+ return
+ if (node.isProjectRoot || (node.target && node.target.isProjectRoot))
+ return
+
+ const { bundleDependencies } = node.package
+ if (bundleDependencies && bundleDependencies.length) {
maxBundleDepth = Math.max(maxBundleDepth, node.depth)
if (!bundlesByDepth.has(node.depth))
bundlesByDepth.set(node.depth, [node])
@@ -784,14 +799,14 @@ module.exports = cls => class Reifier extends cls {
return
const node = diff.ideal
- const bd = node.package.bundleDependencies
- const sw = this[_shrinkwrapUnpacked].has(node)
+ const bd = this[_bundleUnpacked].has(node)
+ const sw = this[_shrinkwrapInflated].has(node)
// check whether we still need to unpack this one.
// test the inDepBundle last, since that's potentially a tree walk.
const doUnpack = node && // can't unpack if removed!
!node.isRoot && // root node already exists
- !(bd && bd.length) && // already unpacked to read bundle
+ !bd && // already unpacked to read bundle
!sw && // already unpacked to read sw
!node.inDepBundle // already unpacked by another dep's bundle
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/debug.js b/deps/npm/node_modules/@npmcli/arborist/lib/debug.js
index 5acacee69e2232..aeda7229d5e8cb 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/debug.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/debug.js
@@ -12,6 +12,7 @@
// run in debug mode if explicitly requested, running arborist tests,
// or working in the arborist project directory.
+
const debug = process.env.ARBORIST_DEBUG !== '0' && (
process.env.ARBORIST_DEBUG === '1' ||
/\barborist\b/.test(process.env.NODE_DEBUG || '') ||
@@ -21,4 +22,10 @@ const debug = process.env.ARBORIST_DEBUG !== '0' && (
)
module.exports = debug ? fn => fn() : () => {}
-module.exports.log = (...msg) => module.exports(() => console.error(...msg))
+const red = process.stderr.isTTY ? msg => `\x1B[31m${msg}\x1B[39m` : m => m
+module.exports.log = (...msg) => module.exports(() => {
+ const { format } = require('util')
+ const prefix = `\n${process.pid} ${red(format(msg.shift()))} `
+ msg = (prefix + format(...msg).trim().split('\n').join(prefix)).trim()
+ console.error(msg)
+})
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/diff.js b/deps/npm/node_modules/@npmcli/arborist/lib/diff.js
index 84a8bae412f54d..ff58ea76ee7849 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/diff.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/diff.js
@@ -11,8 +11,9 @@ const {existsSync} = require('fs')
const ssri = require('ssri')
class Diff {
- constructor ({actual, ideal, filterSet}) {
+ constructor ({actual, ideal, filterSet, shrinkwrapInflated}) {
this.filterSet = filterSet
+ this.shrinkwrapInflated = shrinkwrapInflated
this.children = []
this.actual = actual
this.ideal = ideal
@@ -30,7 +31,7 @@ class Diff {
this.removed = []
}
- static calculate ({actual, ideal, filterNodes = []}) {
+ static calculate ({actual, ideal, filterNodes = [], shrinkwrapInflated = new Set()}) {
// if there's a filterNode, then:
// - get the path from the root to the filterNode. The root or
// root.target should have an edge either to the filterNode or
@@ -77,7 +78,7 @@ class Diff {
}
return depth({
- tree: new Diff({actual, ideal, filterSet}),
+ tree: new Diff({actual, ideal, filterSet, shrinkwrapInflated}),
getChildren,
leave,
})
@@ -135,7 +136,7 @@ const allChildren = node => {
// to create the diff tree
const getChildren = diff => {
const children = []
- const {actual, ideal, unchanged, removed, filterSet} = diff
+ const {actual, ideal, unchanged, removed, filterSet, shrinkwrapInflated} = diff
// Note: we DON'T diff fsChildren themselves, because they are either
// included in the package contents, or part of some other project, and
@@ -144,11 +145,20 @@ const getChildren = diff => {
// responsible for installing.
const actualKids = allChildren(actual)
const idealKids = allChildren(ideal)
+
+ if (ideal && ideal.hasShrinkwrap && !shrinkwrapInflated.has(ideal)) {
+ // Guaranteed to get a diff.leaves here, because we always
+ // be called with a proper Diff object when ideal has a shrinkwrap
+ // that has not been inflated.
+ diff.leaves.push(diff)
+ return children
+ }
+
const paths = new Set([...actualKids.keys(), ...idealKids.keys()])
for (const path of paths) {
const actual = actualKids.get(path)
const ideal = idealKids.get(path)
- diffNode(actual, ideal, children, unchanged, removed, filterSet)
+ diffNode(actual, ideal, children, unchanged, removed, filterSet, shrinkwrapInflated)
}
if (diff.leaves && !children.length)
@@ -157,7 +167,7 @@ const getChildren = diff => {
return children
}
-const diffNode = (actual, ideal, children, unchanged, removed, filterSet) => {
+const diffNode = (actual, ideal, children, unchanged, removed, filterSet, shrinkwrapInflated) => {
if (filterSet.size && !(filterSet.has(ideal) || filterSet.has(actual)))
return
@@ -165,10 +175,10 @@ const diffNode = (actual, ideal, children, unchanged, removed, filterSet) => {
// if it's a match, then get its children
// otherwise, this is the child diff node
- if (action) {
+ if (action || (!shrinkwrapInflated.has(ideal) && ideal.hasShrinkwrap)) {
if (action === 'REMOVE')
removed.push(actual)
- children.push(new Diff({actual, ideal, filterSet}))
+ children.push(new Diff({actual, ideal, filterSet, shrinkwrapInflated}))
} else {
unchanged.push(ideal)
// !*! Weird dirty hack warning !*!
@@ -199,7 +209,7 @@ const diffNode = (actual, ideal, children, unchanged, removed, filterSet) => {
for (const node of bundledChildren)
node.parent = ideal
}
- children.push(...getChildren({actual, ideal, unchanged, removed, filterSet}))
+ children.push(...getChildren({actual, ideal, unchanged, removed, filterSet, shrinkwrapInflated}))
}
}
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/index.js b/deps/npm/node_modules/@npmcli/arborist/lib/index.js
index fd7d8817258ed6..c7b07ce28e4df0 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/index.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/index.js
@@ -3,5 +3,6 @@ module.exports.Arborist = module.exports
module.exports.Node = require('./node.js')
module.exports.Link = require('./link.js')
module.exports.Edge = require('./edge.js')
+module.exports.Shrinkwrap = require('./shrinkwrap.js')
// XXX export the other classes, too. shrinkwrap, diff, etc.
// they're handy!
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/node.js b/deps/npm/node_modules/@npmcli/arborist/lib/node.js
index 197804e0ce0e3f..a54f76afcdf3b3 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/node.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/node.js
@@ -28,6 +28,7 @@
// where we need to quickly find all instances of a given package name within a
// tree.
+const semver = require('semver')
const nameFromFolder = require('@npmcli/name-from-folder')
const Edge = require('./edge.js')
const Inventory = require('./inventory.js')
@@ -885,6 +886,43 @@ class Node {
return node.canReplaceWith(this)
}
+ // return true if it's safe to remove this node, because anything that
+ // is depending on it would be fine with the thing that they would resolve
+ // to if it was removed, or nothing is depending on it in the first place.
+ canDedupe (preferDedupe = false) {
+ // not allowed to mess with shrinkwraps or bundles
+ if (this.inDepBundle || this.inShrinkwrap)
+ return false
+
+ // it's a top level pkg, or a dep of one
+ if (!this.parent || !this.parent.parent)
+ return false
+
+ // no one wants it, remove it
+ if (this.edgesIn.size === 0)
+ return true
+
+ const other = this.parent.parent.resolve(this.name)
+
+ // nothing else, need this one
+ if (!other)
+ return false
+
+ // if it's the same thing, then always fine to remove
+ if (other.matches(this))
+ return true
+
+ // if the other thing can't replace this, then skip it
+ if (!other.canReplace(this))
+ return false
+
+ // if we prefer dedupe, or if the version is greater/equal, take the other
+ if (preferDedupe || semver.gte(other.version, this.version))
+ return true
+
+ return false
+ }
+
satisfies (requested) {
if (requested instanceof Edge)
return this.name === requested.name && requested.satisfiedBy(this)
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/printable.js b/deps/npm/node_modules/@npmcli/arborist/lib/printable.js
index 169984fcf17ea1..79f46a9e93c4a6 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/printable.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/printable.js
@@ -29,6 +29,15 @@ class ArboristNode {
this.peer = true
if (tree.inBundle)
this.bundled = true
+ if (tree.inDepBundle)
+ this.bundler = tree.getBundler().location
+ const bd = tree.package && tree.package.bundleDependencies
+ if (bd && bd.length)
+ this.bundleDependencies = bd
+ if (tree.inShrinkwrap)
+ this.inShrinkwrap = true
+ else if (tree.hasShrinkwrap)
+ this.hasShrinkwrap = true
if (tree.error)
this.error = treeError(tree.error)
if (tree.errors && tree.errors.length)
diff --git a/deps/npm/node_modules/@npmcli/arborist/package.json b/deps/npm/node_modules/@npmcli/arborist/package.json
index d08102ce0cf12d..e7ac932e08d8f3 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.3.0",
+ "version": "2.4.1",
"description": "Manage node_modules trees",
"dependencies": {
"@npmcli/installed-package-contents": "^1.0.7",
@@ -19,7 +19,7 @@
"npm-install-checks": "^4.0.0",
"npm-package-arg": "^8.1.0",
"npm-pick-manifest": "^6.1.0",
- "npm-registry-fetch": "^9.0.0",
+ "npm-registry-fetch": "^10.0.0",
"pacote": "^11.2.6",
"parse-conflict-json": "^1.1.1",
"promise-all-reject-late": "^1.0.0",
@@ -41,8 +41,7 @@
"eslint-plugin-standard": "^4.0.1",
"minify-registry-metadata": "^2.1.0",
"mutate-fs": "^2.1.1",
- "require-inject": "^1.4.4",
- "tap": "^14.11.0",
+ "tap": "^15.0.4",
"tcompare": "^3.0.4"
},
"scripts": {
@@ -76,10 +75,8 @@
"arborist": "bin/index.js"
},
"tap": {
- "100": true,
"after": "test/fixtures/cleanup.js",
"coverage-map": "map.js",
- "esm": false,
"test-env": [
"NODE_OPTIONS=--no-warnings"
],
@@ -87,6 +84,6 @@
"--no-warnings",
"--no-deprecation"
],
- "timeout": "120"
+ "timeout": "240"
}
}
diff --git a/deps/npm/node_modules/@npmcli/config/lib/index.js b/deps/npm/node_modules/@npmcli/config/lib/index.js
index 21a37ded48e7c3..f947896f0ba348 100644
--- a/deps/npm/node_modules/@npmcli/config/lib/index.js
+++ b/deps/npm/node_modules/@npmcli/config/lib/index.js
@@ -197,11 +197,6 @@ class Config {
throw new Error('call config.load() before setting values')
if (!confTypes.has(where))
throw new Error('invalid config location param: ' + where)
- if (key === '_auth') {
- const { email } = this.getCredentialsByURI(this.get('registry'))
- if (!email)
- throw new Error('Cannot set _auth without first setting email')
- }
this[_checkDeprecated](key)
const { data } = this.data.get(where)
data[key] = val
@@ -282,6 +277,14 @@ class Config {
// symbols, as that module also does a bunch of get operations
this[_loaded] = true
+ process.emit('time', 'config:load:credentials')
+ const reg = this.get('registry')
+ const creds = this.getCredentialsByURI(reg)
+ // ignore this error because a failed set will strip out anything that
+ // might be a security hazard, which was the intention.
+ try { this.setCredentialsByURI(reg, creds) } catch (_) {}
+ process.emit('timeEnd', 'config:load:credentials')
+
// set proper globalPrefix now that everything is loaded
this.globalPrefix = this.get('prefix')
@@ -588,14 +591,17 @@ class Config {
const nerfed = nerfDart(uri)
const def = nerfDart(this.get('registry'))
if (def === nerfed) {
+ // do not delete email, that shouldn't be nerfed any more.
+ // just delete the nerfed copy, if one exists.
this.delete(`-authtoken`, 'user')
this.delete(`_authToken`, 'user')
+ this.delete(`_authtoken`, 'user')
this.delete(`_auth`, 'user')
this.delete(`_password`, 'user')
this.delete(`username`, 'user')
- this.delete(`email`, 'user')
}
this.delete(`${nerfed}:-authtoken`, 'user')
+ this.delete(`${nerfed}:_authtoken`, 'user')
this.delete(`${nerfed}:_authToken`, 'user')
this.delete(`${nerfed}:_auth`, 'user')
this.delete(`${nerfed}:_password`, 'user')
@@ -603,7 +609,7 @@ class Config {
this.delete(`${nerfed}:email`, 'user')
}
- setCredentialsByURI (uri, { token, username, password, email, alwaysAuth }) {
+ setCredentialsByURI (uri, { token, username, password, email }) {
const nerfed = nerfDart(uri)
const def = nerfDart(this.get('registry'))
@@ -611,41 +617,45 @@ class Config {
// remove old style auth info not limited to a single registry
this.delete('_password', 'user')
this.delete('username', 'user')
- this.delete('email', 'user')
this.delete('_auth', 'user')
this.delete('_authtoken', 'user')
+ this.delete('-authtoken', 'user')
this.delete('_authToken', 'user')
}
- this.delete(`${nerfed}:-authtoken`)
+ // email used to be nerfed always. if we're using the default
+ // registry, de-nerf it.
+ if (nerfed === def) {
+ email = email ||
+ this.get('email', 'user') ||
+ this.get(`${nerfed}:email`, 'user')
+ if (email)
+ this.set('email', email, 'user')
+ }
+
+ // field that hasn't been used as documented for a LONG time,
+ // and as of npm 7.10.0, isn't used at all. We just always
+ // send auth if we have it, only to the URIs under the nerf dart.
+ this.delete(`${nerfed}:always-auth`, 'user')
+
+ this.delete(`${nerfed}:-authtoken`, 'user')
+ this.delete(`${nerfed}:_authtoken`, 'user')
+ this.delete(`${nerfed}:email`, 'user')
if (token) {
this.set(`${nerfed}:_authToken`, token, 'user')
this.delete(`${nerfed}:_password`, 'user')
this.delete(`${nerfed}:username`, 'user')
- this.delete(`${nerfed}:email`, 'user')
- this.delete(`${nerfed}:always-auth`, 'user')
- } else if (username || password || email) {
- if (username || password) {
- if (!username)
- throw new Error('must include username')
- if (!password)
- throw new Error('must include password')
- }
- if (!email)
- throw new Error('must include email')
+ } else if (username || password) {
+ if (!username)
+ throw new Error('must include username')
+ if (!password)
+ throw new Error('must include password')
this.delete(`${nerfed}:_authToken`, 'user')
- if (username || password) {
- this.set(`${nerfed}:username`, username, 'user')
- // note: not encrypted, no idea why we bothered to do this, but oh well
- // protects against shoulder-hacks if password is memorable, I guess?
- const encoded = Buffer.from(password, 'utf8').toString('base64')
- this.set(`${nerfed}:_password`, encoded, 'user')
- }
- this.set(`${nerfed}:email`, email, 'user')
- if (alwaysAuth !== undefined)
- this.set(`${nerfed}:always-auth`, alwaysAuth, 'user')
- else
- this.delete(`${nerfed}:always-auth`, 'user')
+ this.set(`${nerfed}:username`, username, 'user')
+ // note: not encrypted, no idea why we bothered to do this, but oh well
+ // protects against shoulder-hacks if password is memorable, I guess?
+ const encoded = Buffer.from(password, 'utf8').toString('base64')
+ this.set(`${nerfed}:_password`, encoded, 'user')
} else {
throw new Error('No credentials to set.')
}
@@ -656,18 +666,12 @@ class Config {
const nerfed = nerfDart(uri)
const creds = {}
- // you can set always-auth for a single registry, or as a default
- const alwaysAuthReg = this.get(`${nerfed}:always-auth`)
- if (alwaysAuthReg !== undefined)
- creds.alwaysAuth = !!alwaysAuthReg
- else
- creds.alwaysAuth = this.get('always-auth')
-
const email = this.get(`${nerfed}:email`) || this.get('email')
if (email)
creds.email = email
const tokenReg = this.get(`${nerfed}:_authToken`) ||
+ this.get(`${nerfed}:_authtoken`) ||
this.get(`${nerfed}:-authtoken`) ||
nerfed === nerfDart(this.get('registry')) && this.get('_authToken')
@@ -686,6 +690,16 @@ class Config {
return creds
}
+ const authReg = this.get(`${nerfed}:_auth`)
+ if (authReg) {
+ const authDecode = Buffer.from(authReg, 'base64').toString('utf8')
+ const authSplit = authDecode.split(':')
+ creds.username = authSplit.shift()
+ creds.password = authSplit.join(':')
+ creds.auth = authReg
+ return creds
+ }
+
// at this point, we can only use the values if the URI is the
// default registry.
const defaultNerf = nerfDart(this.get('registry'))
diff --git a/deps/npm/node_modules/@npmcli/config/package.json b/deps/npm/node_modules/@npmcli/config/package.json
index 767718a9d61c75..f80669640ebd4e 100644
--- a/deps/npm/node_modules/@npmcli/config/package.json
+++ b/deps/npm/node_modules/@npmcli/config/package.json
@@ -1,6 +1,6 @@
{
"name": "@npmcli/config",
- "version": "2.1.0",
+ "version": "2.2.0",
"files": [
"lib"
],
@@ -24,7 +24,7 @@
"coverage-map": "map.js"
},
"devDependencies": {
- "tap": "^14.10.8"
+ "tap": "^15.0.4"
},
"dependencies": {
"ini": "^2.0.0",
diff --git a/deps/npm/node_modules/@npmcli/run-script/README.md b/deps/npm/node_modules/@npmcli/run-script/README.md
index 59b473d94706c5..ff8f5d354718c3 100644
--- a/deps/npm/node_modules/@npmcli/run-script/README.md
+++ b/deps/npm/node_modules/@npmcli/run-script/README.md
@@ -103,7 +103,7 @@ terminal, then it is up to the user to end it, of course.
- The `package.json` fields described in
[RFC183](https://github.com/npm/rfcs/pull/183/files).
- `scriptShell` Optional, defaults to `/bin/sh` on Unix, defaults to
- `env.comspec` or `cmd` on Windows. Custom script to use to execute the
+ `env.ComSpec` or `cmd` on Windows. Custom script to use to execute the
command.
- `stdio` Optional, defaults to `'pipe'`. The same as the `stdio` argument
passed to `child_process` functions in Node.js. Note that if a stdio
diff --git a/deps/npm/node_modules/@npmcli/run-script/lib/make-spawn-args.js b/deps/npm/node_modules/@npmcli/run-script/lib/make-spawn-args.js
index 8ee24c06daf7b1..8f299954a7a801 100644
--- a/deps/npm/node_modules/@npmcli/run-script/lib/make-spawn-args.js
+++ b/deps/npm/node_modules/@npmcli/run-script/lib/make-spawn-args.js
@@ -8,7 +8,7 @@ const makeSpawnArgs = options => {
const {
event,
path,
- scriptShell = isWindows ? process.env.comspec || 'cmd' : 'sh',
+ scriptShell = isWindows ? process.env.ComSpec || 'cmd' : 'sh',
env = {},
stdio,
cmd,
diff --git a/deps/npm/node_modules/@npmcli/run-script/package.json b/deps/npm/node_modules/@npmcli/run-script/package.json
index 7e0e5255de4105..756f87f1d4d380 100644
--- a/deps/npm/node_modules/@npmcli/run-script/package.json
+++ b/deps/npm/node_modules/@npmcli/run-script/package.json
@@ -1,6 +1,6 @@
{
"name": "@npmcli/run-script",
- "version": "1.8.4",
+ "version": "1.8.5",
"description": "Run a lifecycle script for a package (descendant of npm-lifecycle)",
"author": "Isaac Z. Schlueter (https://izs.me)",
"license": "ISC",
@@ -25,7 +25,7 @@
"eslint-plugin-standard": "^5.0.0",
"minipass": "^3.1.1",
"require-inject": "^1.4.4",
- "tap": "^14.11.0"
+ "tap": "^15.0.4"
},
"dependencies": {
"@npmcli/node-gyp": "^1.0.2",
diff --git a/deps/npm/node_modules/balanced-match/.github/FUNDING.yml b/deps/npm/node_modules/balanced-match/.github/FUNDING.yml
new file mode 100644
index 00000000000000..cea8b16e9edc40
--- /dev/null
+++ b/deps/npm/node_modules/balanced-match/.github/FUNDING.yml
@@ -0,0 +1,2 @@
+tidelift: "npm/balanced-match"
+patreon: juliangruber
diff --git a/deps/npm/node_modules/chalk/package.json b/deps/npm/node_modules/chalk/package.json
index 0d99f0f28621f2..c2d63f67e5e955 100644
--- a/deps/npm/node_modules/chalk/package.json
+++ b/deps/npm/node_modules/chalk/package.json
@@ -1,6 +1,6 @@
{
"name": "chalk",
- "version": "4.1.0",
+ "version": "4.1.1",
"description": "Terminal string styling done right",
"license": "MIT",
"repository": "chalk/chalk",
diff --git a/deps/npm/node_modules/chalk/readme.md b/deps/npm/node_modules/chalk/readme.md
index 338f42cb8b525b..851259216bc193 100644
--- a/deps/npm/node_modules/chalk/readme.md
+++ b/deps/npm/node_modules/chalk/readme.md
@@ -13,6 +13,48 @@
+
+
+---
+
+
+
+---
+
+
+
## Highlights
- Expressive API
diff --git a/deps/npm/node_modules/init-package-json/default-input.js b/deps/npm/node_modules/init-package-json/default-input.js
index 8e9fe0b573ea5f..d1f65841d6c5a3 100644
--- a/deps/npm/node_modules/init-package-json/default-input.js
+++ b/deps/npm/node_modules/init-package-json/default-input.js
@@ -12,7 +12,7 @@ function isTestPkg (p) {
}
function niceName (n) {
- return n.replace(/^node-|[.-]js$/g, '').replace(' ', '-').toLowerCase()
+ return n.replace(/^node-|[.-]js$/g, '').replace(/\s+/g, ' ').replace(/ /g, '-').toLowerCase()
}
function readDeps (test, excluded) { return function (cb) {
@@ -45,7 +45,7 @@ function readDeps (test, excluded) { return function (cb) {
})
}}
-var name = package.name || basename
+var name = niceName(package.name || basename)
var spec
try {
spec = npa(name)
@@ -61,7 +61,7 @@ if (scope) {
name = scope + '/' + name
}
}
-exports.name = yes ? name : prompt('package name', niceName(name), function (data) {
+exports.name = yes ? name : prompt('package name', name, function (data) {
var its = validateName(data)
if (its.validForNewPackages) return data
var errors = (its.errors || []).concat(its.warnings || [])
diff --git a/deps/npm/node_modules/init-package-json/package.json b/deps/npm/node_modules/init-package-json/package.json
index 91c6bfba82049d..584e313b4c2c7c 100644
--- a/deps/npm/node_modules/init-package-json/package.json
+++ b/deps/npm/node_modules/init-package-json/package.json
@@ -1,6 +1,6 @@
{
"name": "init-package-json",
- "version": "2.0.2",
+ "version": "2.0.3",
"main": "init-package-json.js",
"scripts": {
"test": "tap",
@@ -17,19 +17,19 @@
"description": "A node module to get your node module started",
"dependencies": {
"glob": "^7.1.1",
- "npm-package-arg": "^8.1.0",
+ "npm-package-arg": "^8.1.2",
"promzard": "^0.3.0",
"read": "~1.0.1",
- "read-package-json": "^3.0.0",
- "semver": "^7.3.2",
+ "read-package-json": "^3.0.1",
+ "semver": "^7.3.5",
"validate-npm-package-license": "^3.0.4",
"validate-npm-package-name": "^3.0.0"
},
"devDependencies": {
- "@npmcli/config": "^1.2.1",
+ "@npmcli/config": "^2.1.0",
"mkdirp": "^1.0.4",
"rimraf": "^3.0.2",
- "tap": "^14.10.8"
+ "tap": "^14.11.0"
},
"engines": {
"node": ">=10"
diff --git a/deps/npm/node_modules/just-diff/index.d.ts b/deps/npm/node_modules/just-diff/index.d.ts
new file mode 100644
index 00000000000000..cd3126daeb3aed
--- /dev/null
+++ b/deps/npm/node_modules/just-diff/index.d.ts
@@ -0,0 +1,20 @@
+// Definitions by: Cameron Hunter
+// Modified by: Angus Croll
+type Operation = "add" | "replace" | "remove";
+
+type JSONPatchPathConverter