deps: upgrade npm to 7.11.2

PR-URL: https://github.com/nodejs/node/pull/38475
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Richard Lau <rlau@redhat.com>
This commit is contained in:
Ruy Adorno 2021-04-29 16:30:06 -04:00
parent ff4e782c08
commit c975dff3c0
No known key found for this signature in database
GPG Key ID: 97B01419BD92F80A
112 changed files with 2878 additions and 1001 deletions

2
deps/npm/AUTHORS vendored
View File

@ -770,3 +770,5 @@ Yash Singh <saiansh2525@gmail.com>
Danielle Church <dani.church@gmail.com>
Seth Thomas <seth@emailseth.com>
Andreas <andreas@bielk.se>
Felipe Santos <felipecassiors@gmail.com>
Luigi Pinca <luigipinca@gmail.com>

122
deps/npm/CHANGELOG.md vendored
View File

@ -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

View File

@ -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'`

View File

@ -11,7 +11,7 @@ npm exec -- <pkg>[@<version>] [args...]
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...]
@ -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)

View File

@ -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>/]<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
@ -18,19 +19,16 @@ npm init [<@scope>/]<name> (same as `npx [<@scope>/]create-<name>`)
package.
`initializer` in this case is an npm package named `create-<initializer>`,
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=<url> -- --hello -a`
- `npm exec -y --registry=<url> -- 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 <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:
```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 <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`](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)

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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 <pkg>` commands.
#### `searchexclude`

View File

@ -141,11 +141,11 @@ npm command-line interface
<section id="table_of_contents">
<h2 id="table-of-contents">Table of contents</h2>
<div id="_table_of_contents"><ul><li><a href="#synopsis">Synopsis</a></li><li><a href="#description">Description</a></li><li><a href="#configuration">Configuration</a></li><ul><li><a href="#registry">registry</a></li><li><a href="#scope">scope</a></li><li><a href="#always-auth">always-auth</a></li><li><a href="#auth-type">auth-type</a></li></ul><li><a href="#see-also">See Also</a></li></ul></div>
<div id="_table_of_contents"><ul><li><a href="#synopsis">Synopsis</a></li><li><a href="#description">Description</a></li><li><a href="#configuration">Configuration</a></li><ul><li><a href="#registry">registry</a></li><li><a href="#scope">scope</a></li><li><a href="#auth-type">auth-type</a></li></ul><li><a href="#see-also">See Also</a></li></ul></div>
</section>
<div id="_content"><h3 id="synopsis">Synopsis</h3>
<pre lang="bash"><code>npm adduser [--registry=url] [--scope=@orgname] [--always-auth] [--auth-type=legacy]
<pre lang="bash"><code>npm adduser [--registry=url] [--scope=@orgname] [--auth-type=legacy]
aliases: login, add-user
</code></pre>
@ -177,17 +177,6 @@ e.g.</p>
</code></pre>
<p>This will set a registry for the given scope and login or create a user for
that registry at the same time.</p>
<h4 id="always-auth">always-auth</h4>
<p>Default: false</p>
<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 <code>--registry</code> and / or <code>--scope</code>, e.g.</p>
<pre lang="bash"><code>npm adduser --registry=http://private-registry.example.com --always-auth
</code></pre>
<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 <code>always-auth</code> in <a href="../using-npm/config.html"><code>config</code></a> for more details on always-auth. Registry-specific configuration of <code>always-auth</code> takes precedence over any global configuration.</p>
<h4 id="auth-type">auth-type</h4>
<ul>
<li>Default: <code>'legacy'</code></li>

View File

@ -149,7 +149,7 @@ npm command-line interface
npm exec --package=&lt;pkg&gt;[@&lt;version&gt;] -- &lt;cmd&gt; [args...]
npm exec -c '&lt;cmd&gt; [args...]'
npm exec --package=foo -c '&lt;cmd&gt; [args...]'
npm exec [-ws] [-w &lt;workspace-name] [args...]
npm exec [--ws] [-w &lt;workspace-name] [args...]
npx &lt;pkg&gt;[@&lt;specifier&gt;] [args...]
npx -p &lt;pkg&gt;[@&lt;specifier&gt;] &lt;cmd&gt; [args...]
@ -276,7 +276,7 @@ at a time.</p>
the configured workspaces when using the <code>workspaces</code> configuration options,
in this example were using <strong>eslint</strong> to lint any js file found within each
workspace folder:</p>
<pre><code>npm exec -ws -- eslint ./*.js
<pre><code>npm exec --ws -- eslint ./*.js
</code></pre>
<h4 id="filtering-workspaces">Filtering workspaces</h4>
<p>Its also possible to execute a command in a single workspace using the
@ -348,7 +348,7 @@ children workspaces)</li>
</ul>
<h4 id="workspaces">workspaces</h4>
<ul>
<li>Alias: <code>-ws</code></li>
<li>Alias: <code>--ws</code></li>
<li>Type: Boolean</li>
<li>Default: <code>false</code></li>
</ul>
@ -363,6 +363,7 @@ project.</p>
<li><a href="../commands/npm-restart.html">npm restart</a></li>
<li><a href="../commands/npm-stop.html">npm stop</a></li>
<li><a href="../commands/npm-config.html">npm config</a></li>
<li><a href="../using-npm/workspaces.html">npm workspaces</a></li>
</ul>
</div>

View File

@ -141,29 +141,29 @@ npm command-line interface
<section id="table_of_contents">
<h2 id="table-of-contents">Table of contents</h2>
<div id="_table_of_contents"><ul><li><a href="#synopsis">Synopsis</a></li><li><a href="#description">Description</a></li><li><a href="#examples">Examples</a></li><li><a href="#a-note-on-caching">A note on caching</a></li><ul><li><a href="#prefer-online">prefer-online</a></li><li><a href="#prefer-offline">prefer-offline</a></li><li><a href="#offline">offline</a></li></ul><li><a href="#see-also">See Also</a></li></ul></div>
<div id="_table_of_contents"><ul><li><a href="#synopsis">Synopsis</a></li><li><a href="#description">Description</a></li><ul><li><a href="#forwarding-additional-options">Forwarding additional options</a></li></ul><li><a href="#examples">Examples</a></li><li><a href="#workspaces-support">Workspaces support</a></li><li><a href="#a-note-on-caching">A note on caching</a></li><ul><li><a href="#prefer-online">prefer-online</a></li><li><a href="#prefer-offline">prefer-offline</a></li><li><a href="#offline">offline</a></li><li><a href="#workspace">workspace</a></li><li><a href="#workspaces">workspaces</a></li></ul><li><a href="#see-also">See Also</a></li></ul></div>
</section>
<div id="_content"><h3 id="synopsis">Synopsis</h3>
<pre lang="bash"><code>npm init [--force|-f|--yes|-y|--scope]
npm init &lt;@scope&gt; (same as `npx &lt;@scope&gt;/create`)
npm init [&lt;@scope&gt;/]&lt;name&gt; (same as `npx [&lt;@scope&gt;/]create-&lt;name&gt;`)
npm init &lt;@scope&gt; (same as `npm exec &lt;@scope&gt;/create`)
npm init [&lt;@scope&gt;/]&lt;name&gt; (same as `npm exec [&lt;@scope&gt;/]create-&lt;name&gt;`)
npm init [-w &lt;dir&gt;] [args...]
</code></pre>
<h3 id="description">Description</h3>
<p><code>npm init &lt;initializer&gt;</code> can be used to set up a new or existing npm
package.</p>
<p><code>initializer</code> in this case is an npm package named <code>create-&lt;initializer&gt;</code>,
which will be installed by <a href="https://npm.im/npx"><code>npx</code></a>, and then have its
which will be installed by <a href="../commands/npm-exec.html"><code>npm-exec</code></a>, and then have its
main bin executed presumably creating or updating <code>package.json</code> and
running any other initialization-related operations.</p>
<p>The init command is transformed to a corresponding <code>npx</code> operation as
<p>The init command is transformed to a corresponding <code>npm exec</code> operation as
follows:</p>
<ul>
<li><code>npm init foo</code> -&gt; <code>npx create-foo</code></li>
<li><code>npm init @usr/foo</code> -&gt; <code>npx @usr/create-foo</code></li>
<li><code>npm init @usr</code> -&gt; <code>npx @usr/create</code></li>
<li><code>npm init foo</code> -&gt; <code>npm exec create-foo</code></li>
<li><code>npm init @usr/foo</code> -&gt; <code>npm exec @usr/create-foo</code></li>
<li><code>npm init @usr</code> -&gt; <code>npm exec @usr/create</code></li>
</ul>
<p>Any additional options will be passed directly to the command, so <code>npm init foo -- --hello</code> will map to <code>npx create-foo --hello</code>.</p>
<p>If the initializer is omitted (by just calling <code>npm init</code>), 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 @@ 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 <code>-y</code>/<code>--yes</code> to skip the questionnaire altogether. If
you pass <code>--scope</code>, it will create a scoped package.</p>
<h4 id="forwarding-additional-options">Forwarding additional options</h4>
<p>Any additional options will be passed directly to the command, so <code>npm init foo -- --hello</code> will map to <code>npm exec -- create-foo --hello</code>.</p>
<p>To better illustrate how options are forwarded, heres a more evolved
example showing options passed to both the <strong>npm cli</strong> and a create package,
both following commands are equivalent:</p>
<ul>
<li><code>npm init foo -y --registry=&lt;url&gt; -- --hello -a</code></li>
<li><code>npm exec -y --registry=&lt;url&gt; -- create-foo --hello -a</code></li>
</ul>
<h3 id="examples">Examples</h3>
<p>Create a new React-based project using
<a href="https://npm.im/create-react-app"><code>create-react-app</code></a>:</p>
@ -189,6 +198,51 @@ $ npm init
<p>Generate it without having it ask any questions:</p>
<pre lang="bash"><code>$ npm init -y
</code></pre>
<h3 id="workspaces-support">Workspaces support</h3>
<p>Its possible to create a new workspace within your project by using the
<code>workspace</code> config option. When using <code>npm init -w &lt;dir&gt;</code> the cli will
create the folders and boilerplate expected while also adding a reference
to your project <code>package.json</code> <code>"workspaces": []</code> property in order to make
sure that new generated <strong>workspace</strong> is properly set up as such.</p>
<p>Given a project with no workspaces, e.g:</p>
<pre><code>.
+-- package.json
</code></pre>
<p>You may generate a new workspace using the legacy init:</p>
<pre lang="bash"><code>$ npm init -w packages/a
</code></pre>
<p>That will generate a new folder and <code>package.json</code> file, while also updating
your top-level <code>package.json</code> to add the reference to this new workspace:</p>
<pre><code>.
+-- package.json
`-- packages
`-- a
`-- package.json
</code></pre>
<p>The workspaces init also supports the <code>npm init &lt;initializer&gt; -w &lt;dir&gt;</code>
syntax, following the same set of rules explained earlier in the initial
<strong>Description</strong> section of this page. Similar to the previous example of
creating a new React-based project using
<a href="https://npm.im/create-react-app"><code>create-react-app</code></a>, the following syntax
will make sure to create the new react app as a nested <strong>workspace</strong> within your
project and configure your <code>package.json</code> to recognize it as such:</p>
<pre lang="bash"><code>npm init -w packages/my-react-app react-app .
</code></pre>
<p>This will make sure to generate your react app as expected, one important
consideration to have in mind is that <code>npm exec</code> is going to be run in the
context of the newly created folder for that workspace, and thats 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: <code>react-app .</code>:</p>
<pre><code>.
+-- package.json
`-- packages
+-- a
| `-- package.json
`-- my-react-app
+-- README
+-- package.json
`-- ...
</code></pre>
<h3 id="a-note-on-caching">A note on caching</h3>
<p>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 @@ requested from the server. To force full offline mode, use <code>offline</code>.
<h4 id="offline">offline</h4>
<p>Forces full offline mode. Any packages not locally cached will result in
an error.</p>
<h4 id="workspace">workspace</h4>
<ul>
<li>Alias: <code>-w</code></li>
<li>Type: Array</li>
<li>Default: <code>[]</code></li>
</ul>
<p>Enable running <code>npm init</code> in the context of workspaces, creating any missing
folders, generating files and adding/updating the <code>"workspaces"</code> property of
the project <code>package.json</code>.</p>
<p>the provided names or paths provided.</p>
<p>Valid values for the <code>workspace</code> config are either:</p>
<ul>
<li>Workspace names</li>
<li>Path to a workspace directory</li>
<li>Path to a parent workspace directory (will result to selecting all of the
children workspaces)</li>
</ul>
<h4 id="workspaces">workspaces</h4>
<ul>
<li>Alias: <code>-ws</code></li>
<li>Type: Boolean</li>
<li>Default: <code>false</code></li>
</ul>
<p>Run <code>npm init</code> in the context of all configured workspaces for the
current project.</p>
<h3 id="see-also">See Also</h3>
<ul>
<li><a href="http://npm.im/init-package-json">init-package-json module</a></li>
@ -210,6 +289,7 @@ an error.</p>
<li><a href="../commands/npm-version.html">npm version</a></li>
<li><a href="../using-npm/scope.html">npm scope</a></li>
<li><a href="../commands/npm-exec.html">npm exec</a></li>
<li><a href="../using-npm/workspaces.html">npm workspaces</a></li>
</ul>
</div>

View File

@ -159,7 +159,7 @@ tree at all, use <a href="../commands/npm-explain.html"><code>npm explain</code>
the results to only the paths to the packages named. Note that nested
packages will <em>also</em> show the paths to the specified packages. For
example, running <code>npm ls promzard</code> in npms source tree will show:</p>
<pre lang="bash"><code>npm@7.10.0 /path/to/npm
<pre lang="bash"><code>npm@7.11.2 /path/to/npm
└─┬ init-package-json@0.0.4
└── promzard@0.1.5
</code></pre>

View File

@ -282,7 +282,7 @@ children workspaces)</li>
</ul>
<h4 id="workspaces">workspaces</h4>
<ul>
<li>Alias: <code>-ws</code></li>
<li>Alias: <code>--ws</code></li>
<li>Type: Boolean</li>
<li>Default: <code>false</code></li>
</ul>
@ -296,6 +296,7 @@ project.</p>
<li><a href="../commands/npm-restart.html">npm restart</a></li>
<li><a href="../commands/npm-stop.html">npm stop</a></li>
<li><a href="../commands/npm-config.html">npm config</a></li>
<li><a href="../using-npm/workspaces.html">npm workspaces</a></li>
</ul>
</div>

View File

@ -141,7 +141,7 @@ npm command-line interface
<section id="table_of_contents">
<h2 id="table-of-contents">Table of contents</h2>
<div id="_table_of_contents"><ul><li><a href="#synopsis">Synopsis</a></li><li><a href="#description">Description</a></li><li><a href="#output">Output</a></li><li><a href="#see-also">See Also</a></li></ul></div>
<div id="_table_of_contents"><ul><li><a href="#synopsis">Synopsis</a></li><li><a href="#description">Description</a></li><li><a href="#configuration">Configuration</a></li><ul><li><a href="#json">json</a></li><li><a href="#workspaces">workspaces</a></li><li><a href="#workspace">workspace</a></li></ul><li><a href="#output">Output</a></li><li><a href="#see-also">See Also</a></li></ul></div>
</section>
<div id="_content"><h3 id="synopsis">Synopsis</h3>
@ -198,6 +198,17 @@ was required by each matching version of <code>yui3</code>:</p>
this:</p>
<pre lang="bash"><code>npm view connect versions
</code></pre>
<h3 id="configuration">Configuration</h3>
<h4 id="json">json</h4>
<p>Show information in JSON format. See <a href="#output"><code>Output</code></a> below.</p>
<h4 id="workspaces">workspaces</h4>
<p>Enables workspaces context while searching the <code>package.json</code> in the
current folder. Information about packages named in each workspace will
be viewed.</p>
<h4 id="workspace">workspace</h4>
<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.</p>
<h3 id="output">Output</h3>
<p>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

View File

@ -148,7 +148,7 @@ npm command-line interface
<pre lang="bash"><code>npm &lt;command&gt; [args]
</code></pre>
<h3 id="version">Version</h3>
<p>7.10.0</p>
<p>7.11.2</p>
<h3 id="description">Description</h3>
<p>npm is the package manager for the Node JavaScript platform. It puts
modules in place so that node can find them, and manages dependency

View File

@ -435,6 +435,7 @@ package, then you can just supply it as a string. For example:</p>
<p>Please make sure that your file(s) referenced in <code>bin</code> starts with
<code>#!/usr/bin/env node</code>, otherwise the scripts are started without the node
executable!</p>
<p>Note that you can also set the executable files using <a href="#directoriesbin">directories.bin</a>.</p>
<h3 id="man">man</h3>
<p>Specify either a single file or an array of filenames to put in place for
the <code>man</code> program to find.</p>

File diff suppressed because one or more lines are too long

View File

@ -21,7 +21,6 @@ class AddUser extends BaseCommand {
return [
'registry',
'scope',
'always-auth',
]
}

302
deps/npm/lib/exec.js vendored
View File

@ -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

View File

@ -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

190
deps/npm/lib/init.js vendored
View File

@ -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 })
}
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())
})
return
}
// the old way
const dir = process.cwd()
// 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' })
}
}
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

View File

@ -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!`

11
deps/npm/lib/ls.js vendored
View File

@ -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

22
deps/npm/lib/pack.js vendored
View File

@ -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 })

View File

@ -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 <pkg>\` commands.
`,
flatten (key, obj, flatOptions) {
flatOptions.scriptShell = obj[key] || undefined

View File

@ -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

View File

@ -9,7 +9,7 @@ npm exec \-\- <pkg>[@<version>] [args\.\.\.]
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\.\.\.]
@ -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

View File

@ -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>/]<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\.\.\.]
.fi
.RE
.SS Description
@ -16,25 +17,22 @@ npm init [<@scope>/]<name> (same as `npx [<@scope>/]create\-<name>`)
package\.
.P
\fBinitializer\fP in this case is an npm package named \fBcreate\-<initializer>\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=<url> \-\- \-\-hello \-a\fP
.IP \(bu 2
\fBnpm exec \-y \-\-registry=<url> \-\- 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 <dir>\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 <initializer> \-w <dir>\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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -10,7 +10,7 @@ npm <command> [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

View File

@ -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

View File

@ -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 <pkg>\fP commands\.
.SS \fBsearchexclude\fP
.RS 0
.IP \(bu 2

View File

@ -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)
})

View File

@ -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
}
})

View File

@ -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`)

View File

@ -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.
for (const edge of p.edgesIn) {
if (peerSet.has(edge.from))
continue
const currentPeerSet = getPeerSet(current)
// 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) {
// 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) {
// 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)
}
}
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

View File

@ -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)

View File

@ -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)
}
}

View File

@ -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}`)
}

View File

@ -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

View File

@ -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)
})

View File

@ -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}))
}
}

View File

@ -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!

View File

@ -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)

View File

@ -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)

View File

@ -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"
}
}

View File

@ -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'))

View File

@ -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",

View File

@ -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

View File

@ -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,

View File

@ -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 <i@izs.me> (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",

View File

@ -0,0 +1,2 @@
tidelift: "npm/balanced-match"
patreon: juliangruber

View File

@ -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",

View File

@ -13,6 +13,48 @@
<img src="https://cdn.jsdelivr.net/gh/chalk/ansi-styles@8261697c95bf34b6c7767e2cbe9941a851d59385/screenshot.svg" width="900">
<br>
---
<div align="center">
<p>
<p>
<sup>
Sindre Sorhus' open source work is supported by the community on <a href="https://github.com/sponsors/sindresorhus">GitHub Sponsors</a> and <a href="https://stakes.social/0x44d871aebF0126Bf646753E2C976Aa7e68A66c15">Dev</a>
</sup>
</p>
<sup>Special thanks to:</sup>
<br>
<br>
<a href="https://standardresume.co/tech">
<img src="https://sindresorhus.com/assets/thanks/standard-resume-logo.svg" width="160"/>
</a>
<br>
<br>
<a href="https://retool.com/?utm_campaign=sindresorhus">
<img src="https://sindresorhus.com/assets/thanks/retool-logo.svg" width="210"/>
</a>
<br>
<br>
<a href="https://doppler.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=chalk&utm_source=github">
<div>
<img src="https://dashboard.doppler.com/imgs/logo-long.svg" width="240" alt="Doppler">
</div>
<b>All your environment variables, in one place</b>
<div>
<span>Stop struggling with scattered API keys, hacking together home-brewed tools,</span>
<br>
<span>and avoiding access controls. Keep your team and servers in sync with Doppler.</span>
</div>
</a>
</p>
</div>
---
<br>
## Highlights
- Expressive API

View File

@ -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 || [])

View File

@ -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"

20
deps/npm/node_modules/just-diff/index.d.ts generated vendored Normal file
View File

@ -0,0 +1,20 @@
// Definitions by: Cameron Hunter <https://github.com/cameronhunter>
// Modified by: Angus Croll <https://github.com/angus-c>
type Operation = "add" | "replace" | "remove";
type JSONPatchPathConverter<OUTPUT> = (
arrayPath: Array<string | number>
) => OUTPUT;
export function diff(
a: object | Array<any>,
b: object | Array<any>,
): Array<{ op: Operation; path: Array<string | number>; value: any }>;
export function diff<PATH>(
a: object | Array<any>,
b: object | Array<any>,
jsonPatchPathConverter: JSONPatchPathConverter<PATH>
): Array<{ op: Operation; path: PATH; value: any }>;
export const jsonPatchPathConverter: JSONPatchPathConverter<string>;

64
deps/npm/node_modules/just-diff/index.tests.ts generated vendored Normal file
View File

@ -0,0 +1,64 @@
import diffObj = require('./index');
const {diff, jsonPatchPathConverter} = diffObj;
const obj1 = {a: 2, b: 3};
const obj2 = {a: 2, c: 1};
const arr1 = [1, 'bee'];
const arr2 = [2, 'bee'];
//OK
diff(obj1, obj2);
diff(arr1, arr2);
diff(obj1, arr1);
diff(obj2, arr2);
diff(/yes/, arr1);
diff(new Date(), arr2);
diff(obj1, obj2, jsonPatchPathConverter);
diff(arr1, arr2, jsonPatchPathConverter);
diff(obj1, arr1, jsonPatchPathConverter);
diff(obj2, arr2, jsonPatchPathConverter);
// not OK
// @ts-expect-error
diff(obj1);
// @ts-expect-error
diff(arr2);
// @ts-expect-error
diff('a');
// @ts-expect-error
diff(true);
// @ts-expect-error
diff(obj1, 1);
// @ts-expect-error
diff(3, arr2);
// @ts-expect-error
diff(obj1, 'a');
// @ts-expect-error
diff('b', arr2);
// @ts-expect-error
diff('a', jsonPatchPathConverter);
// @ts-expect-error
diff(true, jsonPatchPathConverter);
// @ts-expect-error
diff(obj1, 1, jsonPatchPathConverter);
// @ts-expect-error
diff(3, arr2, jsonPatchPathConverter);
// @ts-expect-error
diff(obj1, 'a', jsonPatchPathConverter);
// @ts-expect-error
diff('b', arr2, jsonPatchPathConverter);
// @ts-expect-error
diff(obj1, obj2, 'a');
// @ts-expect-error
diff(arr1, arr2, 1);
// @ts-expect-error
diff(obj1, arr1, 'bee');
// @ts-expect-error
diff(obj2, arr2, 'nope');

View File

@ -1,6 +1,6 @@
{
"name": "libnpmaccess",
"version": "4.0.1",
"version": "4.0.2",
"description": "programmatic library for `npm access` commands",
"author": "Kat Marchán <kzm@sykosomatic.org>",
"license": "ISC",
@ -14,7 +14,7 @@
"devDependencies": {
"nock": "^12.0.1",
"standard": "^14.3.0",
"tap": "^14.10.6"
"tap": "^14.11.0"
},
"repository": {
"type": "git",
@ -25,8 +25,8 @@
"dependencies": {
"aproba": "^2.0.0",
"minipass": "^3.1.1",
"npm-package-arg": "^8.0.0",
"npm-registry-fetch": "^9.0.0"
"npm-package-arg": "^8.1.2",
"npm-registry-fetch": "^10.0.0"
},
"engines": {
"node": ">=10"

7
deps/npm/node_modules/libnpmexec/CHANGELOG.md generated vendored Normal file
View File

@ -0,0 +1,7 @@
# Changelog
## v1.0.0
- Initial implementation, moves the code that used to live in the **npm cli**,
ref: https://github.com/npm/cli/blob/release/v7.10.0/lib/exec.js into this
separate module, providing a programmatic API to the **npm exec** functionality.

15
deps/npm/node_modules/libnpmexec/LICENSE generated vendored Normal file
View File

@ -0,0 +1,15 @@
The ISC License
Copyright (c) GitHub Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

48
deps/npm/node_modules/libnpmexec/README.md generated vendored Normal file
View File

@ -0,0 +1,48 @@
# libnpmexec
[![npm version](https://img.shields.io/npm/v/libnpmexec.svg)](https://npm.im/libnpmexec)
[![license](https://img.shields.io/npm/l/libnpmexec.svg)](https://npm.im/libnpmexec)
[![GitHub Actions](https://github.com/npm/libnpmexec/workflows/node-ci/badge.svg)](https://github.com/npm/libnpmexec/actions?query=workflow%3Anode-ci)
[![Coverage Status](https://coveralls.io/repos/github/npm/libnpmexec/badge.svg?branch=main)](https://coveralls.io/github/npm/libnpmexec?branch=main)
The `npm exec` (`npx`) Programmatic API
## Install
`npm install libnpmexec`
## Usage:
```js
const libexec = require('libnpmexec')
await libexec({
args: ['yosay', 'Bom dia!'],
cache: '~/.npm',
yes: true,
})
```
## API:
### `libexec(opts)`
- `opts`:
- `args`: List of pkgs to execute **Array<String>**, defaults to `[]`
- `call`: An alternative command to run when using `packages` option **String**, defaults to empty string.
- `cache`: The path location to where the npm cache folder is placed **String**
- `color`: Output should use color? **Boolean**, defaults to `false`
- `localBin`: Location to the `node_modules/.bin` folder of the local project **String**, defaults to empty string.
- `locationMsg`: Overrides "at location" message when entering interactive mode **String**
- `log`: Sets an optional logger **Object**, defaults to `proc-log` module usage.
- `globalBin`: Location to the global space bin folder, same as: `$(npm bin -g)` **String**, defaults to empty string.
- `output`: A function to print output to **Function**
- `packages`: A list of packages to be used (possibly fetch from the registry) **Array<String>**, defaults to `[]`
- `path`: Location to where to read local project info (`package.json`) **String**, defaults to `.`
- `runPath`: Location to where to execute the script **String**, defaults to `.`
- `scriptShell`: Default shell to be used **String**
- `yes`: Should skip download confirmation prompt when fetching missing packages from the registry? **Boolean**
- `registry`, `cache`, and more options that are forwarded to [@npmcli/arborist](https://github.com/npm/arborist/) and [pacote](https://github.com/npm/pacote/#options) **Object**
## LICENSE
[ISC](./LICENSE)

View File

@ -0,0 +1,19 @@
const crypto = require('crypto')
const { resolve } = require('path')
const cacheInstallDir = ({ cache, packages }) => {
if (!cache)
throw new Error('Must provide a valid cache path')
// only packages not found in ${prefix}/node_modules
return resolve(cache, '_npx', getHash(packages))
}
const getHash = (packages) =>
crypto.createHash('sha512')
.update(packages.sort((a, b) => a.localeCompare(b)).join('\n'))
.digest('hex')
.slice(0, 16)
module.exports = cacheInstallDir

View File

@ -0,0 +1,20 @@
const 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,
})
}
module.exports = getBinFromManifest

185
deps/npm/node_modules/libnpmexec/lib/index.js generated vendored Normal file
View File

@ -0,0 +1,185 @@
const { delimiter, resolve } = require('path')
const { promisify } = require('util')
const read = promisify(require('read'))
const stat = promisify(require('fs').stat)
const Arborist = require('@npmcli/arborist')
const ciDetect = require('@npmcli/ci-detect')
const logger = require('proc-log')
const mkdirp = require('mkdirp-infer-owner')
const npa = require('npm-package-arg')
const pacote = require('pacote')
const readPackageJson = require('read-package-json-fast')
const cacheInstallDir = require('./cache-install-dir.js')
const getBinFromManifest = require('./get-bin-from-manifest.js')
const manifestMissing = require('./manifest-missing.js')
const noTTY = require('./no-tty.js')
const runScript = require('./run-script.js')
const fileExists = (file) => stat(file)
.then((stat) => stat.isFile())
.catch(() => false)
/* istanbul ignore next */
const PATH = (
process.env.PATH || process.env.Path || process.env.path
).split(delimiter)
const exec = async (opts) => {
const {
args = [],
call = '',
color = false,
localBin = '',
locationMsg = undefined,
globalBin = '',
output,
packages: _packages = [],
path = '.',
runPath = '.',
scriptShell = undefined,
yes = undefined,
...flatOptions
} = opts
const log = flatOptions.log || logger
// dereferences values because we manipulate it later
const packages = [..._packages]
const pathArr = [...PATH]
const _run = () => runScript({
args,
call,
color,
flatOptions,
locationMsg,
log,
output,
path,
pathArr,
runPath,
scriptShell,
})
// nothing to maybe install, skip the arborist dance
if (!call && !args.length && !packages.length)
return await _run()
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(`${localBin}/${args[0]}`)) {
pathArr.unshift(localBin)
binExists = true
} else if (await fileExists(`${globalBin}/${args[0]}`)) {
pathArr.unshift(globalBin)
binExists = true
}
if (binExists)
return await _run()
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, 'package.json')
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, {
...flatOptions,
preferOnline: true,
})
}))
if (needPackageCommandSwap)
args[0] = getBinFromManifest(manis[0])
// figure out whether we need to install stuff, or if local is fine
const localArb = new Arborist({
...flatOptions,
path,
})
const tree = await localArb.loadActual()
// do we have all the packages in manifest list?
const needInstall =
manis.some(manifest => manifestMissing({ tree, manifest }))
if (needInstall) {
const { cache } = flatOptions
const installDir = cacheInstallDir({ cache, packages })
await mkdirp(installDir)
const arb = new Arborist({
...flatOptions,
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 => manifestMissing({
tree,
manifest: {
...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 (!yes) {
// set -n to always say no
if (yes === false)
throw new Error('canceled')
if (noTTY() || ciDetect()) {
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({
...flatOptions,
add,
})
}
pathArr.unshift(resolve(installDir, 'node_modules/.bin'))
}
return await _run()
}
module.exports = exec

View File

@ -0,0 +1,17 @@
const manifestMissing = ({ tree, manifest }) => {
// 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(manifest.name)
// if no child, we have to load it
if (!child)
return true
// if no version/tag specified, allow whatever's there
if (manifest._from === `${manifest.name}@`)
return false
// otherwise the version has to match what we WOULD get
return child.version !== manifest.version
}
module.exports = manifestMissing

1
deps/npm/node_modules/libnpmexec/lib/no-tty.js generated vendored Normal file
View File

@ -0,0 +1 @@
module.exports = () => !process.stdin.isTTY

86
deps/npm/node_modules/libnpmexec/lib/run-script.js generated vendored Normal file
View File

@ -0,0 +1,86 @@
const { delimiter } = require('path')
const chalk = require('chalk')
const ciDetect = require('@npmcli/ci-detect')
const runScript = require('@npmcli/run-script')
const readPackageJson = require('read-package-json-fast')
const noTTY = require('./no-tty.js')
const nocolor = {
reset: s => s,
bold: s => s,
dim: s => s,
}
const run = async ({
args,
call,
color,
flatOptions,
locationMsg,
log,
output = () => {},
path,
pathArr,
runPath,
scriptShell,
}) => {
// turn list of args into command string
const script = call || args.shift() || scriptShell
const colorize = color ? chalk : nocolor
// 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,
},
}
if (log && log.disableProgress)
log.disableProgress()
try {
if (script === scriptShell) {
const isTTY = !noTTY()
if (isTTY) {
if (ciDetect())
return log.warn('exec', 'Interactive mode disabled in CI environment')
locationMsg = locationMsg || ` at location:\n${colorize.dim(runPath)}`
output(`${
colorize.reset('\nEntering npm script environment')
}${
colorize.reset(locationMsg)
}${
colorize.bold('\nType \'exit\' or ^D when finished\n')
}`)
}
}
return await runScript({
...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 {
if (log && log.enableProgress)
log.enableProgress()
}
}
module.exports = run

63
deps/npm/node_modules/libnpmexec/package.json generated vendored Normal file
View File

@ -0,0 +1,63 @@
{
"name": "libnpmexec",
"version": "1.0.1",
"files": [
"lib"
],
"main": "lib/index.js",
"engines": {
"node": ">=10"
},
"description": "npm exec (npx) programmatic API",
"repository": "https://github.com/npm/libnpmexec",
"keywords": [
"npm",
"npmcli",
"libnpm",
"cli",
"workspaces",
"libnpmexec"
],
"author": "GitHub Inc.",
"contributors": [
{
"name": "Ruy Adorno",
"url": "https://ruyadorno.com",
"twitter": "ruyadorno"
}
],
"license": "ISC",
"scripts": {
"lint": "eslint lib/*.js",
"pretest": "npm run lint",
"test": "tap test/*.js",
"snap": "tap test/*.js",
"preversion": "npm test",
"postversion": "npm publish",
"prepublishOnly": "git push origin --follow-tags"
},
"tap": {
"check-coverage": true
},
"devDependencies": {
"bin-links": "^2.2.1",
"eslint": "^7.24.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^5.1.0",
"eslint-plugin-standard": "^5.0.0",
"tap": "^15.0.2"
},
"dependencies": {
"@npmcli/arborist": "^2.3.0",
"@npmcli/ci-detect": "^1.3.0",
"@npmcli/run-script": "^1.8.4",
"chalk": "^4.1.0",
"mkdirp-infer-owner": "^2.0.0",
"npm-package-arg": "^8.1.2",
"pacote": "^11.3.1",
"proc-log": "^1.0.0",
"read": "^1.0.7",
"read-package-json-fast": "^2.0.2"
}
}

View File

@ -1,6 +1,6 @@
{
"name": "libnpmhook",
"version": "6.0.1",
"version": "6.0.2",
"description": "programmatic API for managing npm registry hooks",
"main": "index.js",
"files": [
@ -28,7 +28,7 @@
"license": "ISC",
"dependencies": {
"aproba": "^2.0.0",
"npm-registry-fetch": "^9.0.0"
"npm-registry-fetch": "^10.0.0"
},
"devDependencies": {
"nock": "^9.6.1",

View File

@ -1,6 +1,6 @@
{
"name": "libnpmorg",
"version": "2.0.1",
"version": "2.0.2",
"description": "Programmatic api for `npm org` commands",
"author": "Kat Marchán <kzm@sykosomatic.org>",
"keywords": [
@ -40,7 +40,7 @@
"homepage": "https://npmjs.com/package/libnpmorg",
"dependencies": {
"aproba": "^2.0.0",
"npm-registry-fetch": "^9.0.0"
"npm-registry-fetch": "^10.0.0"
},
"engines": {
"node": ">=10"

View File

@ -1,6 +1,6 @@
{
"name": "libnpmpublish",
"version": "4.0.0",
"version": "4.0.1",
"description": "Programmatic API for the bits behind npm publish and unpublish",
"author": "npm Inc. <support@npmjs.com>",
"contributors": [
@ -44,11 +44,11 @@
"bugs": "https://github.com/npm/libnpmpublish/issues",
"homepage": "https://npmjs.com/package/libnpmpublish",
"dependencies": {
"normalize-package-data": "^3.0.0",
"npm-package-arg": "^8.1.0",
"npm-registry-fetch": "^9.0.0",
"normalize-package-data": "^3.0.2",
"npm-package-arg": "^8.1.2",
"npm-registry-fetch": "^10.0.0",
"semver": "^7.1.3",
"ssri": "^8.0.0"
"ssri": "^8.0.1"
},
"engines": {
"node": ">=10"

View File

@ -1,6 +1,6 @@
{
"name": "libnpmsearch",
"version": "3.1.0",
"version": "3.1.1",
"description": "Programmatic API for searching in npm and compatible registries.",
"author": "Kat Marchán <kzm@sykosomatic.org>",
"files": [
@ -36,7 +36,7 @@
"bugs": "https://github.com/npm/libnpmsearch/issues",
"homepage": "https://npmjs.com/package/libnpmsearch",
"dependencies": {
"npm-registry-fetch": "^9.0.0"
"npm-registry-fetch": "^10.0.0"
},
"engines": {
"node": ">=10"

View File

@ -1,7 +1,7 @@
{
"name": "libnpmteam",
"description": "npm Team management APIs",
"version": "2.0.2",
"version": "2.0.3",
"author": "Kat Marchán <kzm@zkat.tech>",
"license": "ISC",
"scripts": {
@ -27,7 +27,7 @@
"homepage": "https://npmjs.com/package/libnpmteam",
"dependencies": {
"aproba": "^2.0.0",
"npm-registry-fetch": "^9.0.0"
"npm-registry-fetch": "^10.0.0"
},
"engines": {
"node": ">=10"

View File

@ -135,9 +135,11 @@ class BundleWalker extends EE {
}
childDep (dep) {
if (this.node_modules.indexOf(dep) !== -1 && !this.seen.has(dep)) {
this.seen.add(dep)
this.child(dep)
if (this.node_modules.indexOf(dep) !== -1) {
if (!this.seen.has(dep)) {
this.seen.add(dep)
this.child(dep)
}
} else if (this.parent) {
this.parent.childDep(dep)
}

View File

@ -1,6 +1,6 @@
{
"name": "npm-bundled",
"version": "1.1.1",
"version": "1.1.2",
"description": "list things in node_modules that are bundledDependencies, or transitive dependencies thereof",
"main": "index.js",
"repository": {

View File

@ -1,12 +1,12 @@
{
"name": "npm-profile",
"version": "5.0.2",
"version": "5.0.3",
"description": "Library for updating an npmjs.com profile",
"keywords": [],
"author": "Rebecca Turner <me@re-becca.org> (http://re-becca.org/)",
"license": "ISC",
"dependencies": {
"npm-registry-fetch": "^9.0.0"
"npm-registry-fetch": "^10.0.0"
},
"main": "index.js",
"repository": {

View File

@ -309,13 +309,6 @@ previously-generated integrity hash for the saved request information, so
`EINTEGRITY` errors can happen if [`opts.cache`](#opts-cache) is used, even if
`opts.integrity` is not passed in.
##### <a name='opts-isFromCI'></a> `opts.isFromCI`
* Type: Boolean
* Default: Based on environment variables
This is used to populate the `npm-in-ci` request header sent to the registry.
##### <a name="opts-key"></a> `opts.key`
* Type: String
@ -425,6 +418,19 @@ This is a one-time password from a two-factor authenticator. It is required for
certain registry interactions when two-factor auth is enabled for a user
account.
##### <a name="opts-otpPrompt"></a> `opts.otpPrompt`
* Type: Function
* Default: null
This is a method which will be called to provide an OTP if the server
responds with a 401 response indicating that a one-time-password is
required.
It may return a promise, which must resolve to the OTP value to be used.
If the method fails to provide an OTP value, then the fetch will fail with
the auth error that indicated an OTP was needed.
##### <a name="opts-password"></a> `opts.password`
* Alias: `_password`

View File

@ -1,55 +1,111 @@
'use strict'
const npa = require('npm-package-arg')
const defaultOpts = require('./default-opts.js')
const url = require('url')
// Find the longest registry key that is used for some kind of auth
// in the options.
const regKeyFromURI = (uri, opts) => {
const parsed = new URL(uri)
// try to find a config key indicating we have auth for this registry
// can be one of :_authToken, :_auth, or :_password and :username
// We walk up the "path" until we're left with just //<host>[:<port>],
// stopping when we reach '//'.
let regKey = `//${parsed.host}${parsed.pathname}`
while (regKey.length > '//'.length) {
// got some auth for this URI
if (hasAuth(regKey, opts))
return regKey
// can be either //host/some/path/:_auth or //host/some/path:_auth
// walk up by removing EITHER what's after the slash OR the slash itself
regKey = regKey.replace(/([^/]+|\/)$/, '')
}
}
const hasAuth = (regKey, opts) => (
opts[`${regKey}:_authToken`] ||
opts[`${regKey}:_auth`] ||
opts[`${regKey}:username`] && opts[`${regKey}:_password`]
)
const sameHost = (a, b) => {
const parsedA = new URL(a)
const parsedB = new URL(b)
return parsedA.host === parsedB.host
}
const getRegistry = opts => {
const { spec } = opts
const { scope: specScope, subSpec } = spec ? npa(spec) : {}
const subSpecScope = subSpec && subSpec.scope
const scope = subSpec ? subSpecScope : specScope
const scopeReg = scope && opts[`${scope}:registry`]
return scopeReg || opts.registry
}
const getAuth = (uri, opts = {}) => {
const { forceAuth } = opts
if (!uri)
throw new Error('URI is required')
const regKey = regKeyFromURI(uri, forceAuth || opts)
// we are only allowed to use what's in forceAuth if specified
if (forceAuth && !regKey) {
return new Auth({
scopeAuthKey: null,
token: forceAuth._authToken,
username: forceAuth.username,
password: forceAuth._password || forceAuth.password,
auth: forceAuth._auth || forceAuth.auth,
})
}
// no auth for this URI, but might have it for the registry
if (!regKey) {
const registry = getRegistry(opts)
if (registry && uri !== registry && sameHost(uri, registry))
return getAuth(registry, opts)
else if (registry !== opts.registry) {
// If making a tarball request to a different base URI than the
// registry where we logged in, but the same auth SHOULD be sent
// to that artifact host, then we track where it was coming in from,
// and warn the user if we get a 4xx error on it.
const scopeAuthKey = regKeyFromURI(registry, opts)
return new Auth({ scopeAuthKey })
}
}
const {
[`${regKey}:_authToken`]: token,
[`${regKey}:username`]: username,
[`${regKey}:_password`]: password,
[`${regKey}:_auth`]: auth,
} = opts
return new Auth({
scopeAuthKey: null,
token,
auth,
username,
password,
})
}
class Auth {
constructor ({ token, auth, username, password, scopeAuthKey }) {
this.scopeAuthKey = scopeAuthKey
this.token = null
this.auth = null
this.isBasicAuth = false
if (token)
this.token = token
else if (auth)
this.auth = auth
else if (username && password) {
const p = Buffer.from(password, 'base64').toString('utf8')
this.auth = Buffer.from(`${username}:${p}`, 'utf8').toString('base64')
this.isBasicAuth = true
}
}
}
module.exports = getAuth
function getAuth (registry, opts_ = {}) {
if (!registry)
throw new Error('registry is required')
const opts = opts_.forceAuth ? opts_.forceAuth : { ...defaultOpts, ...opts_ }
const AUTH = {}
const regKey = registry && registryKey(registry)
const doKey = (key, alias) => addKey(opts, AUTH, regKey, key, alias)
doKey('token')
doKey('_authToken', 'token')
doKey('username')
doKey('password')
doKey('_password', 'password')
doKey('email')
doKey('_auth')
doKey('otp')
doKey('always-auth', 'alwaysAuth')
if (AUTH.password)
AUTH.password = Buffer.from(AUTH.password, 'base64').toString('utf8')
if (AUTH._auth && !(AUTH.username && AUTH.password)) {
let auth = Buffer.from(AUTH._auth, 'base64').toString()
auth = auth.split(':')
AUTH.username = auth.shift()
AUTH.password = auth.join(':')
}
AUTH.alwaysAuth = AUTH.alwaysAuth === 'false' ? false : !!AUTH.alwaysAuth
return AUTH
}
function addKey (opts, obj, scope, key, objKey) {
if (opts[key])
obj[objKey || key] = opts[key]
if (scope && opts[`${scope}:${key}`])
obj[objKey || key] = opts[`${scope}:${key}`]
}
// Called a nerf dart in the main codebase. Used as a "safe"
// key when fetching registry info from config.
function registryKey (registry) {
const parsed = new url.URL(registry)
const formatted = url.format({
protocol: parsed.protocol,
host: parsed.host,
pathname: parsed.pathname,
slashes: true,
})
return url.format(new url.URL('.', formatted)).replace(/^[^:]+:/, '')
}

View File

@ -5,15 +5,25 @@ const LRU = require('lru-cache')
const { Response } = require('minipass-fetch')
const defaultOpts = require('./default-opts.js')
module.exports = checkResponse
function checkResponse (method, res, registry, startTime, opts_ = {}) {
const opts = { ...defaultOpts, ...opts_ }
const checkResponse = async ({ method, uri, res, registry, startTime, auth, opts }) => {
opts = { ...defaultOpts, ...opts }
if (res.headers.has('npm-notice') && !res.headers.has('x-local-cache'))
opts.log.notice('', res.headers.get('npm-notice'))
checkWarnings(res, registry, opts)
if (res.status >= 400) {
logRequest(method, res, startTime, opts)
if (auth && auth.scopeAuthKey && !auth.token && !auth.auth) {
// we didn't have auth for THIS request, but we do have auth for
// requests to the registry indicated by the spec's scope value.
// Warn the user.
opts.log.warn('registry', `No auth for URI, but auth present for scoped registry.
URI: ${uri}
Scoped Registry Key: ${auth.scopeAuthKey}
More info here: https://github.com/npm/cli/wiki/No-auth-for-URI,-but-auth-present-for-scoped-registry`)
}
return checkErrors(method, res, startTime, opts)
} else {
res.body.on('end', () => logRequest(method, res, startTime, opts))
@ -24,6 +34,7 @@ function checkResponse (method, res, registry, startTime, opts_ = {}) {
return res
}
}
module.exports = checkResponse
function logRequest (method, res, startTime, opts) {
const elapsedTime = Date.now() - startTime

View File

@ -1,7 +1,5 @@
const pkg = require('./package.json')
const ciDetect = require('@npmcli/ci-detect')
module.exports = {
isFromCI: ciDetect(),
log: require('./silentlog.js'),
maxSockets: 12,
method: 'GET',

View File

@ -22,6 +22,7 @@ function packageName (href) {
class HttpErrorBase extends Error {
constructor (method, res, body, spec) {
super()
this.name = this.constructor.name
this.headers = res.headers.raw()
this.statusCode = res.status
this.code = `E${res.status}`

View File

@ -1,5 +1,6 @@
'use strict'
const { HttpErrorAuthOTP } = require('./errors.js')
const checkResponse = require('./check-response.js')
const getAuth = require('./auth.js')
const fetch = require('make-fetch-happen')
@ -27,26 +28,32 @@ function regFetch (uri, /* istanbul ignore next */ opts_ = {}) {
...defaultOpts,
...opts_,
}
const registry = opts.registry = (
(opts.spec && pickRegistry(opts.spec, opts)) ||
opts.registry ||
/* istanbul ignore next */
'https://registry.npmjs.org/'
)
if (!urlIsValid(uri)) {
// if we did not get a fully qualified URI, then we look at the registry
// config or relevant scope to resolve it.
const uriValid = urlIsValid(uri)
let registry = opts.registry || defaultOpts.registry
if (!uriValid) {
registry = opts.registry = (
(opts.spec && pickRegistry(opts.spec, opts)) ||
opts.registry ||
registry
)
uri = `${
registry.trim().replace(/\/?$/g, '')
}/${
uri.trim().replace(/^\//, '')
}`
// asserts that this is now valid
new url.URL(uri)
}
const method = opts.method || 'GET'
// through that takes into account the scope, the prefix of `uri`, etc
const startTime = Date.now()
const headers = getHeaders(registry, uri, opts)
const auth = getAuth(uri, opts)
const headers = getHeaders(uri, auth, opts)
let body = opts.body
const bodyIsStream = Minipass.isStream(body)
const bodyIsPromise = body &&
@ -92,34 +99,57 @@ function regFetch (uri, /* istanbul ignore next */ opts_ = {}) {
opts.preferOnline = true
}
const doFetch = (body) => fetch(uri, {
agent: opts.agent,
algorithms: opts.algorithms,
body,
cache: getCacheMode(opts),
cacheManager: opts.cache,
ca: opts.ca,
cert: opts.cert,
headers,
integrity: opts.integrity,
key: opts.key,
localAddress: opts.localAddress,
maxSockets: opts.maxSockets,
memoize: opts.memoize,
method: method,
noProxy: opts.noProxy,
proxy: opts.httpsProxy || opts.proxy,
retry: opts.retry ? opts.retry : {
retries: opts.fetchRetries,
factor: opts.fetchRetryFactor,
minTimeout: opts.fetchRetryMintimeout,
maxTimeout: opts.fetchRetryMaxtimeout,
},
strictSSL: opts.strictSSL,
timeout: opts.timeout || 30 * 1000,
}).then(res => checkResponse(
method, res, registry, startTime, opts
))
const doFetch = async body => {
const p = fetch(uri, {
agent: opts.agent,
algorithms: opts.algorithms,
body,
cache: getCacheMode(opts),
cacheManager: opts.cache,
ca: opts.ca,
cert: opts.cert,
headers,
integrity: opts.integrity,
key: opts.key,
localAddress: opts.localAddress,
maxSockets: opts.maxSockets,
memoize: opts.memoize,
method: method,
noProxy: opts.noProxy,
proxy: opts.httpsProxy || opts.proxy,
retry: opts.retry ? opts.retry : {
retries: opts.fetchRetries,
factor: opts.fetchRetryFactor,
minTimeout: opts.fetchRetryMintimeout,
maxTimeout: opts.fetchRetryMaxtimeout,
},
strictSSL: opts.strictSSL,
timeout: opts.timeout || 30 * 1000,
}).then(res => checkResponse({
method,
uri,
res,
registry,
startTime,
auth,
opts,
}))
if (typeof opts.otpPrompt === 'function') {
return p.catch(async er => {
if (er instanceof HttpErrorAuthOTP) {
// if otp fails to complete, we fail with that failure
const otp = await opts.otpPrompt()
// if no otp provided, throw the original HTTP error
if (!otp)
throw er
return regFetch(uri, { ...opts, otp })
}
throw er
})
} else
return p
}
return Promise.resolve(body).then(doFetch)
}
@ -151,7 +181,7 @@ function pickRegistry (spec, opts = {}) {
registry = opts[opts.scope.replace(/^@?/, '@') + ':registry']
if (!registry)
registry = opts.registry || 'https://registry.npmjs.org/'
registry = opts.registry || defaultOpts.registry
return registry
}
@ -163,9 +193,8 @@ function getCacheMode (opts) {
: 'default'
}
function getHeaders (registry, uri, opts) {
function getHeaders (uri, auth, opts) {
const headers = Object.assign({
'npm-in-ci': !!opts.isFromCI,
'user-agent': opts.userAgent,
}, opts.headers || {})
@ -178,25 +207,15 @@ function getHeaders (registry, uri, opts) {
if (opts.npmCommand)
headers['npm-command'] = opts.npmCommand
const auth = getAuth(registry, opts)
// If a tarball is hosted on a different place than the manifest, only send
// credentials on `alwaysAuth`
const shouldAuth = (
auth.alwaysAuth ||
new url.URL(uri).host === new url.URL(registry).host
)
if (shouldAuth && auth.token)
if (auth.token)
headers.authorization = `Bearer ${auth.token}`
else if (shouldAuth && auth.username && auth.password) {
const encoded = Buffer.from(
`${auth.username}:${auth.password}`, 'utf8'
).toString('base64')
headers.authorization = `Basic ${encoded}`
} else if (shouldAuth && auth._auth)
headers.authorization = `Basic ${auth._auth}`
else if (auth.auth)
headers.authorization = `Basic ${auth.auth}`
if (shouldAuth && auth.otp)
headers['npm-otp'] = auth.otp
if (opts.otp)
headers['npm-otp'] = opts.otp
return headers
}

View File

@ -1,6 +1,6 @@
{
"name": "npm-registry-fetch",
"version": "9.0.0",
"version": "10.1.1",
"description": "Fetch-based http client for use with npm registry APIs",
"main": "index.js",
"files": [
@ -29,7 +29,6 @@
},
"license": "ISC",
"dependencies": {
"@npmcli/ci-detect": "^1.0.0",
"lru-cache": "^6.0.0",
"make-fetch-happen": "^8.0.9",
"minipass": "^3.1.3",
@ -51,7 +50,7 @@
"require-inject": "^1.4.4",
"rimraf": "^2.6.2",
"ssri": "^8.0.0",
"tap": "^14.10.7"
"tap": "^15.0.4"
},
"tap": {
"check-coverage": true,

View File

@ -40,6 +40,7 @@ const _istream = Symbol('_istream')
const _assertType = Symbol('_assertType')
const _tarballFromCache = Symbol('_tarballFromCache')
const _tarballFromResolved = Symbol.for('pacote.Fetcher._tarballFromResolved')
const _cacheFetches = Symbol.for('pacote.Fetcher._cacheFetches')
class FetcherBase {
constructor (spec, opts) {
@ -166,25 +167,19 @@ class FetcherBase {
}
// private, should be overridden.
// Note that they should *not* calculate or check integrity, but *just*
// return the raw tarball data stream.
// Note that they should *not* calculate or check integrity or cache,
// but *just* return the raw tarball data stream.
[_tarballFromResolved] () {
throw this.notImplementedError
}
// public, should not be overridden
tarball () {
return this.tarballStream(stream => new Promise((res, rej) => {
const buf = []
stream.on('error', er => rej(er))
stream.on('end', () => {
const data = Buffer.concat(buf)
data.integrity = this.integrity && String(this.integrity)
data.resolved = this.resolved
data.from = this.from
return res(data)
})
stream.on('data', d => buf.push(d))
return this.tarballStream(stream => stream.concat().then(data => {
data.integrity = this.integrity && String(this.integrity)
data.resolved = this.resolved
data.from = this.from
return data
}))
}
@ -194,6 +189,10 @@ class FetcherBase {
return cacache.get.stream.byDigest(this.cache, this.integrity, this.opts)
}
get [_cacheFetches] () {
return true
}
[_istream] (stream) {
// everyone will need one of these, either for verifying or calculating
// We always set it, because we have might only have a weak legacy hex
@ -203,7 +202,31 @@ class FetcherBase {
// gets to the point of re-setting the integrity.
const istream = ssri.integrityStream(this.opts)
istream.on('integrity', i => this.integrity = i)
return stream.on('error', er => istream.emit('error', er)).pipe(istream)
stream.on('error', er => istream.emit('error', er))
// if not caching this, just pipe through to the istream and return it
if (!this.opts.cache || !this[_cacheFetches])
return stream.pipe(istream)
// we have to return a stream that gets ALL the data, and proxies errors,
// but then pipe from the original tarball stream into the cache as well.
// To do this without losing any data, and since the cacache put stream
// is not a passthrough, we have to pipe from the original stream into
// the cache AFTER we pipe into the istream. Since the cache stream
// has an asynchronous flush to write its contents to disk, we need to
// defer the istream end until the cache stream ends.
stream.pipe(istream, { end: false })
const cstream = cacache.put.stream(
this.opts.cache,
`pacote:tarball:${this.from}`,
this.opts
)
stream.pipe(cstream)
// defer istream end until after cstream
// cache write errors should not crash the fetch, this is best-effort.
cstream.promise().catch(() => {}).then(() => istream.end())
return istream
}
pickIntegrityAlgorithm () {
@ -232,7 +255,9 @@ class FetcherBase {
// An ENOENT trying to read a tgz file, for example, is Right Out.
isRetriableError (er) {
// TODO: check error class, once those are rolled out to our deps
return this.isDataCorruptionError(er) || er.code === 'ENOENT'
return this.isDataCorruptionError(er) ||
er.code === 'ENOENT' ||
er.code === 'EISDIR'
}
// Mostly internal, but has some uses

View File

@ -3,6 +3,7 @@ const RemoteFetcher = require('./remote.js')
const _tarballFromResolved = Symbol.for('pacote.Fetcher._tarballFromResolved')
const pacoteVersion = require('../package.json').version
const npa = require('npm-package-arg')
const rpj = require('read-package-json-fast')
const pickManifest = require('npm-pick-manifest')
const ssri = require('ssri')
const Minipass = require('minipass')
@ -156,7 +157,8 @@ class RegistryFetcher extends Fetcher {
}
if (this.integrity)
mani._integrity = String(this.integrity)
return this.package = mani
this.package = rpj.normalize(mani)
return this.package
})
}

View File

@ -8,6 +8,7 @@ const Minipass = require('minipass')
// The default registry URL is a string of great magic.
const magic = /^https?:\/\/registry\.npmjs\.org\//
const _cacheFetches = Symbol.for('pacote.Fetcher._cacheFetches')
const _headers = Symbol('_headers')
class RemoteFetcher extends Fetcher {
constructor (spec, opts) {
@ -21,6 +22,12 @@ class RemoteFetcher extends Fetcher {
this.pkgid = opts.pkgid ? opts.pkgid : `remote:${nameat}${this.resolved}`
}
// Don't need to cache tarball fetches in pacote, because make-fetch-happen
// will write into cacache anyway.
get [_cacheFetches] () {
return false
}
[_tarballFromResolved] () {
const stream = new Minipass()
const fetchOpts = {

View File

@ -1,6 +1,6 @@
{
"name": "pacote",
"version": "11.3.1",
"version": "11.3.3",
"description": "JavaScript package downloader",
"author": "Isaac Z. Schlueter <i@izs.me> (https://izs.me)",
"bin": {
@ -17,15 +17,12 @@
},
"tap": {
"timeout": 300,
"check-coverage": true,
"coverage-map": "map.js",
"esm": false
"coverage-map": "map.js"
},
"devDependencies": {
"mutate-fs": "^2.1.1",
"npm-registry-mock": "^1.3.1",
"require-inject": "^1.4.4",
"tap": "^14.11.0"
"tap": "^15.0.4"
},
"files": [
"lib/**/*.js"
@ -49,7 +46,7 @@
"npm-package-arg": "^8.0.1",
"npm-packlist": "^2.1.4",
"npm-pick-manifest": "^6.0.0",
"npm-registry-fetch": "^9.0.0",
"npm-registry-fetch": "^10.0.0",
"promise-retry": "^2.0.1",
"read-package-json-fast": "^2.0.1",
"rimraf": "^3.0.2",

15
deps/npm/node_modules/proc-log/LICENSE generated vendored Normal file
View File

@ -0,0 +1,15 @@
The ISC License
Copyright (c) GitHub, Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

33
deps/npm/node_modules/proc-log/README.md generated vendored Normal file
View File

@ -0,0 +1,33 @@
# proc-log
Emits 'log' events on the process object which a log output listener can
consume and print to the terminal.
This is used by various modules within the npm CLI stack in order to send
log events that [`npmlog`](http://npm.im/npmlog) can consume and print.
## API
* `log.error(...args)` calls `process.emit('log', 'error', ...args)`
The highest log level. For printing extremely serious errors that
indicate something went wrong.
* `log.warn(...args)` calls `process.emit('log', 'warn', ...args)`
A fairly high log level. Things that the user needs to be aware of, but
which won't necessarily cause improper functioning of the system.
* `log.notice(...args)` calls `process.emit('log', 'notice', ...args)`
Notices which are important, but not necessarily dangerous or a cause for
excess concern.
* `log.info(...args)` calls `process.emit('log', 'info', ...args)`
Informative messages that may benefit the user, but aren't particularly
important.
* `log.verbose(...args)` calls `process.emit('log', 'verbose', ...args)`
Noisy output that is more detail that most users will care about.
* `log.silly(...args)` calls `process.emit('log', 'silly', ...args)`
Extremely noisy excessive logging messages that are typically only useful
for debugging.
* `log.http(...args)` calls `process.emit('log', 'http', ...args)`
Information about HTTP requests made and/or completed.
* `log.pause(...args)` calls `process.emit('log', 'pause')` Used to tell
the consumer to stop printing messages.
* `log.resume(...args)` calls `process.emit('log', 'resume', ...args)`
Used to tell the consumer that it is ok to print messages again.

22
deps/npm/node_modules/proc-log/index.js generated vendored Normal file
View File

@ -0,0 +1,22 @@
// emits 'log' events on the process
const LEVELS = [
'notice',
'error',
'warn',
'info',
'verbose',
'http',
'silly',
'pause',
'resume',
]
const log = level => (...args) => process.emit('log', level, ...args)
const logger = {}
for (const level of LEVELS)
logger[level] = log(level)
logger.LEVELS = LEVELS
module.exports = logger

28
deps/npm/node_modules/proc-log/package.json generated vendored Normal file
View File

@ -0,0 +1,28 @@
{
"name": "proc-log",
"version": "1.0.0",
"files": [
"index.js"
],
"description": "just emit 'log' events on the process object",
"repository": "https://github.com/npm/proc-log",
"author": "Isaac Z. Schlueter <i@izs.me> (https://izs.me)",
"license": "ISC",
"scripts": {
"test": "tap",
"snap": "tap",
"posttest": "eslint index.js test/*.js",
"postsnap": "eslint index.js test/*.js --fix",
"preversion": "npm test",
"postversion": "npm publish",
"prepublishOnly": "git push origin --follow-tags"
},
"devDependencies": {
"eslint": "^7.9.0",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
"tap": "^15.0.2"
}
}

View File

@ -409,7 +409,7 @@ Note: When using 4a please specify type: 4, and when using 5h please specify typ
| --- | :---: | :---: | :---: | :---: | :---: |
| SOCKS v4 | ✅ | ❌ | ✅ | ❌ | ❌ |
| SOCKS v4a | ✅ | ❌ | ✅ | ❌ | ✅ |
| SOCKS v5 (includes 5hh) | ✅ | ✅ | ✅ | ✅ | ✅ |
| SOCKS v5 (includes v5h) | ✅ | ✅ | ✅ | ✅ | ✅ |
### new SocksClient(options)

View File

@ -690,7 +690,7 @@ class SocksClient extends events_1.EventEmitter {
if (constants_1.SocksCommand[this.options.command] === constants_1.SocksCommand.connect) {
this.setState(constants_1.SocksClientState.Established);
this.removeInternalSocketHandlers();
this.emit('established', { socket: this.socket });
this.emit('established', { remoteHost, socket: this.socket });
}
else if (constants_1.SocksCommand[this.options.command] === constants_1.SocksCommand.bind) {
/* If using BIND, the Socks client is now in BoundWaitingForConnection state.

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,7 @@
{
"name": "socks",
"private": false,
"version": "2.6.0",
"version": "2.6.1",
"description": "Fully featured SOCKS proxy client supporting SOCKSv4, SOCKSv4a, and SOCKSv5. Includes Bind and Associate functionality.",
"main": "build/index.js",
"typings": "typings/index.d.ts",
@ -34,8 +34,8 @@
"readmeFilename": "README.md",
"devDependencies": {
"@types/ip": "1.1.0",
"@types/mocha": "^8.2.1",
"@types/node": "^14.14.35",
"@types/mocha": "^8.2.2",
"@types/node": "^14.14.41",
"coveralls": "3.1.0",
"mocha": "^8.3.2",
"nyc": "15.1.0",
@ -44,7 +44,7 @@
"ts-node": "^9.1.1",
"tslint": "^6.1.3",
"tslint-config-airbnb": "^5.11.2",
"typescript": "^4.2.3"
"typescript": "^4.2.4"
},
"dependencies": {
"ip": "^1.1.5",

32
deps/npm/package.json vendored
View File

@ -1,5 +1,5 @@
{
"version": "7.10.0",
"version": "7.11.2",
"name": "npm",
"description": "a package manager for JavaScript",
"keywords": [
@ -42,10 +42,10 @@
"./package.json": "./package.json"
},
"dependencies": {
"@npmcli/arborist": "^2.3.0",
"@npmcli/arborist": "^2.4.1",
"@npmcli/ci-detect": "^1.2.0",
"@npmcli/config": "^2.1.0",
"@npmcli/run-script": "^1.8.4",
"@npmcli/config": "^2.2.0",
"@npmcli/run-script": "^1.8.5",
"abbrev": "~1.1.1",
"ansicolors": "~0.3.2",
"ansistyles": "~0.1.3",
@ -61,19 +61,20 @@
"graceful-fs": "^4.2.6",
"hosted-git-info": "^4.0.2",
"ini": "^2.0.0",
"init-package-json": "^2.0.2",
"init-package-json": "^2.0.3",
"is-cidr": "^4.0.2",
"json-parse-even-better-errors": "^2.3.1",
"leven": "^3.1.0",
"libnpmaccess": "^4.0.1",
"libnpmaccess": "^4.0.2",
"libnpmdiff": "^2.0.4",
"libnpmexec": "^1.0.1",
"libnpmfund": "^1.0.2",
"libnpmhook": "^6.0.1",
"libnpmorg": "^2.0.1",
"libnpmhook": "^6.0.2",
"libnpmorg": "^2.0.2",
"libnpmpack": "^2.0.1",
"libnpmpublish": "^4.0.0",
"libnpmsearch": "^3.1.0",
"libnpmteam": "^2.0.2",
"libnpmpublish": "^4.0.1",
"libnpmsearch": "^3.1.1",
"libnpmteam": "^2.0.3",
"libnpmversion": "^1.2.0",
"make-fetch-happen": "^8.0.14",
"minipass": "^3.1.3",
@ -86,12 +87,12 @@
"npm-audit-report": "^2.1.4",
"npm-package-arg": "^8.1.2",
"npm-pick-manifest": "^6.1.1",
"npm-profile": "^5.0.2",
"npm-registry-fetch": "^9.0.0",
"npm-profile": "^5.0.3",
"npm-registry-fetch": "^10.1.1",
"npm-user-validate": "^1.0.1",
"npmlog": "~4.1.2",
"opener": "^1.5.2",
"pacote": "^11.3.1",
"pacote": "^11.3.3",
"parse-conflict-json": "^1.1.1",
"qrcode-terminal": "^0.12.0",
"read": "~1.0.7",
@ -135,6 +136,7 @@
"leven",
"libnpmaccess",
"libnpmdiff",
"libnpmexec",
"libnpmfund",
"libnpmhook",
"libnpmorg",
@ -188,7 +190,7 @@
"jsdom": "^16.5.2",
"licensee": "^8.1.0",
"marked-man": "^0.7.0",
"tap": "^15.0.2",
"tap": "^15.0.6",
"yaml": "^1.10.2"
},
"scripts": {

Some files were not shown because too many files have changed in this diff Show More