Commit 4eb3908d1f2 for nodejs
commit 4eb3908d1f237e9dfdf09111540d2a7ede48f8c9
Author: npm team <ops+robot@npmjs.com>
Date: Thu Sep 24 13:43:40 2026 -0700
deps: upgrade npm to 12.1.0
PR-URL: https://github.com/nodejs/node/pull/66212
Reviewed-By: Mike McCready <66998419+MikeMcC399@users.noreply.github.com>
Reviewed-By: Jordan Harband <ljharb@gmail.com>
Reviewed-By: Richard Lau <richard.lau@ibm.com>
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
diff --git a/deps/npm/docs/content/commands/npm-adduser.md b/deps/npm/docs/content/commands/npm-adduser.md
deleted file mode 100644
index be2685d7853..00000000000
--- a/deps/npm/docs/content/commands/npm-adduser.md
+++ /dev/null
@@ -1,87 +0,0 @@
----
-title: npm-adduser
-section: 1
-description: Add a registry user account
----
-
-### Synopsis
-
-```bash
-npm adduser
-
-alias: add-user
-```
-
-Note: This command is unaware of workspaces.
-
-### Description
-
-Create a new user in the specified registry, and save the credentials to the `.npmrc` file.
-If no registry is specified, the default registry will be used (see [`registry`](/using-npm/registry)).
-
-When you run `npm adduser`, the CLI automatically generates a legacy token of `publish` type.
-For more information, see [About legacy tokens](/about-access-tokens#about-legacy-tokens).
-
-When using `legacy` for your `auth-type`, the username, password, and email are read in from prompts.
-
-### Configuration
-
-#### `registry`
-
-* Default: "https://registry.npmjs.org/"
-* Type: URL
-
-The base URL of the npm registry.
-
-
-
-#### `scope`
-
-* Default: the scope of the current project, if any, or ""
-* Type: String
-
-Associate an operation with a scope for a scoped registry.
-
-Useful when logging in to or out of a private registry:
-
-```
-# log in, linking the scope to the custom registry
-npm login --scope=@mycorp --registry=https://registry.mycorp.com
-
-# log out, removing the link and the auth token
-npm logout --scope=@mycorp
-```
-
-This will cause `@mycorp` to be mapped to the registry for future
-installation of packages specified according to the pattern
-`@mycorp/package`.
-
-This will also cause `npm init` to create a scoped package.
-
-```
-# accept all defaults, and create a package named "@foo/whatever",
-# instead of just named "whatever"
-npm init --scope=@foo --yes
-```
-
-
-
-#### `auth-type`
-
-* Default: "web"
-* Type: "legacy" or "web"
-
-What authentication strategy to use with `login`. Note that if an `otp`
-config is given, this value will always be set to `legacy`.
-
-
-
-### See Also
-
-* [npm registry](/using-npm/registry)
-* [npm config](/commands/npm-config)
-* [npmrc](/configuring-npm/npmrc)
-* [npm owner](/commands/npm-owner)
-* [npm whoami](/commands/npm-whoami)
-* [npm token](/commands/npm-token)
-* [npm profile](/commands/npm-profile)
diff --git a/deps/npm/docs/content/commands/npm-approve-scripts.md b/deps/npm/docs/content/commands/npm-approve-scripts.md
index c4d3c15a814..c7624b8fc9f 100644
--- a/deps/npm/docs/content/commands/npm-approve-scripts.md
+++ b/deps/npm/docs/content/commands/npm-approve-scripts.md
@@ -21,9 +21,10 @@ records which of your dependencies are permitted to run install scripts
(`preinstall`, `install`, `postinstall`, and `prepare` for non-registry
sources). This command is the recommended way to maintain that field.
-In the current release, this field is advisory: install scripts still run
-by default, but installs print a list of packages whose scripts have not
-been reviewed. A future release will block unreviewed install scripts.
+Dependency install scripts are blocked by default. Install commands
+silently skip lifecycle scripts for any dependency that does not have a
+matching entry in `allowScripts`, and end with a list of the packages
+whose scripts were skipped so you can review them with this command.
This command only works inside a project that has a `package.json`. Running
it with `--global` (`-g`) fails with an `EGLOBAL` error, since global
diff --git a/deps/npm/docs/content/commands/npm-audit.md b/deps/npm/docs/content/commands/npm-audit.md
index e0b80373ad1..578e87717d3 100644
--- a/deps/npm/docs/content/commands/npm-audit.md
+++ b/deps/npm/docs/content/commands/npm-audit.md
@@ -27,7 +27,7 @@ This option does not filter the report output, it simply changes the command's f
### Package lock
-By default npm requires a package-lock or shrinkwrap in order to run the audit.
+By default npm requires a package-lock in order to run the audit.
You can bypass the package lock with `--no-package-lock` but be aware the results may be different with every run, since npm will re-build the dependency tree each time.
### Audit Signatures
@@ -313,8 +313,7 @@ will also prevent _writing_ `package-lock.json` if `save` is true.
Dependency types to omit from the installation tree on disk.
Note that these dependencies _are_ still resolved and added to the
-`package-lock.json` or `npm-shrinkwrap.json` file. They are just not
-physically installed on disk.
+`package-lock.json` file. They are just not physically installed on disk.
If a package type appears in both the `--include` and `--omit` lists, then
it will be included.
@@ -365,6 +364,9 @@ Note that commands explicitly intended to run a particular script, such as
run their intended script if `ignore-scripts` is set, but they will *not*
run any pre- or post-scripts.
+Setting `ignore-scripts` also disables `.npm-extension` execution, as if
+`ignore-extension` were set.
+
#### `include-attestations`
diff --git a/deps/npm/docs/content/commands/npm-ci.md b/deps/npm/docs/content/commands/npm-ci.md
index 741caf5eae7..af76af434cb 100644
--- a/deps/npm/docs/content/commands/npm-ci.md
+++ b/deps/npm/docs/content/commands/npm-ci.md
@@ -18,13 +18,12 @@ This command is similar to [`npm install`](/commands/npm-install), except it's m
The main differences between using `npm install` and `npm ci` are:
-* The project **must** have an existing `package-lock.json` or
- `npm-shrinkwrap.json`.
+* The project **must** have an existing `package-lock.json`.
* If dependencies in the package lock do not match those in `package.json`,
`npm ci` will exit with an error, instead of updating the package lock.
* `npm ci` can only install entire projects at a time: individual dependencies cannot be added with this command.
* If a `node_modules` is already present, it will be automatically removed before `npm ci` begins its install.
-* It will never write to `package.json` or any of the package-locks:
+* It will never write to `package.json` or `package-lock.json`:
installs are essentially frozen.
NOTE: If you create your `package-lock.json` file by running `npm install` with flags that can affect the shape of your dependency tree, such as
@@ -122,8 +121,7 @@ on deeper dependencies. Sets `--install-strategy=shallow`.
Dependency types to omit from the installation tree on disk.
Note that these dependencies _are_ still resolved and added to the
-`package-lock.json` or `npm-shrinkwrap.json` file. They are just not
-physically installed on disk.
+`package-lock.json` file. They are just not physically installed on disk.
If a package type appears in both the `--include` and `--omit` lists, then
it will be included.
@@ -195,6 +193,9 @@ Note that commands explicitly intended to run a particular script, such as
run their intended script if `ignore-scripts` is set, but they will *not*
run any pre- or post-scripts.
+Setting `ignore-scripts` also disables `.npm-extension` execution, as if
+`ignore-extension` were set.
+
#### `allow-directory`
@@ -235,7 +236,7 @@ dependencies to be used for other commands like `npm view`
#### `allow-git`
-* Default: "all"
+* Default: "none"
* Type: "all", "none", or "root"
Limits the ability for npm to fetch dependencies from git references. That
@@ -244,6 +245,11 @@ range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.
+As of npm 12 the default is `none`. Git dependencies run `git` against a
+remote repo and may install configuration the project does not control. Opt
+in explicitly per project (in `.npmrc`) or per command (on the CLI) when you
+need git deps.
+
`all` allows any git dependencies to be fetched and installed. `none`
prevents any git dependencies from being fetched and installed. `root` only
allows git dependencies defined in your project's package.json to be fetched
@@ -254,7 +260,7 @@ like `npm view`
#### `allow-remote`
-* Default: "all"
+* Default: "none"
* Type: "all", "none", or "root"
Limits the ability for npm to fetch dependencies from urls. That is,
@@ -263,6 +269,13 @@ range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.
+As of npm 12 the default is `none`. Tarballs that share a hostname with the
+configured registry (the typical case for the npm registry, GitHub Packages,
+and most private registries) are still installed normally. If your registry
+serves tarballs from a different host, set `replace-registry-host` or
+override this setting. Opt in explicitly per project (in `.npmrc`) or per
+command (on the CLI) when you intentionally install from a URL.
+
`all` allows any url to be installed. `none` prevents any url from being
installed. `root` only allows urls defined in your project's package.json to
be installed. Also allows url dependencies to be used for other commands
@@ -290,7 +303,7 @@ Each name is matched against a dependency's resolved identity, not against
the package's self-reported name. `--ignore-scripts` and
`--dangerously-allow-all-scripts` both override this setting.
-
+This value is not exported to the environment for child processes.
#### `strict-allow-scripts`
@@ -298,11 +311,12 @@ the package's self-reported name. `--ignore-scripts` and
* Type: Boolean
If `true`, turn the install-script policy from a warning into a hard error:
-any dependency with install scripts not covered by `allowScripts` will fail
-the install instead of running with a notice.
+any dependency with install scripts that is not covered by `allowScripts`
+will fail the install instead of being blocked with a warning.
Dependencies explicitly denied with `false` in `allowScripts` are always
-silently skipped; this setting only affects unreviewed entries.
+silently skipped; this setting only affects unreviewed entries (packages
+with install scripts that are neither approved nor denied).
`--ignore-scripts` and `--dangerously-allow-all-scripts` both override this
setting.
diff --git a/deps/npm/docs/content/commands/npm-dedupe.md b/deps/npm/docs/content/commands/npm-dedupe.md
index a48bf1bd622..faebfc69e38 100644
--- a/deps/npm/docs/content/commands/npm-dedupe.md
+++ b/deps/npm/docs/content/commands/npm-dedupe.md
@@ -153,8 +153,7 @@ will also prevent _writing_ `package-lock.json` if `save` is true.
Dependency types to omit from the installation tree on disk.
Note that these dependencies _are_ still resolved and added to the
-`package-lock.json` or `npm-shrinkwrap.json` file. They are just not
-physically installed on disk.
+`package-lock.json` file. They are just not physically installed on disk.
If a package type appears in both the `--include` and `--omit` lists, then
it will be included.
@@ -190,6 +189,9 @@ Note that commands explicitly intended to run a particular script, such as
run their intended script if `ignore-scripts` is set, but they will *not*
run any pre- or post-scripts.
+Setting `ignore-scripts` also disables `.npm-extension` execution, as if
+`ignore-extension` were set.
+
#### `allow-directory`
@@ -230,7 +232,7 @@ dependencies to be used for other commands like `npm view`
#### `allow-git`
-* Default: "all"
+* Default: "none"
* Type: "all", "none", or "root"
Limits the ability for npm to fetch dependencies from git references. That
@@ -239,6 +241,11 @@ range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.
+As of npm 12 the default is `none`. Git dependencies run `git` against a
+remote repo and may install configuration the project does not control. Opt
+in explicitly per project (in `.npmrc`) or per command (on the CLI) when you
+need git deps.
+
`all` allows any git dependencies to be fetched and installed. `none`
prevents any git dependencies from being fetched and installed. `root` only
allows git dependencies defined in your project's package.json to be fetched
@@ -249,7 +256,7 @@ like `npm view`
#### `allow-remote`
-* Default: "all"
+* Default: "none"
* Type: "all", "none", or "root"
Limits the ability for npm to fetch dependencies from urls. That is,
@@ -258,6 +265,13 @@ range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.
+As of npm 12 the default is `none`. Tarballs that share a hostname with the
+configured registry (the typical case for the npm registry, GitHub Packages,
+and most private registries) are still installed normally. If your registry
+serves tarballs from a different host, set `replace-registry-host` or
+override this setting. Opt in explicitly per project (in `.npmrc`) or per
+command (on the CLI) when you intentionally install from a URL.
+
`all` allows any url to be installed. `none` prevents any url from being
installed. `root` only allows urls defined in your project's package.json to
be installed. Also allows url dependencies to be used for other commands
diff --git a/deps/npm/docs/content/commands/npm-deny-scripts.md b/deps/npm/docs/content/commands/npm-deny-scripts.md
index fdefca28957..1e6c8e18039 100644
--- a/deps/npm/docs/content/commands/npm-deny-scripts.md
+++ b/deps/npm/docs/content/commands/npm-deny-scripts.md
@@ -20,10 +20,10 @@ Writes `false` entries into the `allowScripts` field of your project's
`package.json`, recording that a dependency must not run install scripts
even if a future version would otherwise be eligible.
-In the current release, install scripts still run by default, so `deny-scripts`
-only affects how installs of denied packages are reported. A future release
-will block unreviewed install scripts and respect deny entries at install
-time.
+Dependency install scripts are blocked by default. Adding a `false`
+entry with `deny-scripts` makes the denial explicit (so it survives
+`npm approve-scripts --all`) and excludes the package from any future
+`--allow-scripts-pending` review prompts.
```bash
npm deny-scripts <pkg> [<pkg> ...]
diff --git a/deps/npm/docs/content/commands/npm-deprecate.md b/deps/npm/docs/content/commands/npm-deprecate.md
index fbb207da6bf..32f4dec1521 100644
--- a/deps/npm/docs/content/commands/npm-deprecate.md
+++ b/deps/npm/docs/content/commands/npm-deprecate.md
@@ -32,7 +32,7 @@ npm deprecate my-thing@1.x "1.x is no longer supported"
In this case, a version `my-thing@1.0.0-beta.0` will also be deprecated.
You must be the package owner to deprecate something.
-See the `owner` and `adduser` help topics.
+See the `owner` and `login` help topics.
To un-deprecate a package, specify an empty string (`""`) for the `message` argument.
Note that you must use double quotes with no space between them to format an empty string.
@@ -82,4 +82,4 @@ Note: This is NOT honored by other network related commands, eg `dist-tags`,
* [npm publish](/commands/npm-publish)
* [npm registry](/using-npm/registry)
* [npm owner](/commands/npm-owner)
-* [npm adduser](/commands/npm-adduser)
+* [npm login](/commands/npm-login)
diff --git a/deps/npm/docs/content/commands/npm-exec.md b/deps/npm/docs/content/commands/npm-exec.md
index ff08d07786a..95789626f28 100644
--- a/deps/npm/docs/content/commands/npm-exec.md
+++ b/deps/npm/docs/content/commands/npm-exec.md
@@ -178,7 +178,7 @@ Each name is matched against a dependency's resolved identity, not against
the package's self-reported name. `--ignore-scripts` and
`--dangerously-allow-all-scripts` both override this setting.
-
+This value is not exported to the environment for child processes.
#### `strict-allow-scripts`
@@ -186,11 +186,12 @@ the package's self-reported name. `--ignore-scripts` and
* Type: Boolean
If `true`, turn the install-script policy from a warning into a hard error:
-any dependency with install scripts not covered by `allowScripts` will fail
-the install instead of running with a notice.
+any dependency with install scripts that is not covered by `allowScripts`
+will fail the install instead of being blocked with a warning.
Dependencies explicitly denied with `false` in `allowScripts` are always
-silently skipped; this setting only affects unreviewed entries.
+silently skipped; this setting only affects unreviewed entries (packages
+with install scripts that are neither approved nor denied).
`--ignore-scripts` and `--dangerously-allow-all-scripts` both override this
setting.
diff --git a/deps/npm/docs/content/commands/npm-find-dupes.md b/deps/npm/docs/content/commands/npm-find-dupes.md
index 2d72186fe5a..ad6c3e86da9 100644
--- a/deps/npm/docs/content/commands/npm-find-dupes.md
+++ b/deps/npm/docs/content/commands/npm-find-dupes.md
@@ -104,8 +104,7 @@ will also prevent _writing_ `package-lock.json` if `save` is true.
Dependency types to omit from the installation tree on disk.
Note that these dependencies _are_ still resolved and added to the
-`package-lock.json` or `npm-shrinkwrap.json` file. They are just not
-physically installed on disk.
+`package-lock.json` file. They are just not physically installed on disk.
If a package type appears in both the `--include` and `--omit` lists, then
it will be included.
@@ -141,6 +140,9 @@ Note that commands explicitly intended to run a particular script, such as
run their intended script if `ignore-scripts` is set, but they will *not*
run any pre- or post-scripts.
+Setting `ignore-scripts` also disables `.npm-extension` execution, as if
+`ignore-extension` were set.
+
#### `audit`
diff --git a/deps/npm/docs/content/commands/npm-init.md b/deps/npm/docs/content/commands/npm-init.md
index 4b3b6342380..5284f23fe24 100644
--- a/deps/npm/docs/content/commands/npm-init.md
+++ b/deps/npm/docs/content/commands/npm-init.md
@@ -157,10 +157,11 @@ homepage.
#### `init-license`
-* Default: "ISC"
+* Default: ""
* Type: String
-The value `npm init` should use by default for the package license.
+The value `npm init` should use by default for the package license. If not
+set, the license field will be omitted from new packages.
diff --git a/deps/npm/docs/content/commands/npm-install-ci-test.md b/deps/npm/docs/content/commands/npm-install-ci-test.md
index 2194a4df84a..0103ca86ac5 100644
--- a/deps/npm/docs/content/commands/npm-install-ci-test.md
+++ b/deps/npm/docs/content/commands/npm-install-ci-test.md
@@ -75,8 +75,7 @@ on deeper dependencies. Sets `--install-strategy=shallow`.
Dependency types to omit from the installation tree on disk.
Note that these dependencies _are_ still resolved and added to the
-`package-lock.json` or `npm-shrinkwrap.json` file. They are just not
-physically installed on disk.
+`package-lock.json` file. They are just not physically installed on disk.
If a package type appears in both the `--include` and `--omit` lists, then
it will be included.
@@ -148,6 +147,9 @@ Note that commands explicitly intended to run a particular script, such as
run their intended script if `ignore-scripts` is set, but they will *not*
run any pre- or post-scripts.
+Setting `ignore-scripts` also disables `.npm-extension` execution, as if
+`ignore-extension` were set.
+
#### `allow-directory`
@@ -188,7 +190,7 @@ dependencies to be used for other commands like `npm view`
#### `allow-git`
-* Default: "all"
+* Default: "none"
* Type: "all", "none", or "root"
Limits the ability for npm to fetch dependencies from git references. That
@@ -197,6 +199,11 @@ range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.
+As of npm 12 the default is `none`. Git dependencies run `git` against a
+remote repo and may install configuration the project does not control. Opt
+in explicitly per project (in `.npmrc`) or per command (on the CLI) when you
+need git deps.
+
`all` allows any git dependencies to be fetched and installed. `none`
prevents any git dependencies from being fetched and installed. `root` only
allows git dependencies defined in your project's package.json to be fetched
@@ -207,7 +214,7 @@ like `npm view`
#### `allow-remote`
-* Default: "all"
+* Default: "none"
* Type: "all", "none", or "root"
Limits the ability for npm to fetch dependencies from urls. That is,
@@ -216,6 +223,13 @@ range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.
+As of npm 12 the default is `none`. Tarballs that share a hostname with the
+configured registry (the typical case for the npm registry, GitHub Packages,
+and most private registries) are still installed normally. If your registry
+serves tarballs from a different host, set `replace-registry-host` or
+override this setting. Opt in explicitly per project (in `.npmrc`) or per
+command (on the CLI) when you intentionally install from a URL.
+
`all` allows any url to be installed. `none` prevents any url from being
installed. `root` only allows urls defined in your project's package.json to
be installed. Also allows url dependencies to be used for other commands
@@ -243,7 +257,7 @@ Each name is matched against a dependency's resolved identity, not against
the package's self-reported name. `--ignore-scripts` and
`--dangerously-allow-all-scripts` both override this setting.
-
+This value is not exported to the environment for child processes.
#### `strict-allow-scripts`
@@ -251,11 +265,12 @@ the package's self-reported name. `--ignore-scripts` and
* Type: Boolean
If `true`, turn the install-script policy from a warning into a hard error:
-any dependency with install scripts not covered by `allowScripts` will fail
-the install instead of running with a notice.
+any dependency with install scripts that is not covered by `allowScripts`
+will fail the install instead of being blocked with a warning.
Dependencies explicitly denied with `false` in `allowScripts` are always
-silently skipped; this setting only affects unreviewed entries.
+silently skipped; this setting only affects unreviewed entries (packages
+with install scripts that are neither approved nor denied).
`--ignore-scripts` and `--dangerously-allow-all-scripts` both override this
setting.
diff --git a/deps/npm/docs/content/commands/npm-install-test.md b/deps/npm/docs/content/commands/npm-install-test.md
index e13f79a51e6..ed5ed2bd03f 100644
--- a/deps/npm/docs/content/commands/npm-install-test.md
+++ b/deps/npm/docs/content/commands/npm-install-test.md
@@ -116,8 +116,7 @@ on deeper dependencies. Sets `--install-strategy=shallow`.
Dependency types to omit from the installation tree on disk.
Note that these dependencies _are_ still resolved and added to the
-`package-lock.json` or `npm-shrinkwrap.json` file. They are just not
-physically installed on disk.
+`package-lock.json` file. They are just not physically installed on disk.
If a package type appears in both the `--include` and `--omit` lists, then
it will be included.
@@ -225,6 +224,9 @@ Note that commands explicitly intended to run a particular script, such as
run their intended script if `ignore-scripts` is set, but they will *not*
run any pre- or post-scripts.
+Setting `ignore-scripts` also disables `.npm-extension` execution, as if
+`ignore-extension` were set.
+
#### `allow-directory`
@@ -265,7 +267,7 @@ dependencies to be used for other commands like `npm view`
#### `allow-git`
-* Default: "all"
+* Default: "none"
* Type: "all", "none", or "root"
Limits the ability for npm to fetch dependencies from git references. That
@@ -274,6 +276,11 @@ range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.
+As of npm 12 the default is `none`. Git dependencies run `git` against a
+remote repo and may install configuration the project does not control. Opt
+in explicitly per project (in `.npmrc`) or per command (on the CLI) when you
+need git deps.
+
`all` allows any git dependencies to be fetched and installed. `none`
prevents any git dependencies from being fetched and installed. `root` only
allows git dependencies defined in your project's package.json to be fetched
@@ -284,7 +291,7 @@ like `npm view`
#### `allow-remote`
-* Default: "all"
+* Default: "none"
* Type: "all", "none", or "root"
Limits the ability for npm to fetch dependencies from urls. That is,
@@ -293,6 +300,13 @@ range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.
+As of npm 12 the default is `none`. Tarballs that share a hostname with the
+configured registry (the typical case for the npm registry, GitHub Packages,
+and most private registries) are still installed normally. If your registry
+serves tarballs from a different host, set `replace-registry-host` or
+override this setting. Opt in explicitly per project (in `.npmrc`) or per
+command (on the CLI) when you intentionally install from a URL.
+
`all` allows any url to be installed. `none` prevents any url from being
installed. `root` only allows urls defined in your project's package.json to
be installed. Also allows url dependencies to be used for other commands
@@ -320,7 +334,7 @@ Each name is matched against a dependency's resolved identity, not against
the package's self-reported name. `--ignore-scripts` and
`--dangerously-allow-all-scripts` both override this setting.
-
+This value is not exported to the environment for child processes.
#### `strict-allow-scripts`
@@ -328,11 +342,12 @@ the package's self-reported name. `--ignore-scripts` and
* Type: Boolean
If `true`, turn the install-script policy from a warning into a hard error:
-any dependency with install scripts not covered by `allowScripts` will fail
-the install instead of running with a notice.
+any dependency with install scripts that is not covered by `allowScripts`
+will fail the install instead of being blocked with a warning.
Dependencies explicitly denied with `false` in `allowScripts` are always
-silently skipped; this setting only affects unreviewed entries.
+silently skipped; this setting only affects unreviewed entries (packages
+with install scripts that are neither approved nor denied).
`--ignore-scripts` and `--dangerously-allow-all-scripts` both override this
setting.
diff --git a/deps/npm/docs/content/commands/npm-install.md b/deps/npm/docs/content/commands/npm-install.md
index 98d69d5e842..19efd10b711 100644
--- a/deps/npm/docs/content/commands/npm-install.md
+++ b/deps/npm/docs/content/commands/npm-install.md
@@ -15,13 +15,12 @@ aliases: add, i, in, ins, inst, insta, instal, isnt, isnta, isntal, isntall
### Description
This command installs a package and any packages that it depends on.
-If the package has a package-lock, or an npm shrinkwrap file, or a yarn lock file, the installation of dependencies will be driven by that, respecting the following order of precedence:
+If the package has a package-lock or a yarn lock file, the installation of dependencies will be driven by that, respecting the following order of precedence:
-* `npm-shrinkwrap.json`
* `package-lock.json`
* `yarn.lock`
-See [package-lock.json](/configuring-npm/package-lock-json) and [`npm shrinkwrap`](/commands/npm-shrinkwrap).
+See [package-lock.json](/configuring-npm/package-lock-json).
#### How `npm install` uses `package-lock.json`
@@ -140,7 +139,7 @@ Even if you never publish your package, you can still get a lot of benefits of u
* `-B, --save-bundle`: Saved dependencies will also be added to your `bundleDependencies` list.
- Further, if you have an `npm-shrinkwrap.json` or `package-lock.json` then it will be updated as well.
+ Further, if you have a `package-lock.json` then it will be updated as well.
`<scope>` is optional.
The package will be downloaded from the registry associated with the specified scope.
@@ -458,8 +457,7 @@ on deeper dependencies. Sets `--install-strategy=shallow`.
Dependency types to omit from the installation tree on disk.
Note that these dependencies _are_ still resolved and added to the
-`package-lock.json` or `npm-shrinkwrap.json` file. They are just not
-physically installed on disk.
+`package-lock.json` file. They are just not physically installed on disk.
If a package type appears in both the `--include` and `--omit` lists, then
it will be included.
@@ -567,6 +565,9 @@ Note that commands explicitly intended to run a particular script, such as
run their intended script if `ignore-scripts` is set, but they will *not*
run any pre- or post-scripts.
+Setting `ignore-scripts` also disables `.npm-extension` execution, as if
+`ignore-extension` were set.
+
#### `allow-directory`
@@ -607,7 +608,7 @@ dependencies to be used for other commands like `npm view`
#### `allow-git`
-* Default: "all"
+* Default: "none"
* Type: "all", "none", or "root"
Limits the ability for npm to fetch dependencies from git references. That
@@ -616,6 +617,11 @@ range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.
+As of npm 12 the default is `none`. Git dependencies run `git` against a
+remote repo and may install configuration the project does not control. Opt
+in explicitly per project (in `.npmrc`) or per command (on the CLI) when you
+need git deps.
+
`all` allows any git dependencies to be fetched and installed. `none`
prevents any git dependencies from being fetched and installed. `root` only
allows git dependencies defined in your project's package.json to be fetched
@@ -626,7 +632,7 @@ like `npm view`
#### `allow-remote`
-* Default: "all"
+* Default: "none"
* Type: "all", "none", or "root"
Limits the ability for npm to fetch dependencies from urls. That is,
@@ -635,6 +641,13 @@ range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.
+As of npm 12 the default is `none`. Tarballs that share a hostname with the
+configured registry (the typical case for the npm registry, GitHub Packages,
+and most private registries) are still installed normally. If your registry
+serves tarballs from a different host, set `replace-registry-host` or
+override this setting. Opt in explicitly per project (in `.npmrc`) or per
+command (on the CLI) when you intentionally install from a URL.
+
`all` allows any url to be installed. `none` prevents any url from being
installed. `root` only allows urls defined in your project's package.json to
be installed. Also allows url dependencies to be used for other commands
@@ -662,7 +675,7 @@ Each name is matched against a dependency's resolved identity, not against
the package's self-reported name. `--ignore-scripts` and
`--dangerously-allow-all-scripts` both override this setting.
-
+This value is not exported to the environment for child processes.
#### `strict-allow-scripts`
@@ -670,11 +683,12 @@ the package's self-reported name. `--ignore-scripts` and
* Type: Boolean
If `true`, turn the install-script policy from a warning into a hard error:
-any dependency with install scripts not covered by `allowScripts` will fail
-the install instead of running with a notice.
+any dependency with install scripts that is not covered by `allowScripts`
+will fail the install instead of being blocked with a warning.
Dependencies explicitly denied with `false` in `allowScripts` are always
-silently skipped; this setting only affects unreviewed entries.
+silently skipped; this setting only affects unreviewed entries (packages
+with install scripts that are neither approved nor denied).
`--ignore-scripts` and `--dangerously-allow-all-scripts` both override this
setting.
@@ -971,6 +985,5 @@ See [folders](/configuring-npm/folders) for a more detailed description of the s
* [npm registry](/using-npm/registry)
* [npm dist-tag](/commands/npm-dist-tag)
* [npm uninstall](/commands/npm-uninstall)
-* [npm shrinkwrap](/commands/npm-shrinkwrap)
* [package.json](/configuring-npm/package-json)
* [workspaces](/using-npm/workspaces)
diff --git a/deps/npm/docs/content/commands/npm-link.md b/deps/npm/docs/content/commands/npm-link.md
index fa9626c4edd..2e9369d0534 100644
--- a/deps/npm/docs/content/commands/npm-link.md
+++ b/deps/npm/docs/content/commands/npm-link.md
@@ -217,8 +217,7 @@ will also prevent _writing_ `package-lock.json` if `save` is true.
Dependency types to omit from the installation tree on disk.
Note that these dependencies _are_ still resolved and added to the
-`package-lock.json` or `npm-shrinkwrap.json` file. They are just not
-physically installed on disk.
+`package-lock.json` file. They are just not physically installed on disk.
If a package type appears in both the `--include` and `--omit` lists, then
it will be included.
@@ -254,6 +253,9 @@ Note that commands explicitly intended to run a particular script, such as
run their intended script if `ignore-scripts` is set, but they will *not*
run any pre- or post-scripts.
+Setting `ignore-scripts` also disables `.npm-extension` execution, as if
+`ignore-extension` were set.
+
#### `allow-directory`
@@ -294,7 +296,7 @@ dependencies to be used for other commands like `npm view`
#### `allow-git`
-* Default: "all"
+* Default: "none"
* Type: "all", "none", or "root"
Limits the ability for npm to fetch dependencies from git references. That
@@ -303,6 +305,11 @@ range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.
+As of npm 12 the default is `none`. Git dependencies run `git` against a
+remote repo and may install configuration the project does not control. Opt
+in explicitly per project (in `.npmrc`) or per command (on the CLI) when you
+need git deps.
+
`all` allows any git dependencies to be fetched and installed. `none`
prevents any git dependencies from being fetched and installed. `root` only
allows git dependencies defined in your project's package.json to be fetched
@@ -313,7 +320,7 @@ like `npm view`
#### `allow-remote`
-* Default: "all"
+* Default: "none"
* Type: "all", "none", or "root"
Limits the ability for npm to fetch dependencies from urls. That is,
@@ -322,6 +329,13 @@ range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.
+As of npm 12 the default is `none`. Tarballs that share a hostname with the
+configured registry (the typical case for the npm registry, GitHub Packages,
+and most private registries) are still installed normally. If your registry
+serves tarballs from a different host, set `replace-registry-host` or
+override this setting. Opt in explicitly per project (in `.npmrc`) or per
+command (on the CLI) when you intentionally install from a URL.
+
`all` allows any url to be installed. `none` prevents any url from being
installed. `root` only allows urls defined in your project's package.json to
be installed. Also allows url dependencies to be used for other commands
diff --git a/deps/npm/docs/content/commands/npm-ll.md b/deps/npm/docs/content/commands/npm-ll.md
index dacac2f5a26..0c5370263ce 100644
--- a/deps/npm/docs/content/commands/npm-ll.md
+++ b/deps/npm/docs/content/commands/npm-ll.md
@@ -100,8 +100,7 @@ project. If `--all` is set, then npm will show all dependencies by default.
Dependency types to omit from the installation tree on disk.
Note that these dependencies _are_ still resolved and added to the
-`package-lock.json` or `npm-shrinkwrap.json` file. They are just not
-physically installed on disk.
+`package-lock.json` file. They are just not physically installed on disk.
If a package type appears in both the `--include` and `--omit` lists, then
it will be included.
diff --git a/deps/npm/docs/content/commands/npm-logout.md b/deps/npm/docs/content/commands/npm-logout.md
index 0008259ce78..3bed6ad585e 100644
--- a/deps/npm/docs/content/commands/npm-logout.md
+++ b/deps/npm/docs/content/commands/npm-logout.md
@@ -66,7 +66,7 @@ npm init --scope=@foo --yes
### See Also
-* [npm adduser](/commands/npm-adduser)
+* [npm login](/commands/npm-login)
* [npm registry](/using-npm/registry)
* [npm config](/commands/npm-config)
* [npm whoami](/commands/npm-whoami)
diff --git a/deps/npm/docs/content/commands/npm-ls.md b/deps/npm/docs/content/commands/npm-ls.md
index b38603c203f..222e62cb8cf 100644
--- a/deps/npm/docs/content/commands/npm-ls.md
+++ b/deps/npm/docs/content/commands/npm-ls.md
@@ -23,7 +23,7 @@ Note that nested packages will *also* show the paths to the specified packages.
For example, running `npm ls promzard` in npm's source tree will show:
```bash
-npm@11.19.1 /path/to/npm
+npm@12.1.0 /path/to/npm
└─┬ init-package-json@0.0.4
└── promzard@0.1.5
```
@@ -120,8 +120,7 @@ project. If `--all` is set, then npm will show all dependencies by default.
Dependency types to omit from the installation tree on disk.
Note that these dependencies _are_ still resolved and added to the
-`package-lock.json` or `npm-shrinkwrap.json` file. They are just not
-physically installed on disk.
+`package-lock.json` file. They are just not physically installed on disk.
If a package type appears in both the `--include` and `--omit` lists, then
it will be included.
diff --git a/deps/npm/docs/content/commands/npm-owner.md b/deps/npm/docs/content/commands/npm-owner.md
index f20fa216860..8fe0aa94e84 100644
--- a/deps/npm/docs/content/commands/npm-owner.md
+++ b/deps/npm/docs/content/commands/npm-owner.md
@@ -101,4 +101,4 @@ This value is not exported to the environment for child processes.
* [npm profile](/commands/npm-profile)
* [npm publish](/commands/npm-publish)
* [npm registry](/using-npm/registry)
-* [npm adduser](/commands/npm-adduser)
+* [npm login](/commands/npm-login)
diff --git a/deps/npm/docs/content/commands/npm-pack.md b/deps/npm/docs/content/commands/npm-pack.md
index 7d9c8974d29..0b70db47a2d 100644
--- a/deps/npm/docs/content/commands/npm-pack.md
+++ b/deps/npm/docs/content/commands/npm-pack.md
@@ -115,6 +115,9 @@ Note that commands explicitly intended to run a particular script, such as
run their intended script if `ignore-scripts` is set, but they will *not*
run any pre- or post-scripts.
+Setting `ignore-scripts` also disables `.npm-extension` execution, as if
+`ignore-extension` were set.
+
### Description
diff --git a/deps/npm/docs/content/commands/npm-patch.md b/deps/npm/docs/content/commands/npm-patch.md
new file mode 100644
index 00000000000..5ba7a1c90f8
--- /dev/null
+++ b/deps/npm/docs/content/commands/npm-patch.md
@@ -0,0 +1,162 @@
+---
+title: npm-patch
+section: 1
+description: Apply local patches to installed dependencies
+---
+
+### Synopsis
+
+```bash
+npm patch <pkg>[@<version>]
+npm patch add <pkg>[@<version>] [--edit-dir <path>] [--ignore-existing]
+npm patch commit <edit-dir> [--patches-dir <dir>] [--keep-edit-dir]
+npm patch update <pkg>[@<old-version>] [--to <new-version>] [--patches-dir <dir>]
+npm patch ls
+npm patch rm <pkg>[@<version>]
+```
+
+Note: This command is unaware of workspaces.
+
+### Description
+
+`npm patch` lets you apply small, local modifications to an installed
+dependency and have them re-applied automatically on every install. Patches
+are declared in the `patchedDependencies` field of your root `package.json`,
+stored as plain unified diffs under the `patches/` directory, and recorded with
+a content hash in `package-lock.json`.
+
+Because patches are applied during the install itself, they work regardless of
+`install-strategy`, apply to transitive dependencies, and are **not** disabled
+by `--ignore-scripts`.
+
+The bare form `npm patch <pkg>` is shorthand for `npm patch add <pkg>`. A
+package literally named like a subcommand must use the explicit form, e.g.
+`npm patch add add`.
+
+* `npm patch add <pkg>[@<version>]`
+
+ Prepares a package for editing. npm extracts a clean copy of the resolved
+ package tarball into a temporary directory outside `node_modules` and prints
+ its path. Edit the files there, then run `npm patch commit`.
+
+ If more than one version of `<pkg>` is installed, re-run with an exact
+ selector such as `npm patch add lodash@4.17.21`.
+
+* `npm patch commit <edit-dir>`
+
+ Diffs the edited directory against a clean copy of the original tarball,
+ writes the unified diff to `<patches-dir>/<name>@<version>.patch`, adds the
+ entry to `patchedDependencies`, and updates `package-lock.json`.
+
+* `npm patch ls`
+
+ Lists registered patches and how many installed nodes each one matches.
+
+* `npm patch rm <pkg>[@<version>]`
+
+ Removes the matching entries from `patchedDependencies`, deletes the patch
+ file when no other entry references it, and updates `package-lock.json`. If
+ `<version>` is omitted, all entries for `<pkg>` are removed.
+
+### Failure modes
+
+By default any patch problem is a hard error that aborts the install: a patch
+that fails to apply, a registered patch that matches no installed package, a
+missing patch file, or a patch whose hash does not match the lockfile.
+
+Two CLI-only flags relax this for one-off cases: `--allow-unused-patches` and
+`--ignore-patch-failures`.
+
+### Configuration
+
+#### `patches-dir`
+
+* Default: "patches"
+* Type: String
+
+The directory, relative to the project root, where `npm patch commit` writes
+patch files for `patchedDependencies`.
+
+
+
+#### `allow-unused-patches`
+
+* Default: false
+* Type: Boolean
+
+Install even when a registered patch in `patchedDependencies` matches no
+installed package. Does not silence patch apply failures.
+
+This flag is only honored when passed on the command line; it is ignored in
+`.npmrc` and environment variables, and rejected by `npm ci`.
+
+
+
+#### `ignore-patch-failures`
+
+* Default: false
+* Type: Boolean
+
+Install even when a registered patch fails to apply, with a warning per
+failure. Intended for incident response only.
+
+This flag is only honored when passed on the command line; it is ignored in
+`.npmrc` and environment variables, and rejected by `npm ci`.
+
+
+
+#### `edit-dir`
+
+* Default: null
+* Type: null or Path
+
+Override the temporary directory used by `npm patch add` to prepare a
+package for editing.
+
+
+
+#### `ignore-existing`
+
+* Default: false
+* Type: Boolean
+
+With `npm patch add`, discard a previous unfinished edit directory and start
+fresh.
+
+
+
+#### `keep-edit-dir`
+
+* Default: false
+* Type: Boolean
+
+With `npm patch commit`, do not remove the edit directory after committing
+the patch.
+
+
+
+#### `to`
+
+* Default: null
+* Type: null or String
+
+Used by `npm patch update` to set the version to rebase a patch onto when it
+cannot be read from `package-lock.json` — for example an exact-version
+selector, or a version that has not been installed yet.
+
+
+
+#### `registry`
+
+* Default: "https://registry.npmjs.org/"
+* Type: URL
+
+The base URL of the npm registry.
+
+
+## See Also
+
+* [npm install](/commands/npm-install)
+* [npm ci](/commands/npm-ci)
+* [package-lock.json](/configuring-npm/package-lock-json)
+* [config](/commands/npm-config)
diff --git a/deps/npm/docs/content/commands/npm-profile.md b/deps/npm/docs/content/commands/npm-profile.md
index 8c1ad4ee79c..04650228532 100644
--- a/deps/npm/docs/content/commands/npm-profile.md
+++ b/deps/npm/docs/content/commands/npm-profile.md
@@ -29,15 +29,13 @@ email: e@example.com (verified)
two-factor auth: auth-and-writes
fullname: Example User
homepage:
-freenode:
-twitter:
github:
created: 2015-02-26T01:38:35.892Z
updated: 2017-10-02T21:29:45.922Z
```
* `npm profile set <property> <value>`: Set the value of a profile property.
-You can set the following properties this way: email, fullname, homepage, freenode, twitter, github
+You can set the following properties this way: email, fullname, homepage, github
* `npm profile set password`: Change your password.
This is interactive, you'll be prompted for your current password and a new password.
@@ -106,7 +104,7 @@ password, npm will prompt on the command line for one.
### See Also
-* [npm adduser](/commands/npm-adduser)
+* [npm login](/commands/npm-login)
* [npm registry](/using-npm/registry)
* [npm config](/commands/npm-config)
* [npmrc](/configuring-npm/npmrc)
diff --git a/deps/npm/docs/content/commands/npm-prune.md b/deps/npm/docs/content/commands/npm-prune.md
index 35150fd5abc..4f06e712622 100644
--- a/deps/npm/docs/content/commands/npm-prune.md
+++ b/deps/npm/docs/content/commands/npm-prune.md
@@ -37,8 +37,7 @@ However, in the real world, operation is not always "normal". When crashes or m
Dependency types to omit from the installation tree on disk.
Note that these dependencies _are_ still resolved and added to the
-`package-lock.json` or `npm-shrinkwrap.json` file. They are just not
-physically installed on disk.
+`package-lock.json` file. They are just not physically installed on disk.
If a package type appears in both the `--include` and `--omit` lists, then
it will be included.
@@ -118,6 +117,9 @@ Note that commands explicitly intended to run a particular script, such as
run their intended script if `ignore-scripts` is set, but they will *not*
run any pre- or post-scripts.
+Setting `ignore-scripts` also disables `.npm-extension` execution, as if
+`ignore-extension` were set.
+
#### `workspace`
diff --git a/deps/npm/docs/content/commands/npm-publish.md b/deps/npm/docs/content/commands/npm-publish.md
index 04c020b3563..274773ec763 100644
--- a/deps/npm/docs/content/commands/npm-publish.md
+++ b/deps/npm/docs/content/commands/npm-publish.md
@@ -222,6 +222,9 @@ This value is not exported to the environment for child processes.
When publishing from a supported cloud CI/CD system, the package will be
publicly linked to where it was built and published from.
+When the `provenance-file` config is set, it takes precedence and automatic
+provenance generation (including via trusted publishing/OIDC) is skipped.
+
This config cannot be used with: `provenance-file`
#### `provenance-file`
@@ -231,6 +234,9 @@ This config cannot be used with: `provenance-file`
When publishing, the provenance bundle at the given path will be used.
+This takes precedence over automatic provenance generation in trusted
+publishing flows.
+
This config cannot be used with: `provenance`
### See Also
@@ -239,7 +245,7 @@ This config cannot be used with: `provenance`
* [npm-packlist package](http://npm.im/npm-packlist)
* [npm registry](/using-npm/registry)
* [npm scope](/using-npm/scope)
-* [npm adduser](/commands/npm-adduser)
+* [npm login](/commands/npm-login)
* [npm owner](/commands/npm-owner)
* [npm deprecate](/commands/npm-deprecate)
* [npm dist-tag](/commands/npm-dist-tag)
diff --git a/deps/npm/docs/content/commands/npm-query.md b/deps/npm/docs/content/commands/npm-query.md
index 4349e47ad23..e355aede8fb 100644
--- a/deps/npm/docs/content/commands/npm-query.md
+++ b/deps/npm/docs/content/commands/npm-query.md
@@ -154,7 +154,7 @@ $ npm query ':root>:outdated(in-range).prod' --no-expect-results
### Package lock only mode
-If package-lock-only is enabled, only the information in the package lock (or shrinkwrap) is loaded.
+If package-lock-only is enabled, only the information in the package lock is loaded.
This means that information from the package.json files of your dependencies will not be included in the result set (e.g. description, homepage, engines).
### Configuration
diff --git a/deps/npm/docs/content/commands/npm-rebuild.md b/deps/npm/docs/content/commands/npm-rebuild.md
index c70307a2a7f..f3107c60567 100644
--- a/deps/npm/docs/content/commands/npm-rebuild.md
+++ b/deps/npm/docs/content/commands/npm-rebuild.md
@@ -98,6 +98,9 @@ Note that commands explicitly intended to run a particular script, such as
run their intended script if `ignore-scripts` is set, but they will *not*
run any pre- or post-scripts.
+Setting `ignore-scripts` also disables `.npm-extension` execution, as if
+`ignore-extension` were set.
+
#### `allow-scripts`
@@ -120,7 +123,7 @@ Each name is matched against a dependency's resolved identity, not against
the package's self-reported name. `--ignore-scripts` and
`--dangerously-allow-all-scripts` both override this setting.
-
+This value is not exported to the environment for child processes.
#### `strict-allow-scripts`
@@ -128,11 +131,12 @@ the package's self-reported name. `--ignore-scripts` and
* Type: Boolean
If `true`, turn the install-script policy from a warning into a hard error:
-any dependency with install scripts not covered by `allowScripts` will fail
-the install instead of running with a notice.
+any dependency with install scripts that is not covered by `allowScripts`
+will fail the install instead of being blocked with a warning.
Dependencies explicitly denied with `false` in `allowScripts` are always
-silently skipped; this setting only affects unreviewed entries.
+silently skipped; this setting only affects unreviewed entries (packages
+with install scripts that are neither approved nor denied).
`--ignore-scripts` and `--dangerously-allow-all-scripts` both override this
setting.
diff --git a/deps/npm/docs/content/commands/npm-restart.md b/deps/npm/docs/content/commands/npm-restart.md
index 03eeec5da78..85c974ffe49 100644
--- a/deps/npm/docs/content/commands/npm-restart.md
+++ b/deps/npm/docs/content/commands/npm-restart.md
@@ -46,6 +46,9 @@ Note that commands explicitly intended to run a particular script, such as
run their intended script if `ignore-scripts` is set, but they will *not*
run any pre- or post-scripts.
+Setting `ignore-scripts` also disables `.npm-extension` execution, as if
+`ignore-extension` were set.
+
#### `script-shell`
diff --git a/deps/npm/docs/content/commands/npm-run.md b/deps/npm/docs/content/commands/npm-run.md
index 9894e4b939d..51f81e292b8 100644
--- a/deps/npm/docs/content/commands/npm-run.md
+++ b/deps/npm/docs/content/commands/npm-run.md
@@ -193,6 +193,9 @@ Note that commands explicitly intended to run a particular script, such as
run their intended script if `ignore-scripts` is set, but they will *not*
run any pre- or post-scripts.
+Setting `ignore-scripts` also disables `.npm-extension` execution, as if
+`ignore-extension` were set.
+
#### `foreground-scripts`
diff --git a/deps/npm/docs/content/commands/npm-sbom.md b/deps/npm/docs/content/commands/npm-sbom.md
index f15e30bfcd0..8c130288db4 100644
--- a/deps/npm/docs/content/commands/npm-sbom.md
+++ b/deps/npm/docs/content/commands/npm-sbom.md
@@ -207,7 +207,7 @@ SBOMs can be generated in either [SPDX](https://spdx.dev/) or [CycloneDX](https:
### Package lock only mode
-If package-lock-only is enabled, only the information in the package lock (or shrinkwrap) is loaded.
+If package-lock-only is enabled, only the information in the package lock is loaded.
This means that information from the package.json files of your dependencies will not be included in the result set (e.g.
description, homepage, engines).
@@ -222,8 +222,7 @@ description, homepage, engines).
Dependency types to omit from the installation tree on disk.
Note that these dependencies _are_ still resolved and added to the
-`package-lock.json` or `npm-shrinkwrap.json` file. They are just not
-physically installed on disk.
+`package-lock.json` file. They are just not physically installed on disk.
If a package type appears in both the `--include` and `--omit` lists, then
it will be included.
diff --git a/deps/npm/docs/content/commands/npm-shrinkwrap.md b/deps/npm/docs/content/commands/npm-shrinkwrap.md
deleted file mode 100644
index 813affd9f56..00000000000
--- a/deps/npm/docs/content/commands/npm-shrinkwrap.md
+++ /dev/null
@@ -1,29 +0,0 @@
----
-title: npm-shrinkwrap
-section: 1
-description: Lock down dependency versions for publication
----
-
-### Synopsis
-
-```bash
-npm shrinkwrap
-```
-
-Note: This command is unaware of workspaces.
-
-### Description
-
-This command repurposes `package-lock.json` into a publishable `npm-shrinkwrap.json` or simply creates a new one.
-The file created and updated by this command will then take precedence over any other existing or future `package-lock.json` files.
-For a detailed explanation of the design and purpose of package locks in npm, see [package-lock-json](/configuring-npm/package-lock-json).
-
-### See Also
-
-* [npm install](/commands/npm-install)
-* [npm run](/commands/npm-run)
-* [npm scripts](/using-npm/scripts)
-* [package.json](/configuring-npm/package-json)
-* [package-lock.json](/configuring-npm/package-lock-json)
-* [npm-shrinkwrap.json](/configuring-npm/npm-shrinkwrap-json)
-* [npm ls](/commands/npm-ls)
diff --git a/deps/npm/docs/content/commands/npm-stage.md b/deps/npm/docs/content/commands/npm-stage.md
index 798d6c2d953..4228a43cce7 100644
--- a/deps/npm/docs/content/commands/npm-stage.md
+++ b/deps/npm/docs/content/commands/npm-stage.md
@@ -158,7 +158,7 @@ npm stage publish <package-spec>
| `--workspace`, `-w` | | String (can be set multiple times) | Enable running a command in the context of the configured workspaces of the current project while filtering by running only the workspaces defined by this configuration option. Valid values for the `workspace` config are either: * Workspace names * Path to a workspace directory * Path to a parent workspace directory (will result in selecting all workspaces within that folder) When set for the `npm init` command, this may be set to the folder of a workspace which does not yet exist, to create the folder and set it up as a brand new workspace within the project. |
| `--workspaces` | null | null or Boolean | Set to true to run the command in the context of **all** configured workspaces. Explicitly setting this to false will cause commands like `install` to ignore workspaces altogether. When not set explicitly: - Commands that operate on the `node_modules` tree (install, update, etc.) will link workspaces into the `node_modules` folder. - Commands that do other things (test, exec, publish, etc.) will operate on the root project, _unless_ one or more workspaces are specified in the `workspace` config. |
| `--include-workspace-root` | false | Boolean | Include the workspace root when workspaces are enabled for a command. When false, specifying individual workspaces via the `workspace` config, or all workspaces via the `workspaces` flag, will cause npm to operate only on the specified workspaces, and not on the root project. |
-| `--provenance` | false | Boolean | When publishing from a supported cloud CI/CD system, the package will be publicly linked to where it was built and published from. |
+| `--provenance` | false | Boolean | When publishing from a supported cloud CI/CD system, the package will be publicly linked to where it was built and published from. When the `provenance-file` config is set, it takes precedence and automatic provenance generation (including via trusted publishing/OIDC) is skipped. |
### `npm stage list`
diff --git a/deps/npm/docs/content/commands/npm-star.md b/deps/npm/docs/content/commands/npm-star.md
deleted file mode 100644
index 2820d1ca2e2..00000000000
--- a/deps/npm/docs/content/commands/npm-star.md
+++ /dev/null
@@ -1,79 +0,0 @@
----
-title: npm-star
-section: 1
-description: Mark your favorite packages
----
-
-### Synopsis
-
-```bash
-npm star [<package-spec>...]
-```
-
-Note: This command is unaware of workspaces.
-
-### Description
-
-"Starring" a package means that you have some interest in it.
-It's a vaguely positive way to show that you care.
-
-It's a boolean thing.
-Starring repeatedly has no additional effect.
-
-### More
-
-There's also these extra commands to help you manage your favorite packages:
-
-#### Unstar
-
-You can also "unstar" a package using [`npm unstar`](/commands/npm-unstar)
-
-"Unstarring" is the same thing, but in reverse.
-
-#### Listing stars
-
-You can see all your starred packages using [`npm stars`](/commands/npm-stars)
-
-### Configuration
-
-#### `registry`
-
-* Default: "https://registry.npmjs.org/"
-* Type: URL
-
-The base URL of the npm registry.
-
-
-
-#### `unicode`
-
-* Default: false on windows, true on mac/unix systems with a unicode locale,
- as defined by the `LC_ALL`, `LC_CTYPE`, or `LANG` environment variables.
-* Type: Boolean
-
-When set to true, npm uses unicode characters in the tree output. When
-false, it uses ascii characters instead of unicode glyphs.
-
-
-
-#### `otp`
-
-* Default: null
-* Type: null or String
-
-This is a one-time password from a two-factor authenticator. It's needed
-when publishing or changing package permissions with `npm access`.
-
-If not set, and a registry response fails with a challenge for a one-time
-password, npm will prompt on the command line for one.
-
-
-
-### See Also
-
-* [package spec](/using-npm/package-spec)
-* [npm unstar](/commands/npm-unstar)
-* [npm stars](/commands/npm-stars)
-* [npm view](/commands/npm-view)
-* [npm whoami](/commands/npm-whoami)
-* [npm adduser](/commands/npm-adduser)
diff --git a/deps/npm/docs/content/commands/npm-stars.md b/deps/npm/docs/content/commands/npm-stars.md
deleted file mode 100644
index f49883a7a2c..00000000000
--- a/deps/npm/docs/content/commands/npm-stars.md
+++ /dev/null
@@ -1,38 +0,0 @@
----
-title: npm-stars
-section: 1
-description: View packages marked as favorites
----
-
-### Synopsis
-
-```bash
-npm stars [<user>]
-```
-
-Note: This command is unaware of workspaces.
-
-### Description
-
-If you have starred a lot of neat things and want to find them again quickly this command lets you do just that.
-
-You may also want to see your friend's favorite packages, in this case you will most certainly enjoy this command.
-
-### Configuration
-
-#### `registry`
-
-* Default: "https://registry.npmjs.org/"
-* Type: URL
-
-The base URL of the npm registry.
-
-
-
-### See Also
-
-* [npm star](/commands/npm-star)
-* [npm unstar](/commands/npm-unstar)
-* [npm view](/commands/npm-view)
-* [npm whoami](/commands/npm-whoami)
-* [npm adduser](/commands/npm-adduser)
diff --git a/deps/npm/docs/content/commands/npm-start.md b/deps/npm/docs/content/commands/npm-start.md
index eb5d5c54684..b2ae9145614 100644
--- a/deps/npm/docs/content/commands/npm-start.md
+++ b/deps/npm/docs/content/commands/npm-start.md
@@ -55,6 +55,9 @@ Note that commands explicitly intended to run a particular script, such as
run their intended script if `ignore-scripts` is set, but they will *not*
run any pre- or post-scripts.
+Setting `ignore-scripts` also disables `.npm-extension` execution, as if
+`ignore-extension` were set.
+
#### `script-shell`
diff --git a/deps/npm/docs/content/commands/npm-stop.md b/deps/npm/docs/content/commands/npm-stop.md
index 2ccad18038e..0129ac599b0 100644
--- a/deps/npm/docs/content/commands/npm-stop.md
+++ b/deps/npm/docs/content/commands/npm-stop.md
@@ -50,6 +50,9 @@ Note that commands explicitly intended to run a particular script, such as
run their intended script if `ignore-scripts` is set, but they will *not*
run any pre- or post-scripts.
+Setting `ignore-scripts` also disables `.npm-extension` execution, as if
+`ignore-extension` were set.
+
#### `script-shell`
diff --git a/deps/npm/docs/content/commands/npm-test.md b/deps/npm/docs/content/commands/npm-test.md
index f145dc8958b..dd303d23bb7 100644
--- a/deps/npm/docs/content/commands/npm-test.md
+++ b/deps/npm/docs/content/commands/npm-test.md
@@ -48,6 +48,9 @@ Note that commands explicitly intended to run a particular script, such as
run their intended script if `ignore-scripts` is set, but they will *not*
run any pre- or post-scripts.
+Setting `ignore-scripts` also disables `.npm-extension` execution, as if
+`ignore-extension` were set.
+
#### `script-shell`
diff --git a/deps/npm/docs/content/commands/npm-token.md b/deps/npm/docs/content/commands/npm-token.md
index 3c8e08d7fc3..d80bd7944b3 100644
--- a/deps/npm/docs/content/commands/npm-token.md
+++ b/deps/npm/docs/content/commands/npm-token.md
@@ -110,11 +110,14 @@ the token access to specific organizations.
#### `packages-and-scopes-permission`
* Default: null
-* Type: null, "read-only", "read-write", or "no-access"
+* Type: null, "read-only", "read-write", "read-write-stage-only", or
+ "no-access"
When creating a Granular Access Token with `npm token create`, sets the
permission level for packages and scopes. Options are "read-only",
-"read-write", or "no-access".
+"read-write", "read-write-stage-only", or "no-access".
+"read-write-stage-only" grants publish access that stages releases instead
+of publishing them directly.
@@ -194,7 +197,7 @@ access tokens with the `npm token create` command.
### See Also
-* [npm adduser](/commands/npm-adduser)
+* [npm login](/commands/npm-login)
* [npm registry](/using-npm/registry)
* [npm config](/commands/npm-config)
* [npmrc](/configuring-npm/npmrc)
diff --git a/deps/npm/docs/content/commands/npm-uninstall.md b/deps/npm/docs/content/commands/npm-uninstall.md
index 43b706f9c94..73b901dcee4 100644
--- a/deps/npm/docs/content/commands/npm-uninstall.md
+++ b/deps/npm/docs/content/commands/npm-uninstall.md
@@ -19,11 +19,11 @@ This uninstalls a package, completely removing everything npm installed on its b
It also removes the package from the `dependencies`, `devDependencies`,
`optionalDependencies`, and `peerDependencies` objects in your `package.json`.
-Further, if you have an `npm-shrinkwrap.json` or `package-lock.json`, npm will update those files as well.
+Further, if you have a `package-lock.json`, npm will update that file as well.
-`--no-save` will tell npm not to remove the package from your `package.json`, `npm-shrinkwrap.json`, or `package-lock.json` files.
+`--no-save` will tell npm not to remove the package from your `package.json` or `package-lock.json` files.
-`--save` or `-S` will tell npm to remove the package from your `package.json`, `npm-shrinkwrap.json`, and `package-lock.json` files.
+`--save` or `-S` will tell npm to remove the package from your `package.json` and `package-lock.json` files.
This is the default, but you may need to use this if you have for instance `save=false` in your `npmrc` file
In global mode (ie, with `-g` or `--global` appended to the command), it uninstalls the current package context as a global package.
@@ -37,14 +37,14 @@ Scope is optional and follows the usual rules for [`scope`](/using-npm/scope).
npm uninstall sax
```
-`sax` will no longer be in your `package.json`, `npm-shrinkwrap.json`, or `package-lock.json` files.
+`sax` will no longer be in your `package.json` or `package-lock.json` files.
```bash
npm uninstall lodash --no-save
```
-`lodash` will not be removed from your `package.json`,
-`npm-shrinkwrap.json`, or `package-lock.json` files.
+`lodash` will not be removed from your `package.json` or
+`package-lock.json` files.
### Configuration
diff --git a/deps/npm/docs/content/commands/npm-unpublish.md b/deps/npm/docs/content/commands/npm-unpublish.md
index fe2d9be0f4a..c2d6ff7848c 100644
--- a/deps/npm/docs/content/commands/npm-unpublish.md
+++ b/deps/npm/docs/content/commands/npm-unpublish.md
@@ -20,7 +20,7 @@ Consider using the [`deprecate`](/commands/npm-deprecate) command instead, if yo
This removes a package version from the registry, deleting its entry and removing the tarball.
-The npm registry will return an error if you are not [logged in](/commands/npm-adduser).
+The npm registry will return an error if you are not [logged in](/commands/npm-login).
If you do not specify a package name at all, the name and version to be unpublished will be pulled from the project in the current directory.
@@ -121,6 +121,5 @@ This value is not exported to the environment for child processes.
* [npm deprecate](/commands/npm-deprecate)
* [npm publish](/commands/npm-publish)
* [npm registry](/using-npm/registry)
-* [npm adduser](/commands/npm-adduser)
* [npm owner](/commands/npm-owner)
-* [npm login](/commands/npm-adduser)
+* [npm login](/commands/npm-login)
diff --git a/deps/npm/docs/content/commands/npm-unstar.md b/deps/npm/docs/content/commands/npm-unstar.md
deleted file mode 100644
index 24764733e4a..00000000000
--- a/deps/npm/docs/content/commands/npm-unstar.md
+++ /dev/null
@@ -1,73 +0,0 @@
----
-title: npm-unstar
-section: 1
-description: Remove an item from your favorite packages
----
-
-### Synopsis
-
-```bash
-npm unstar [<package-spec>...]
-```
-
-Note: This command is unaware of workspaces.
-
-### Description
-
-"Unstarring" a package is the opposite of [`npm star`](/commands/npm-star), it removes an item from your list of favorite packages.
-
-### More
-
-There's also these extra commands to help you manage your favorite packages:
-
-#### Star
-
-You can "star" a package using [`npm star`](/commands/npm-star)
-
-#### Listing stars
-
-You can see all your starred packages using [`npm stars`](/commands/npm-stars)
-
-### Configuration
-
-#### `registry`
-
-* Default: "https://registry.npmjs.org/"
-* Type: URL
-
-The base URL of the npm registry.
-
-
-
-#### `unicode`
-
-* Default: false on windows, true on mac/unix systems with a unicode locale,
- as defined by the `LC_ALL`, `LC_CTYPE`, or `LANG` environment variables.
-* Type: Boolean
-
-When set to true, npm uses unicode characters in the tree output. When
-false, it uses ascii characters instead of unicode glyphs.
-
-
-
-#### `otp`
-
-* Default: null
-* Type: null or String
-
-This is a one-time password from a two-factor authenticator. It's needed
-when publishing or changing package permissions with `npm access`.
-
-If not set, and a registry response fails with a challenge for a one-time
-password, npm will prompt on the command line for one.
-
-
-
-### See Also
-
-* [npm star](/commands/npm-star)
-* [npm stars](/commands/npm-stars)
-* [npm view](/commands/npm-view)
-* [npm whoami](/commands/npm-whoami)
-* [npm adduser](/commands/npm-adduser)
-
diff --git a/deps/npm/docs/content/commands/npm-update.md b/deps/npm/docs/content/commands/npm-update.md
index 317f85f7d0d..1dd224318f9 100644
--- a/deps/npm/docs/content/commands/npm-update.md
+++ b/deps/npm/docs/content/commands/npm-update.md
@@ -225,8 +225,7 @@ on deeper dependencies. Sets `--install-strategy=shallow`.
Dependency types to omit from the installation tree on disk.
Note that these dependencies _are_ still resolved and added to the
-`package-lock.json` or `npm-shrinkwrap.json` file. They are just not
-physically installed on disk.
+`package-lock.json` file. They are just not physically installed on disk.
If a package type appears in both the `--include` and `--omit` lists, then
it will be included.
@@ -308,6 +307,9 @@ Note that commands explicitly intended to run a particular script, such as
run their intended script if `ignore-scripts` is set, but they will *not*
run any pre- or post-scripts.
+Setting `ignore-scripts` also disables `.npm-extension` execution, as if
+`ignore-extension` were set.
+
#### `allow-scripts`
@@ -330,7 +332,7 @@ Each name is matched against a dependency's resolved identity, not against
the package's self-reported name. `--ignore-scripts` and
`--dangerously-allow-all-scripts` both override this setting.
-
+This value is not exported to the environment for child processes.
#### `strict-allow-scripts`
@@ -338,11 +340,12 @@ the package's self-reported name. `--ignore-scripts` and
* Type: Boolean
If `true`, turn the install-script policy from a warning into a hard error:
-any dependency with install scripts not covered by `allowScripts` will fail
-the install instead of running with a notice.
+any dependency with install scripts that is not covered by `allowScripts`
+will fail the install instead of being blocked with a warning.
Dependencies explicitly denied with `false` in `allowScripts` are always
-silently skipped; this setting only affects unreviewed entries.
+silently skipped; this setting only affects unreviewed entries (packages
+with install scripts that are neither approved nor denied).
`--ignore-scripts` and `--dangerously-allow-all-scripts` both override this
setting.
@@ -570,7 +573,6 @@ workspaces.
* [npm install](/commands/npm-install)
* [npm outdated](/commands/npm-outdated)
-* [npm shrinkwrap](/commands/npm-shrinkwrap)
* [npm registry](/using-npm/registry)
* [npm folders](/configuring-npm/folders)
* [npm ls](/commands/npm-ls)
diff --git a/deps/npm/docs/content/commands/npm-version.md b/deps/npm/docs/content/commands/npm-version.md
index 9016c8071f7..1aba89200b4 100644
--- a/deps/npm/docs/content/commands/npm-version.md
+++ b/deps/npm/docs/content/commands/npm-version.md
@@ -169,12 +169,14 @@ Note that commands explicitly intended to run a particular script, such as
run their intended script if `ignore-scripts` is set, but they will *not*
run any pre- or post-scripts.
+Setting `ignore-scripts` also disables `.npm-extension` execution, as if
+`ignore-extension` were set.
+
### Description
-Run this in a package directory to bump the version and write the new data back to `package.json`, `package-lock.json`, and, if present,
-`npm-shrinkwrap.json`.
+Run this in a package directory to bump the version and write the new data back to `package.json` and `package-lock.json`.
The `newversion` argument should be a valid semver string, a valid second argument to [semver.inc](https://github.com/npm/node-semver#functions) (one of `patch`, `minor`, `major`, `prepatch`, `preminor`, `premajor`, `prerelease`), or `from-git`.
In the second case, the existing version will be incremented by 1 in the specified field.
diff --git a/deps/npm/docs/content/commands/npm-view.md b/deps/npm/docs/content/commands/npm-view.md
index 3b4fa50976d..7172e9a5194 100644
--- a/deps/npm/docs/content/commands/npm-view.md
+++ b/deps/npm/docs/content/commands/npm-view.md
@@ -243,6 +243,9 @@ If only a single string field for a single version is output, then it will not b
If the field is an object, it will be output as a JavaScript object literal.
If the `--json` flag is given, the outputted fields will be JSON.
+Scalar and object results are returned in an array, even if only a single version matches.
+When the output contains one array-valued result, that array is returned directly without an additional result wrapper.
+Multiple array-valued results remain separate items in the outer results array.
If the version range matches multiple versions then each printed value will be prefixed with the version it applies to.
diff --git a/deps/npm/docs/content/commands/npm-whoami.md b/deps/npm/docs/content/commands/npm-whoami.md
index fb09864050f..001b417d33d 100644
--- a/deps/npm/docs/content/commands/npm-whoami.md
+++ b/deps/npm/docs/content/commands/npm-whoami.md
@@ -35,4 +35,4 @@ The base URL of the npm registry.
* [npm config](/commands/npm-config)
* [npmrc](/configuring-npm/npmrc)
-* [npm adduser](/commands/npm-adduser)
+* [npm login](/commands/npm-login)
diff --git a/deps/npm/docs/content/commands/npm.md b/deps/npm/docs/content/commands/npm.md
index 75157bd7b59..e67492993a0 100644
--- a/deps/npm/docs/content/commands/npm.md
+++ b/deps/npm/docs/content/commands/npm.md
@@ -14,7 +14,7 @@ Note: This command is unaware of workspaces.
### Version
-11.19.1
+12.1.0
### Description
@@ -82,8 +82,8 @@ If you're using npm to develop and publish your code, check out the following he
* install:
It's a good idea to install things if you don't need the symbolic link.
Especially, installing other peoples code from the registry is done via [`npm install`](/commands/npm-install)
-* adduser:
- Create an account or log in.
+* login:
+ Log in to the registry and store credentials.
When you do this, npm will store credentials in the user config file.
* publish:
Use the [`npm publish`](/commands/npm-publish) command to upload your code to the registry.
diff --git a/deps/npm/docs/content/configuring-npm/npm-extension.md b/deps/npm/docs/content/configuring-npm/npm-extension.md
new file mode 100644
index 00000000000..80ae3d90d7b
--- /dev/null
+++ b/deps/npm/docs/content/configuring-npm/npm-extension.md
@@ -0,0 +1,90 @@
+---
+title: .npm-extension
+section: 5
+description: Imperative, root-owned manifest repairs
+---
+
+### Description
+
+A root-owned `.npm-extension.mjs` or `.npm-extension.cjs` file lets a project imperatively repair the manifests of third-party dependencies before npm resolves the dependency tree. It exports a `transformManifest(pkg, context)` function that receives a candidate dependency manifest and returns the effective manifest npm should use.
+
+`.npm-extension` is the imperative counterpart to the declarative [`packageExtensions`](/configuring-npm/package-json#packageextensions) field, and runs in the same pre-resolution phase, **before** `packageExtensions`. Prefer `packageExtensions` for simple, data-only repairs; reach for `.npm-extension` when you need comments and links explaining a repair, conditional logic, repeated repairs expressed as code, deletion or range rewrites, stale-repair guards, or a policy location outside `package.json`.
+
+### Example
+
+```js
+// .npm-extension.mjs
+export function transformManifest (pkg, context) {
+ if (pkg.name === 'foo' && pkg.version.startsWith('1.')) {
+ pkg.dependencies = { ...pkg.dependencies, bar: '^2.0.0' }
+ context.log(`added bar to ${pkg.name}@${pkg.version}`)
+ }
+ return pkg
+}
+```
+
+The `.cjs` form uses CommonJS exports instead:
+
+```js
+// .npm-extension.cjs
+module.exports = {
+ transformManifest (pkg, context) {
+ return pkg
+ },
+}
+```
+
+### The `transformManifest` function
+
+`transformManifest(pkg, context)` receives a deeply isolated copy of a candidate dependency manifest. It may mutate and return that copy, or return a new manifest object. It **must** return a manifest object synchronously; returning `null`, `undefined`, a primitive, an array, or a promise fails the install.
+
+The `context` argument is intentionally small:
+
+* `context.log(message)` writes an npm debug log message.
+* `context.root` is the absolute path to the project root.
+* `context.extensionPoint` is the string `"transformManifest"`.
+
+npm provides no registry, fetch, lockfile, or extraction helpers. Keep the extension file self-contained or limited to Node builtins; npm does not guarantee that project dependencies are available when the file is loaded.
+
+### Supported mutations
+
+Only the four resolution-affecting fields may change:
+
+* `dependencies`
+* `optionalDependencies`
+* `peerDependencies`
+* `peerDependenciesMeta`
+
+Within those fields you may add, replace, or delete entries. Changing any other field (such as `scripts`, `bin`, `engines`, `os`, `cpu`, `exports`, or `main`) is rejected, and the install fails with an error naming `.npm-extension` and the package being processed. The package tarball and the installed `node_modules/<pkg>/package.json` are never rewritten.
+
+### Discovery and `extension-file`
+
+npm looks for a single `.npm-extension.mjs` or `.npm-extension.cjs` at the project root (the workspace root in a workspace project). Having both files present is an error. A `.npm-extension` file in a dependency or in a non-root workspace is ignored; a non-root workspace file produces a warning.
+
+The [`extension-file`](/using-npm/config#extension-file) config selects a different project-local file. It must resolve inside the project root and use a `.mjs` or `.cjs` extension, and it is honored only from project config or the command line — never from user, global, or builtin config.
+
+### Interaction with `packageExtensions` and `overrides`
+
+When both are present, `transformManifest` runs first and `packageExtensions` is applied to its output. Avoid targeting the same package with both unless you intend to rely on that ordering. `overrides` still controls the final resolution target of any edge, including edges created by `transformManifest`.
+
+### Lockfile and `npm ci`
+
+A lockfile influenced by `.npm-extension` records an `npmExtensionHash` (a digest of the selected file's bytes and module format) on its root entry, and minimal `npmExtensionApplied` provenance on each affected package entry. Extension state requires `lockfileVersion: 4`.
+
+Changing the file's contents makes `npm install` re-resolve the affected packages. `npm ci` does **not** import or execute `.npm-extension`; it verifies the recorded hash against the file and reifies the locked graph, failing if the file and lockfile disagree (or if one has extension state and the other does not).
+
+The hash proves only that the install uses the same extension file bytes that generated the lockfile. It does not make arbitrary JavaScript deterministic: extension output that depends on environment variables, the network, the clock, or files imported by the extension can still produce non-reproducible installs. Treat `.npm-extension` as trusted, deterministic project code, and only enable it in repositories you trust.
+
+### Disabling
+
+Set [`ignore-extension`](/using-npm/config#ignore-extension) to skip importing and executing `.npm-extension`. [`ignore-scripts`](/using-npm/config#ignore-scripts) implies `ignore-extension`, since both disable root-owned install-time code. `npm ci` still verifies the file hash even when execution is disabled.
+
+### Publishing
+
+`.npm-extension.mjs` and `.npm-extension.cjs` are project configuration, not package contents. npm excludes the root file from the package tarball produced by `npm pack` and `npm publish`, even when the package's `files` list would include it, so a public package can keep `.npm-extension` in its repository for local use without publishing it.
+
+### See also
+
+* [package.json `packageExtensions`](/configuring-npm/package-json#packageextensions)
+* [package-lock.json](/configuring-npm/package-lock-json)
+* [config](/using-npm/config)
diff --git a/deps/npm/docs/content/configuring-npm/npm-shrinkwrap-json.md b/deps/npm/docs/content/configuring-npm/npm-shrinkwrap-json.md
deleted file mode 100644
index 4ea5e4dc20b..00000000000
--- a/deps/npm/docs/content/configuring-npm/npm-shrinkwrap-json.md
+++ /dev/null
@@ -1,25 +0,0 @@
----
-title: npm-shrinkwrap.json
-section: 5
-description: A publishable lockfile
----
-
-### Description
-
-`npm-shrinkwrap.json` is a file created by [`npm shrinkwrap`](/commands/npm-shrinkwrap).
-It is identical to `package-lock.json`, with one major caveat: Unlike `package-lock.json`,
-`npm-shrinkwrap.json` may be included when publishing a package.
-
-The recommended use-case for `npm-shrinkwrap.json` is applications deployed through the publishing process on the registry: for example, daemons and command-line tools intended as global installs or `devDependencies`.
-It's strongly discouraged for library authors to publish this file, since that would prevent end users from having control over transitive dependency updates.
-
-If both `package-lock.json` and `npm-shrinkwrap.json` are present in a package root, `npm-shrinkwrap.json` will be preferred over the `package-lock.json` file.
-
-For full details and description of the `npm-shrinkwrap.json` file format, refer to the manual page for [package-lock.json](/configuring-npm/package-lock-json).
-
-### See also
-
-* [npm shrinkwrap](/commands/npm-shrinkwrap)
-* [package-lock.json](/configuring-npm/package-lock-json)
-* [package.json](/configuring-npm/package-json)
-* [npm install](/commands/npm-install)
diff --git a/deps/npm/docs/content/configuring-npm/package-json.md b/deps/npm/docs/content/configuring-npm/package-json.md
index 12b87cb7a84..917c9a38eb0 100644
--- a/deps/npm/docs/content/configuring-npm/package-json.md
+++ b/deps/npm/docs/content/configuring-npm/package-json.md
@@ -301,7 +301,7 @@ Some files are always ignored by default:
* `config.gypi`
* `node_modules`
* `npm-debug.log`
-* `package-lock.json` (use [`npm-shrinkwrap.json`](/configuring-npm/npm-shrinkwrap-json) if you wish it to be published)
+* `package-lock.json`
* `pnpm-lock.yaml`
* `yarn.lock`
* `bun.lockb`
@@ -399,9 +399,11 @@ See [folders](/configuring-npm/folders#executables) for more info on executables
### man
-Specify either a single file or an array of filenames to put in place for the `man` program to find.
+> **Note:** As of npm v12, man pages are no longer registered with the system `man` program. This field is retained for backward compatibility with package metadata and tools that consume it, but `man <pkgname>` will not work after a global install. Use `npm help <pkgname>` instead where supported.
+
+Specify either a single file or an array of filenames to include as man pages.
-If only a single file is provided, then it's installed such that it is the result from `man <pkgname>`, regardless of its actual filename.
+If only a single file is provided, then it corresponds to `man <pkgname>`, regardless of its actual filename.
For example:
```json
@@ -414,7 +416,7 @@ For example:
}
```
-would link the `./man/doc.1` file in such that it is the target for `man foo`
+would associate the `./man/doc.1` file such that it is the target for `man foo`
If the filename doesn't start with the package name, then it's prefixed.
So, this:
@@ -432,10 +434,10 @@ So, this:
}
```
-will create files to do `man foo` and `man foo-bar`.
+will correspond to `man foo` and `man foo-bar`.
Man files must end with a number, and optionally a `.gz` suffix if they are compressed.
-The number dictates which man section the file is installed into.
+The number dictates which man section the file belongs to.
```json
{
@@ -469,7 +471,7 @@ If you want to specify individual files, use `bin`, and for all the files in an
#### directories.man
A folder that is full of man pages.
-Sugar to generate a "man" array by walking the folder.
+Sugar to generate a "man" array by walking the folder. See the note on [`man`](#man) above: as of npm v12, these are no longer installed into the system `man` path.
### repository
@@ -840,6 +842,16 @@ This is a map of package name to version or URL, just like the `dependencies` ob
The difference is that build failures do not cause installation to fail.
Running `npm install --omit=optional` will prevent these dependencies from being installed.
+For example:
+
+```json
+{
+ "optionalDependencies": {
+ "@npm/foo": "^1.0.0"
+ }
+}
+```
+
It is still your program's responsibility to handle the lack of the dependency.
For example, something like this:
@@ -872,7 +884,7 @@ These changes can be scoped as specific or as vague as desired.
Overrides are only considered in the root `package.json` file for a project.
Overrides in installed dependencies (including [workspaces](/using-npm/workspaces)) are not considered in dependency tree resolution.
-Published packages may dictate their resolutions by pinning dependencies or using an [`npm-shrinkwrap.json`](/configuring-npm/npm-shrinkwrap-json) file.
+Published packages may dictate their resolutions by pinning dependencies or using [`bundleDependencies`](#bundledependencies).
To make sure the package `@npm/foo` is always installed as version `1.0.0` no matter what version your dependencies rely on:
@@ -1021,6 +1033,66 @@ For example, to replace a transitive dependency with a fork:
}
```
+### packageExtensions
+
+`packageExtensions` lets a project apply small, declarative repairs to the manifests of third-party dependencies before npm resolves the dependency tree.
+Use it to add a missing `dependencies`, `optionalDependencies`, or `peerDependencies` entry, or to correct `peerDependencies` and `peerDependenciesMeta`, while you wait for the upstream package to publish a fix.
+
+This is especially useful with [`install-strategy=linked`](/using-npm/config#install-strategy), where dependencies are fully isolated and a package only sees what it actually declared.
+A package that worked under a hoisted layout because a dependency happened to be hoisted above it can fail under `linked`; `packageExtensions` records the missing edge as explicit, reviewable, root-owned policy.
+
+`packageExtensions` complements [`overrides`](#overrides): `overrides` changes what an existing dependency edge resolves to, while `packageExtensions` adds or corrects the dependency metadata that creates the edge in the first place.
+For changing the resolved version of a dependency that is already declared, use `overrides`.
+
+Like `overrides`, `packageExtensions` is only honored in the root `package.json` of a project (the workspace root in a workspace).
+The field in installed dependencies and in non-root workspace packages is ignored.
+Because it is root-only project policy, npm refuses to publish a non-private package that contains `packageExtensions`; it remains available to private packages and unpublished local projects.
+
+Each key is a package selector: a package name with an optional semver range.
+
+```json
+{
+ "packageExtensions": {
+ "broken-package@1": {
+ "dependencies": {
+ "missing-runtime-dep": "^2.0.0"
+ }
+ },
+ "typescript-plugin@4.3.0": {
+ "peerDependencies": {
+ "typescript": ">=5"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "@scope/uses-types@2": {
+ "dependencies": {
+ "@types/node": "^22.0.0"
+ }
+ }
+ }
+}
+```
+
+- `"foo"` matches all versions of `foo`.
+- `"foo@1"` matches versions satisfying `1`.
+- `"@scope/foo@^2.3.0"` matches versions satisfying `^2.3.0`.
+
+Selectors match a candidate package's own `name` and `version`. They do not accept dist-tags, git, file, directory, URL, or `npm:` alias specs. For aliases, the selector matches the underlying package name. At most one selector may match a given package; overlapping selectors that both match the same package fail the install.
+
+Only `dependencies`, `optionalDependencies`, `peerDependencies`, and `peerDependenciesMeta` may be extended. The merge rules are:
+
+- `dependencies` and `optionalDependencies` entries add a missing dependency only. Adding a name that the package already declares in either field is an error; use `overrides` to change a version.
+- `peerDependencies` entries are merged by name, replacing an existing range.
+- `peerDependenciesMeta` entries are merged by name and then by key, so you can add `optional: true` without dropping other metadata. Every `peerDependenciesMeta` entry must correspond to a `peerDependencies` entry.
+
+Deletion is not supported; a `null`, `false`, or `"-"` value is an error.
+
+`packageExtensions` does not rewrite the installed package's `package.json` on disk and does not modify `bundleDependencies`. Affected packages are recorded in `package-lock.json` and surfaced by [`npm explain`](/commands/npm-explain) and [`npm ls`](/commands/npm-ls), so each repair is easy to audit and to remove once upstream is fixed.
+
### engines
You can specify the version of node that your stuff works on:
diff --git a/deps/npm/docs/content/configuring-npm/package-lock-json.md b/deps/npm/docs/content/configuring-npm/package-lock-json.md
index 4d81156bd9c..227c6449e39 100644
--- a/deps/npm/docs/content/configuring-npm/package-lock-json.md
+++ b/deps/npm/docs/content/configuring-npm/package-lock-json.md
@@ -23,16 +23,16 @@ This file is intended to be committed into source repositories, and serves vario
When `npm` creates or updates `package-lock.json`, it will infer line endings and indentation from `package.json` so that the formatting of both files matches.
-### `package-lock.json` vs `npm-shrinkwrap.json`
+### `npm-shrinkwrap.json`
-Both of these files have the same format, and perform similar functions in the root of a project.
-
-The difference is that `package-lock.json` cannot be published, and it will be ignored if found in any place other than the root project.
-
-In contrast, [npm-shrinkwrap.json](/configuring-npm/npm-shrinkwrap-json) allows publication, and defines the dependency tree from the point encountered.
-This is not recommended unless deploying a CLI tool or otherwise using the publication process for producing production packages.
-
-If both `package-lock.json` and `npm-shrinkwrap.json` are present in the root of a project, `npm-shrinkwrap.json` will take precedence and `package-lock.json` will be ignored.
+As of npm v12, `npm-shrinkwrap.json` is no longer read or written by
+npm. Projects that previously committed `npm-shrinkwrap.json` should
+rename it to `package-lock.json`; the file format is identical. When
+npm v12 encounters a dependency that ships an `npm-shrinkwrap.json`
+inside its tarball, the file is ignored — publishers who need to ship
+a locked tree should use
+[`bundleDependencies`](/configuring-npm/package-json#bundledependencies)
+instead.
### Hidden Lockfiles
@@ -76,7 +76,7 @@ An integer version, starting at `1` with the version number of this document who
Note that the file format changed significantly in npm v7 to track information that would have otherwise required looking in `node_modules` or the npm registry.
Lockfiles generated by npm v7 will contain `lockfileVersion: 2`.
-* No version provided: an "ancient" shrinkwrap file from a version of npm prior to npm v5.
+* No version provided: an "ancient" lockfile from a version of npm prior to npm v5.
* `1`: The lockfile version used by npm v5 and v6.
* `2`: The lockfile version used by npm v7 and v8. Backwards compatible to v1 lockfiles.
* `3`: The lockfile version used by npm v9 and above.
@@ -115,8 +115,6 @@ Package descriptors have the following fields:
* hasInstallScript: A flag to indicate that the package has a `preinstall`, `install`, or `postinstall` script.
-* hasShrinkwrap: A flag to indicate that the package has an `npm-shrinkwrap.json` file.
-
* bin, license, engines, dependencies, optionalDependencies: fields from `package.json`
* os: An array of operating systems this package is compatible with, as specified in `package.json`. This field is included when the package specifies OS restrictions.
@@ -176,7 +174,5 @@ Dependency objects have the following fields:
### See also
-* [npm shrinkwrap](/commands/npm-shrinkwrap)
-* [npm-shrinkwrap.json](/configuring-npm/npm-shrinkwrap-json)
* [package.json](/configuring-npm/package-json)
* [npm install](/commands/npm-install)
diff --git a/deps/npm/docs/content/using-npm/config.md b/deps/npm/docs/content/using-npm/config.md
index 5d951493e8a..8d8d0af983d 100644
--- a/deps/npm/docs/content/using-npm/config.md
+++ b/deps/npm/docs/content/using-npm/config.md
@@ -206,7 +206,7 @@ dependencies to be used for other commands like `npm view`
#### `allow-git`
-* Default: "all"
+* Default: "none"
* Type: "all", "none", or "root"
Limits the ability for npm to fetch dependencies from git references. That
@@ -215,6 +215,11 @@ range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.
+As of npm 12 the default is `none`. Git dependencies run `git` against a
+remote repo and may install configuration the project does not control. Opt
+in explicitly per project (in `.npmrc`) or per command (on the CLI) when you
+need git deps.
+
`all` allows any git dependencies to be fetched and installed. `none`
prevents any git dependencies from being fetched and installed. `root` only
allows git dependencies defined in your project's package.json to be fetched
@@ -225,7 +230,7 @@ like `npm view`
#### `allow-remote`
-* Default: "all"
+* Default: "none"
* Type: "all", "none", or "root"
Limits the ability for npm to fetch dependencies from urls. That is,
@@ -234,6 +239,13 @@ range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.
+As of npm 12 the default is `none`. Tarballs that share a hostname with the
+configured registry (the typical case for the npm registry, GitHub Packages,
+and most private registries) are still installed normally. If your registry
+serves tarballs from a different host, set `replace-registry-host` or
+override this setting. Opt in explicitly per project (in `.npmrc`) or per
+command (on the CLI) when you intentionally install from a URL.
+
`all` allows any url to be installed. `none` prevents any url from being
installed. `root` only allows urls defined in your project's package.json to
be installed. Also allows url dependencies to be used for other commands
@@ -271,7 +283,7 @@ Each name is matched against a dependency's resolved identity, not against
the package's self-reported name. `--ignore-scripts` and
`--dangerously-allow-all-scripts` both override this setting.
-
+This value is not exported to the environment for child processes.
#### `allow-scripts-pending`
@@ -296,6 +308,19 @@ setting.
+#### `allow-unused-patches`
+
+* Default: false
+* Type: Boolean
+
+Install even when a registered patch in `patchedDependencies` matches no
+installed package. Does not silence patch apply failures.
+
+This flag is only honored when passed on the command line; it is ignored in
+`.npmrc` and environment variables, and rejected by `npm ci`.
+
+
+
#### `audit`
* Default: true
@@ -621,6 +646,16 @@ Note: This is NOT honored by other network related commands, eg `dist-tags`,
+#### `edit-dir`
+
+* Default: null
+* Type: null or Path
+
+Override the temporary directory used by `npm patch add` to prepare a
+package for editing.
+
+
+
#### `editor`
* Default: The EDITOR or VISUAL environment variables, or
@@ -674,6 +709,19 @@ expiration.
+#### `extension-file`
+
+* Default: null
+* Type: null or Path
+
+Path to a project-local npm extension file to load instead of discovering
+`.npm-extension.mjs` / `.npm-extension.cjs` at the project root. Must
+resolve inside the project root and use a `.mjs` or `.cjs` extension. Only
+honored from project config or the command line, never from user, global, or
+builtin config.
+
+
+
#### `fetch-retries`
* Default: 2
@@ -773,8 +821,7 @@ but can be useful for debugging.
* Default: true
* Type: Boolean
-Format `package-lock.json` or `npm-shrinkwrap.json` as a human readable
-file.
+Format `package-lock.json` as a human readable file.
@@ -825,6 +872,25 @@ folder instead of the current working directory. See
+#### `global-ignore-file`
+
+* Default: The global --prefix setting plus 'etc/npmignore'. For example,
+ '/usr/local/etc/npmignore'
+* Type: Path
+
+An additional ignore file applied during `npm pack` and `npm publish`, owned
+by the current user rather than the package. Patterns follow the same syntax
+as a package's local `.npmignore` file. Useful for keeping editor metadata
+(such as `.idea/` or `*.iml`) and scratch directories out of every package
+you publish, without adding them to each package's own ignore rules.
+
+The global rules apply in addition to a package's local `.npmignore`. When a
+package uses a `files` field in its `package.json`, an entry in `files` that
+contradicts a global rule (i.e., explicitly includes a path the global rule
+would exclude) still wins.
+
+
+
#### `globalconfig`
* Default: The global --prefix setting plus 'etc/npmrc'. For example,
@@ -870,6 +936,41 @@ CI setup.
This value is not exported to the environment for child processes.
+#### `ignore-existing`
+
+* Default: false
+* Type: Boolean
+
+With `npm patch add`, discard a previous unfinished edit directory and start
+fresh.
+
+
+
+#### `ignore-extension`
+
+* Default: false
+* Type: Boolean
+
+If true, npm does not import or execute a root `.npm-extension.mjs` /
+`.npm-extension.cjs` file (or one selected via `extension-file`).
+`ignore-scripts` implies `ignore-extension`, since both disable root-owned
+install-time code.
+
+
+
+#### `ignore-patch-failures`
+
+* Default: false
+* Type: Boolean
+
+Install even when a registered patch fails to apply, with a warning per
+failure. Intended for incident response only.
+
+This flag is only honored when passed on the command line; it is ignored in
+`.npmrc` and environment variables, and rejected by `npm ci`.
+
+
+
#### `ignore-scripts`
* Default: false
@@ -882,6 +983,9 @@ Note that commands explicitly intended to run a particular script, such as
run their intended script if `ignore-scripts` is set, but they will *not*
run any pre- or post-scripts.
+Setting `ignore-scripts` also disables `.npm-extension` execution, as if
+`ignore-extension` were set.
+
#### `include`
@@ -965,10 +1069,11 @@ homepage.
#### `init-license`
-* Default: "ISC"
+* Default: ""
* Type: String
-The value `npm init` should use by default for the package license.
+The value `npm init` should use by default for the package license. If not
+set, the license field will be omitted from new packages.
@@ -1060,6 +1165,16 @@ Not supported by all npm commands.
+#### `keep-edit-dir`
+
+* Default: false
+* Type: Boolean
+
+With `npm patch commit`, do not remove the edit directory after committing
+the patch.
+
+
+
#### `legacy-peer-deps`
* Default: false
@@ -1134,8 +1249,8 @@ instead of the current working directory. See
otherwise, maintain current lockfile version.
* Type: null, 1, 2, 3, "1", "2", or "3"
-Set the lockfile format version to be used in package-lock.json and
-npm-shrinkwrap-json files. Possible options are:
+Set the lockfile format version to be used in package-lock.json files.
+Possible options are:
1: The lockfile version used by npm versions 5 and 6. Lacks some data that
is used during the install, resulting in slower and possibly less
@@ -1339,8 +1454,7 @@ allow the CLI to fill in missing cache data, see `--prefer-offline`.
Dependency types to omit from the installation tree on disk.
Note that these dependencies _are_ still resolved and added to the
-`package-lock.json` or `npm-shrinkwrap.json` file. They are just not
-physically installed on disk.
+`package-lock.json` file. They are just not physically installed on disk.
If a package type appears in both the `--include` and `--omit` lists, then
it will be included.
@@ -1473,11 +1587,14 @@ token access to all packages instead of limiting to specific packages.
#### `packages-and-scopes-permission`
* Default: null
-* Type: null, "read-only", "read-write", or "no-access"
+* Type: null, "read-only", "read-write", "read-write-stage-only", or
+ "no-access"
When creating a Granular Access Token with `npm token create`, sets the
permission level for packages and scopes. Options are "read-only",
-"read-write", or "no-access".
+"read-write", "read-write-stage-only", or "no-access".
+"read-write-stage-only" grants publish access that stages releases instead
+of publishing them directly.
@@ -1501,6 +1618,16 @@ tokens, though it's generally safer to be prompted for it.
+#### `patches-dir`
+
+* Default: "patches"
+* Type: String
+
+The directory, relative to the project root, where `npm patch commit` writes
+patch files for `patchedDependencies`.
+
+
+
#### `prefer-dedupe`
* Default: false
@@ -1575,6 +1702,9 @@ Set to `false` to suppress the progress bar.
When publishing from a supported cloud CI/CD system, the package will be
publicly linked to where it was built and published from.
+When the `provenance-file` config is set, it takes precedence and automatic
+provenance generation (including via trusted publishing/OIDC) is skipped.
+
This config cannot be used with: `provenance-file`
#### `provenance-file`
@@ -1584,6 +1714,9 @@ This config cannot be used with: `provenance-file`
When publishing, the provenance bundle at the given path will be used.
+This takes precedence over automatic provenance generation in trusted
+publishing flows.
+
This config cannot be used with: `provenance`
#### `proxy`
@@ -1894,11 +2027,12 @@ this to work properly.
* Type: Boolean
If `true`, turn the install-script policy from a warning into a hard error:
-any dependency with install scripts not covered by `allowScripts` will fail
-the install instead of running with a notice.
+any dependency with install scripts that is not covered by `allowScripts`
+will fail the install instead of being blocked with a warning.
Dependencies explicitly denied with `false` in `allowScripts` are always
-silently skipped; this setting only affects unreviewed entries.
+silently skipped; this setting only affects unreviewed entries (packages
+with install scripts that are neither approved nor denied).
`--ignore-scripts` and `--dangerously-allow-all-scripts` both override this
setting.
@@ -1908,6 +2042,19 @@ their install scripts never run.
+#### `strict-npmrc`
+
+* Default: false
+* Type: Boolean
+
+If set to `true`, unknown configuration keys found in `.npmrc` files are
+treated as a hard error instead of a warning.
+
+Unknown command line flags and abbreviated flags always error regardless of
+this setting.
+
+
+
#### `strict-peer-deps`
* Default: false
@@ -1991,6 +2138,17 @@ while still writing the timing file, use `--silent`.
+#### `to`
+
+* Default: null
+* Type: null or String
+
+Used by `npm patch update` to set the version to rebase a patch onto when it
+cannot be read from `package-lock.json` — for example an exact-version
+selector, or a version that has not been installed yet.
+
+
+
#### `token-description`
* Default: null
@@ -2296,7 +2454,7 @@ Alias for `--init-author-url`
#### `init.license`
-* Default: "ISC"
+* Default: ""
* Type: String
* DEPRECATED: Use `--init-license` instead.
@@ -2392,16 +2550,6 @@ Alias for `--omit=dev`
-#### `shrinkwrap`
-
-* Default: true
-* Type: Boolean
-* DEPRECATED: Use the --package-lock setting instead.
-
-Alias for --package-lock
-
-
-
### See also
* [npm config](/commands/npm-config)
diff --git a/deps/npm/docs/content/using-npm/developers.md b/deps/npm/docs/content/using-npm/developers.md
index b1fff0e3894..106930c32da 100644
--- a/deps/npm/docs/content/using-npm/developers.md
+++ b/deps/npm/docs/content/using-npm/developers.md
@@ -191,16 +191,7 @@ npm test
### Create a User Account
-Create a user with the adduser command.
-It works like this:
-
-```bash
-npm adduser
-```
-
-and then follow the prompts.
-
-This is documented better in [npm adduser](/commands/npm-adduser).
+Create a user account on the [npm website](https://www.npmjs.com/signup).
### Publish your Package
@@ -229,5 +220,5 @@ Tell the world how easy it is to install your program!
* [package.json](/configuring-npm/package-json)
* [npm scripts](/using-npm/scripts)
* [npm publish](/commands/npm-publish)
-* [npm adduser](/commands/npm-adduser)
+* [npm login](/commands/npm-login)
* [npm registry](/using-npm/registry)
diff --git a/deps/npm/docs/content/using-npm/registry.md b/deps/npm/docs/content/using-npm/registry.md
index 739f2a6a203..2af6edcd752 100644
--- a/deps/npm/docs/content/using-npm/registry.md
+++ b/deps/npm/docs/content/using-npm/registry.md
@@ -23,7 +23,7 @@ See [`npm config`](/commands/npm-config), [`npmrc`](/configuring-npm/npmrc), and
Authentication configuration such as auth tokens and certificates are configured specifically scoped to an individual registry.
See [Auth Related Configuration](/configuring-npm/npmrc#auth-related-configuration)
-When the default registry is used in a package-lock or shrinkwrap it has the special meaning of "the currently configured registry". If you create a lock file while using the default registry you can switch to another registry and npm will install packages from the new registry, but if you create a lock file while using a custom registry packages will be installed from that registry even after you change to another registry.
+When the default registry is used in a package-lock it has the special meaning of "the currently configured registry". If you create a lock file while using the default registry you can switch to another registry and npm will install packages from the new registry, but if you create a lock file while using a custom registry packages will be installed from that registry even after you change to another registry.
### Does npm send any information about me back to the registry?
diff --git a/deps/npm/docs/content/using-npm/scripts.md b/deps/npm/docs/content/using-npm/scripts.md
index dcae0c66da0..14e6fad9fae 100644
--- a/deps/npm/docs/content/using-npm/scripts.md
+++ b/deps/npm/docs/content/using-npm/scripts.md
@@ -111,7 +111,7 @@ It is run AFTER the changes have been applied and the `package.json` and `packag
#### [`npm ci`](/commands/npm-ci)
-* `preinstall`
+* `preinstall` (before dependencies are installed)
* `install`
* `postinstall`
* `prepublish`
@@ -119,8 +119,9 @@ It is run AFTER the changes have been applied and the `package.json` and `packag
* `prepare`
* `postprepare`
-These all run after the actual installation of modules into
- `node_modules`, in order, with no internal actions happening in between
+`preinstall` runs before any dependencies are fetched or unpacked into `node_modules`, so scripts can prepare the environment (for example, setting up authentication for a private registry) before tarballs are fetched. For `npm ci`, `preinstall` fires *after* the lockfile has been validated against `package.json`, so it cannot influence dependency resolution — that remains locked to `package-lock.json`. The remaining scripts run after the installation of modules into `node_modules`, in order, with no internal actions happening in between.
+
+Because `preinstall` runs before reify, scripts cannot rely on packages from `node_modules`. `npm ci` wipes `node_modules` before `preinstall` fires, so `require()` of a dependency will always fail. Use `install` or `postinstall` for setup that depends on installed packages.
#### [`npm diff`](/commands/npm-diff)
@@ -128,9 +129,9 @@ These all run after the actual installation of modules into
#### [`npm install`](/commands/npm-install)
-These also run when you run `npm install -g <pkg-name>`
+These run on a bare `npm install` in a local project (no package arguments).
-* `preinstall`
+* `preinstall` (before dependencies are installed)
* `install`
* `postinstall`
* `prepublish`
@@ -138,6 +139,10 @@ These also run when you run `npm install -g <pkg-name>`
* `prepare`
* `postprepare`
+`preinstall` runs before any dependencies are fetched or unpacked into `node_modules`, so scripts can prepare the environment (for example, setting up authentication for a private registry) before resolution begins. The remaining scripts run after installation has completed.
+
+Because `preinstall` runs before reify, scripts cannot rely on packages from `node_modules`. On a fresh checkout, `require()` of a dependency will fail. On a repeat `npm install` against an existing `node_modules/`, it may incidentally succeed because the previously-installed tree is still on disk, but the version available is whatever was previously installed and may be removed or replaced by the upcoming install. Use `install` or `postinstall` for setup that depends on installed packages.
+
If there is a `binding.gyp` file in the root of your package and you haven't defined your own `install` or `preinstall` scripts, npm will default the `install` command to compile using node-gyp via `node-gyp rebuild`
These are run from the scripts of `<pkg-name>`
diff --git a/deps/npm/docs/lib/index.js b/deps/npm/docs/lib/index.js
deleted file mode 100644
index 9779d546572..00000000000
--- a/deps/npm/docs/lib/index.js
+++ /dev/null
@@ -1,312 +0,0 @@
-const localeCompare = require('@isaacs/string-locale-compare')('en')
-const { join, basename, resolve } = require('path')
-const transformHTML = require('./transform-html.js')
-const { version } = require('../../lib/npm.js')
-const { aliases } = require('../../lib/utils/cmd-list')
-const { shorthands, definitions } = require('@npmcli/config/lib/definitions')
-
-const DOC_EXT = '.md'
-
-const TAGS = {
- CONFIG: '<!-- AUTOGENERATED CONFIG DESCRIPTIONS -->',
- USAGE: '<!-- AUTOGENERATED USAGE DESCRIPTIONS -->',
- SHORTHANDS: '<!-- AUTOGENERATED CONFIG SHORTHANDS -->',
-}
-
-const assertPlaceholder = (src, path, placeholder) => {
- if (!src.includes(placeholder)) {
- throw new Error(
- `Cannot replace ${placeholder} in ${path} due to missing placeholder`
- )
- }
- return placeholder
-}
-
-// Default command loader - loads commands from lib/commands
-const defaultCommandLoader = (name) => {
- return require(`../../lib/commands/${name}`)
-}
-
-// Load a command using the provided loader or default
-const getCommand = (name, commandLoader = defaultCommandLoader) => {
- return commandLoader(name)
-}
-
-// Resolve definitions for a command - use definitions if present, otherwise build from params
-const resolveDefinitions = (command) => {
- // If command has definitions, use them directly (ignore params)
- if (command.definitions && Object.keys(command.definitions).length > 0) {
- return command.definitions
- }
-
- // Otherwise build from params using global definitions
- if (command.params) {
- const resolved = {}
- for (const param of command.params) {
- if (definitions[param]) {
- resolved[param] = definitions[param]
- }
- }
- return resolved
- }
-
- return {}
-}
-
-const getCommandByDoc = (docFile, docExt, commandLoader = defaultCommandLoader) => {
- // Grab the command name from the *.md filename
- // NOTE: We cannot use the name property command file because in the case of
- // `npx` the file being used is `lib/commands/exec.js`
- const name = basename(docFile, docExt).replace('npm-', '')
-
- if (name === 'npm') {
- return {
- name,
- definitions: [],
- usage: 'npm',
- }
- }
-
- // special case for `npx`:
- // `npx` is not technically a command in and of itself,
- // so it just needs the usage of npm exec
- const srcName = name === 'npx' ? 'exec' : name
- const command = getCommand(srcName, commandLoader)
- const { usage = [''], workspaces } = command
- const usagePrefix = name === 'npx' ? 'npx' : `npm ${name}`
-
- // Resolve definitions - handles exclusive params expansion
- const commandDefs = resolveDefinitions(command)
- const resolvedDefs = {}
- for (const [key, def] of Object.entries(commandDefs)) {
- resolvedDefs[key] = def
- // Handle exclusive params
- if (def.exclusive) {
- for (const e of def.exclusive) {
- if (!resolvedDefs[e] && definitions[e]) {
- resolvedDefs[e] = definitions[e]
- }
- }
- }
- }
-
- return {
- name,
- workspaces,
- definitions: name === 'npx' ? {} : resolvedDefs,
- usage: usage?.map(u => `${usagePrefix} ${u}`.trim()).join('\n'),
- }
-}
-
-const replaceVersion = (src) => src.replace(/@VERSION@/g, version)
-
-const replaceUsage = (src, { path, commandLoader }) => {
- const replacer = assertPlaceholder(src, path, TAGS.USAGE)
- const { usage, name, workspaces } = getCommandByDoc(path, DOC_EXT, commandLoader)
-
- const synopsis = []
-
- if (usage) {
- synopsis.push('```bash', usage)
-
- const cmdAliases = Object.keys(aliases).reduce((p, c) => {
- if (aliases[c] === name) {
- p.push(c)
- }
- return p
- }, [])
-
- if (cmdAliases.length === 1) {
- synopsis.push('', `alias: ${cmdAliases[0]}`)
- } else if (cmdAliases.length > 1) {
- synopsis.push('', `aliases: ${cmdAliases.join(', ')}`)
- }
-
- synopsis.push('```')
- }
-
- if (!workspaces) {
- if (synopsis.length) {
- synopsis.push('')
- }
- synopsis.push('Note: This command is unaware of workspaces.')
- }
-
- return src.replace(replacer, synopsis.join('\n'))
-}
-
-// Helper to generate a markdown table from definitions
-const generateFlagsTable = (definitionPool) => {
- const rows = Object.keys(definitionPool).map((n) => {
- const def = definitionPool[n]
- const flags = [`\`--${def.key}\``]
- if (def.alias) {
- flags.push(...def.alias.map(a => `\`--${a}\``))
- }
- if (def.short) {
- flags.push(`\`-${def.short}\``)
- }
- const flagsStr = flags.join(', ')
- let defaultVal = def.defaultDescription
- if (!defaultVal) {
- defaultVal = String(def.default)
- }
- defaultVal = defaultVal.replace(/\n/g, ' ').trim()
- let typeVal = def.typeDescription || String(def.type)
- if (def.required) {
- typeVal = `${typeVal} (required)`
- }
- typeVal = typeVal.replace(/\n/g, ' ').trim()
- const desc = (def.description || '').replace(/\n/g, ' ').trim()
- return `| ${flagsStr} | ${defaultVal} | ${typeVal} | ${desc} |`
- })
-
- return [
- '| Flag | Default | Type | Description |',
- '| --- | --- | --- | --- |',
- ...rows,
- ].join('\n')
-}
-
-const replaceDefinitions = (src, { path, commandLoader }) => {
- const { definitions: commandDefs, name } = getCommandByDoc(path, DOC_EXT, commandLoader)
-
- let subcommands = {}
- try {
- const command = getCommand(name, commandLoader)
- subcommands = command.subcommands || {}
- } catch {
- // Command doesn't exist
- }
-
- // If no definitions and no subcommands, nothing to replace
- if (Object.keys(commandDefs).length === 0 && Object.keys(subcommands).length === 0) {
- return src
- }
-
- // Assert placeholder is present
- const replacer = assertPlaceholder(src, path, TAGS.CONFIG)
-
- // If command has subcommands, generate sections for each subcommand
- if (Object.keys(subcommands).length > 0) {
- const subcommandSections = Object.entries(subcommands).map(([subName, SubCommand]) => {
- const subUsage = SubCommand.usage || []
- const subDefs = resolveDefinitions(SubCommand)
-
- const parts = [`### \`npm ${name} ${subName}\``, '']
-
- if (SubCommand.description) {
- parts.push(SubCommand.description, '')
- }
-
- // Add usage/synopsis
- if (subUsage.length > 0) {
- parts.push('#### Synopsis', '', '```bash')
- subUsage.forEach(u => {
- parts.push(`npm ${name} ${subName} ${u}`.trim())
- })
- parts.push('```', '')
- }
-
- // Add flags section if definitions exist
- if (Object.keys(subDefs).length > 0) {
- parts.push('#### Flags', '')
- parts.push(generateFlagsTable(subDefs), '')
- }
-
- return parts.join('\n')
- })
-
- return src.replace(replacer, subcommandSections.join('\n'))
- }
-
- // For commands without subcommands - commandDefs must be non-empty here
- // (we would have returned early at line 175 if both were empty)
- const paramDescriptions = Object.values(commandDefs)
- .map(def => def.describe())
-
- return src.replace(replacer, paramDescriptions.join('\n\n'))
-}
-
-const replaceConfig = (src, { path }) => {
- const replacer = assertPlaceholder(src, path, TAGS.CONFIG)
-
- // sort not-deprecated ones to the top
- /* istanbul ignore next - typically already sorted in the definitions file,
- * but this is here so that our help doc will stay consistent if we decide
- * to move them around. */
- const sort = ([keya, { deprecated: depa }], [keyb, { deprecated: depb }]) => {
- return depa && !depb ? 1
- : !depa && depb ? -1
- : localeCompare(keya, keyb)
- }
-
- const allConfig = Object.entries(definitions).sort(sort)
- .map(([, def]) => def.describe())
- .join('\n\n')
-
- return src.replace(replacer, allConfig)
-}
-
-const replaceShorthands = (src, { path }) => {
- const replacer = assertPlaceholder(src, path, TAGS.SHORTHANDS)
-
- const sh = Object.entries(shorthands)
- .sort(([shorta, expansiona], [shortb, expansionb]) =>
- // sort by what they're short FOR
- localeCompare(expansiona.join(' '), expansionb.join(' ')) || localeCompare(shorta, shortb)
- )
- .map(([short, expansion]) => {
- // XXX: this is incorrect. we have multicharacter flags like `-iwr` that
- // can only be set with a single dash
- const dash = short.length === 1 ? '-' : '--'
- return `* \`${dash}${short}\`: \`${expansion.join(' ')}\``
- })
-
- return src.replace(replacer, sh.join('\n'))
-}
-
-const replaceHelpLinks = (src) => {
- // replaces markdown links with equivalent-ish npm help commands
- return src.replace(
- /\[`?([\w\s-]+)`?\]\(\/(?:commands|configuring-npm|using-npm)\/(?:[\w\s-]+)\)/g,
- (_, p1) => {
- const term = p1.replace(/npm\s/g, '').replace(/\s+/g, ' ').trim()
- const help = `npm help ${term.includes(' ') ? `"${term}"` : term}`
- return help
- }
- )
-}
-
-const transformMan = (src, { data, unified, remarkParse, remarkMan }) => unified()
- .use(remarkParse)
- .use(remarkMan, { version: `NPM@${version}` })
- .processSync(`# ${data.title}(${data.section}) - ${data.description}\n\n${src}`)
- .toString()
-
-const manPath = (name, { data }) => join(`man${data.section}`, `${name}.${data.section}`)
-
-const transformMd = (src, { frontmatter }) => ['---', frontmatter, '---', '', src].join('\n')
-
-module.exports = {
- DOC_EXT,
- TAGS,
- paths: {
- content: resolve(__dirname, 'content'),
- nav: resolve(__dirname, 'content', 'nav.yml'),
- template: resolve(__dirname, 'template.html'),
- man: resolve(__dirname, '..', '..', 'man'),
- html: resolve(__dirname, '..', 'output'),
- md: resolve(__dirname, '..', 'content'),
- },
- usage: replaceUsage,
- definitions: replaceDefinitions,
- config: replaceConfig,
- shorthands: replaceShorthands,
- version: replaceVersion,
- helpLinks: replaceHelpLinks,
- man: transformMan,
- manPath: manPath,
- md: transformMd,
- html: transformHTML,
-}
diff --git a/deps/npm/docs/output/commands/npm-access.html b/deps/npm/docs/output/commands/npm-access.html
index ac6df64b960..f1145dca357 100644
--- a/deps/npm/docs/output/commands/npm-access.html
+++ b/deps/npm/docs/output/commands/npm-access.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-access----11191">
+<h1 id="----npm-access----1210">
<span>npm-access</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Set access level on published packages</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-adduser.html b/deps/npm/docs/output/commands/npm-adduser.html
deleted file mode 100644
index 29aec6314e9..00000000000
--- a/deps/npm/docs/output/commands/npm-adduser.html
+++ /dev/null
@@ -1,271 +0,0 @@
-<!DOCTYPE html><html><head>
-<meta charset="utf-8">
-<title>npm-adduser</title>
-<style>
-body {
- background-color: #ffffff;
- color: #24292e;
-
- margin: 0;
-
- line-height: 1.5;
-
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
-}
-#rainbar {
- height: 10px;
- background-image: linear-gradient(139deg, #fb8817, #ff4b01, #c12127, #e02aff);
-}
-
-a {
- text-decoration: none;
- color: #0366d6;
-}
-a:hover {
- text-decoration: underline;
-}
-
-pre {
- margin: 1em 0px;
- padding: 1em;
- border: solid 1px #e1e4e8;
- border-radius: 6px;
-
- display: block;
- overflow: auto;
-
- white-space: pre;
-
- background-color: #f6f8fa;
- color: #393a34;
-}
-code {
- font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace;
- font-size: 85%;
- padding: 0.2em 0.4em;
- background-color: #f6f8fa;
- color: #393a34;
-}
-pre > code {
- padding: 0;
- background-color: inherit;
- color: inherit;
-}
-h1, h2, h3 {
- font-weight: 600;
-}
-
-#logobar {
- background-color: #333333;
- margin: 0 auto;
- padding: 1em 4em;
-}
-#logobar .logo {
- float: left;
-}
-#logobar .title {
- font-weight: 600;
- color: #dddddd;
- float: left;
- margin: 5px 0 0 1em;
-}
-#logobar:after {
- content: "";
- display: block;
- clear: both;
-}
-
-#content {
- margin: 0 auto;
- padding: 0 4em;
-}
-
-#table_of_contents > h2 {
- font-size: 1.17em;
-}
-#table_of_contents ul:first-child {
- border: solid 1px #e1e4e8;
- border-radius: 6px;
- padding: 1em;
- background-color: #f6f8fa;
- color: #393a34;
-}
-#table_of_contents ul {
- list-style-type: none;
- padding-left: 1.5em;
-}
-#table_of_contents li {
- font-size: 0.9em;
-}
-#table_of_contents li a {
- color: #000000;
-}
-
-header.title {
- border-bottom: solid 1px #e1e4e8;
-}
-header.title > h1 {
- margin-bottom: 0.25em;
-}
-header.title > .description {
- display: block;
- margin-bottom: 0.5em;
- line-height: 1;
-}
-
-header.title .version {
- font-size: 0.8em;
- color: #666666;
-}
-
-footer#edit {
- border-top: solid 1px #e1e4e8;
- margin: 3em 0 4em 0;
- padding-top: 2em;
-}
-
-table {
- width: 100%;
- margin: 1em 0;
- border-radius: 6px;
- border: 1px solid #e1e4e8;
- overflow: hidden;
- border-collapse: separate;
- border-spacing: 0;
-}
-
-table thead {
- background-color: #f6f8fa;
-}
-
-table tbody {
- background-color: #ffffff;
-}
-
-table th,
-table td {
- padding: 0.75em;
- text-align: left;
- border-right: 1px solid #e1e4e8;
- border-bottom: 1px solid #e1e4e8;
-}
-
-table th:last-child,
-table td:last-child {
- border-right: none;
-}
-
-table tbody tr:last-child td {
- border-bottom: none;
-}
-
-table th {
- font-weight: 600;
- background-color: #f6f8fa;
-}
-
-table code {
- white-space: nowrap;
-}
-
-</style>
-</head>
-<body>
-<div id="banner">
-<div id="rainbar"></div>
-<div id="logobar">
-<svg class="logo" role="img" height="32" width="32" viewBox="0 0 700 700">
-<polygon fill="#cb0000" points="0,700 700,700 700,0 0,0"></polygon>
-<polygon fill="#ffffff" points="150,550 350,550 350,250 450,250 450,550 550,550 550,150 150,150"></polygon>
-</svg>
-<div class="title">
-npm command-line interface
-</div>
-</div>
-</div>
-
-<section id="content">
-<header class="title">
-<h1 id="----npm-adduser----11191">
- <span>npm-adduser</span>
- <span class="version">@11.19.1</span>
-</h1>
-<span class="description">Add a registry user account</span>
-</header>
-
-<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"><code>registry</code></a></li><li><a href="#scope"><code>scope</code></a></li><li><a href="#auth-type"><code>auth-type</code></a></li></ul><li><a href="#see-also">See Also</a></li></ul></div>
-</section>
-
-<div id="_content"><h3 id="synopsis">Synopsis</h3>
-<pre><code class="language-bash">npm adduser
-
-alias: add-user
-</code></pre>
-<p>Note: This command is unaware of workspaces.</p>
-<h3 id="description">Description</h3>
-<p>Create a new user in the specified registry, and save the credentials to the <code>.npmrc</code> file.
-If no registry is specified, the default registry will be used (see <a href="../using-npm/registry.html"><code>registry</code></a>).</p>
-<p>When you run <code>npm adduser</code>, the CLI automatically generates a legacy token of <code>publish</code> type.
-For more information, see <a href="../about-access-tokens#about-legacy-tokens.html">About legacy tokens</a>.</p>
-<p>When using <code>legacy</code> for your <code>auth-type</code>, the username, password, and email are read in from prompts.</p>
-<h3 id="configuration">Configuration</h3>
-<h4 id="registry"><code>registry</code></h4>
-<ul>
-<li>Default: "<a href="https://registry.npmjs.org/">https://registry.npmjs.org/</a>"</li>
-<li>Type: URL</li>
-</ul>
-<p>The base URL of the npm registry.</p>
-<h4 id="scope"><code>scope</code></h4>
-<ul>
-<li>Default: the scope of the current project, if any, or ""</li>
-<li>Type: String</li>
-</ul>
-<p>Associate an operation with a scope for a scoped registry.</p>
-<p>Useful when logging in to or out of a private registry:</p>
-<pre><code># log in, linking the scope to the custom registry
-npm login --scope=@mycorp --registry=https://registry.mycorp.com
-
-# log out, removing the link and the auth token
-npm logout --scope=@mycorp
-</code></pre>
-<p>This will cause <code>@mycorp</code> to be mapped to the registry for future
-installation of packages specified according to the pattern
-<code>@mycorp/package</code>.</p>
-<p>This will also cause <code>npm init</code> to create a scoped package.</p>
-<pre><code># accept all defaults, and create a package named "@foo/whatever",
-# instead of just named "whatever"
-npm init --scope=@foo --yes
-</code></pre>
-<h4 id="auth-type"><code>auth-type</code></h4>
-<ul>
-<li>Default: "web"</li>
-<li>Type: "legacy" or "web"</li>
-</ul>
-<p>What authentication strategy to use with <code>login</code>. Note that if an <code>otp</code>
-config is given, this value will always be set to <code>legacy</code>.</p>
-<h3 id="see-also">See Also</h3>
-<ul>
-<li><a href="../using-npm/registry.html">npm registry</a></li>
-<li><a href="../commands/npm-config.html">npm config</a></li>
-<li><a href="../configuring-npm/npmrc.html">npmrc</a></li>
-<li><a href="../commands/npm-owner.html">npm owner</a></li>
-<li><a href="../commands/npm-whoami.html">npm whoami</a></li>
-<li><a href="../commands/npm-token.html">npm token</a></li>
-<li><a href="../commands/npm-profile.html">npm profile</a></li>
-</ul></div>
-
-<footer id="edit">
-<a href="https://github.com/npm/cli/edit/latest/docs/lib/content/commands/npm-adduser.md">
-<svg role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentcolor" style="vertical-align: text-bottom; margin-right: 0.3em;">
-<path fill-rule="evenodd" d="M11.013 1.427a1.75 1.75 0 012.474 0l1.086 1.086a1.75 1.75 0 010 2.474l-8.61 8.61c-.21.21-.47.364-.756.445l-3.251.93a.75.75 0 01-.927-.928l.929-3.25a1.75 1.75 0 01.445-.758l8.61-8.61zm1.414 1.06a.25.25 0 00-.354 0L10.811 3.75l1.439 1.44 1.263-1.263a.25.25 0 000-.354l-1.086-1.086zM11.189 6.25L9.75 4.81l-6.286 6.287a.25.25 0 00-.064.108l-.558 1.953 1.953-.558a.249.249 0 00.108-.064l6.286-6.286z"></path>
-</svg>
-Edit this page on GitHub
-</a>
-</footer>
-</section>
-
-
-
-</body></html>
\ No newline at end of file
diff --git a/deps/npm/docs/output/commands/npm-approve-scripts.html b/deps/npm/docs/output/commands/npm-approve-scripts.html
index 3d61cc8ea23..dfa9da343fb 100644
--- a/deps/npm/docs/output/commands/npm-approve-scripts.html
+++ b/deps/npm/docs/output/commands/npm-approve-scripts.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-approve-scripts----11191">
+<h1 id="----npm-approve-scripts----1210">
<span>npm-approve-scripts</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Approve install scripts for specific dependencies</span>
</header>
@@ -209,9 +209,10 @@ npm approve-scripts --allow-scripts-pending
records which of your dependencies are permitted to run install scripts
(<code>preinstall</code>, <code>install</code>, <code>postinstall</code>, and <code>prepare</code> for non-registry
sources). This command is the recommended way to maintain that field.</p>
-<p>In the current release, this field is advisory: install scripts still run
-by default, but installs print a list of packages whose scripts have not
-been reviewed. A future release will block unreviewed install scripts.</p>
+<p>Dependency install scripts are blocked by default. Install commands
+silently skip lifecycle scripts for any dependency that does not have a
+matching entry in <code>allowScripts</code>, and end with a list of the packages
+whose scripts were skipped so you can review them with this command.</p>
<p>This command only works inside a project that has a <code>package.json</code>. Running
it with <code>--global</code> (<code>-g</code>) fails with an <code>EGLOBAL</code> error, since global
installs (<code>npm install -g</code>) and one-off executions (<code>npm exec</code> / <code>npx</code>) have
diff --git a/deps/npm/docs/output/commands/npm-audit.html b/deps/npm/docs/output/commands/npm-audit.html
index 9117faa9bed..580a501c913 100644
--- a/deps/npm/docs/output/commands/npm-audit.html
+++ b/deps/npm/docs/output/commands/npm-audit.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-audit----11191">
+<h1 id="----npm-audit----1210">
<span>npm-audit</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Run a security audit</span>
</header>
@@ -212,7 +212,7 @@ Also note that since <code>npm audit fix</code> runs a full-fledged <code>npm in
It may be useful in CI environments to include the <code>--audit-level</code> parameter to specify the minimum vulnerability level that will cause the command to fail.
This option does not filter the report output, it simply changes the command's failure threshold.</p>
<h3 id="package-lock">Package lock</h3>
-<p>By default npm requires a package-lock or shrinkwrap in order to run the audit.
+<p>By default npm requires a package-lock in order to run the audit.
You can bypass the package lock with <code>--no-package-lock</code> but be aware the results may be different with every run, since npm will re-build the dependency tree each time.</p>
<h3 id="audit-signatures">Audit Signatures</h3>
<p>To ensure the integrity of packages you download from the public npm registry, or any registry that supports signatures, you can verify the registry signatures of downloaded packages using the npm CLI.</p>
@@ -409,8 +409,7 @@ will also prevent <em>writing</em> <code>package-lock.json</code> if <code>save<
</ul>
<p>Dependency types to omit from the installation tree on disk.</p>
<p>Note that these dependencies <em>are</em> still resolved and added to the
-<code>package-lock.json</code> or <code>npm-shrinkwrap.json</code> file. They are just not
-physically installed on disk.</p>
+<code>package-lock.json</code> file. They are just not physically installed on disk.</p>
<p>If a package type appears in both the <code>--include</code> and <code>--omit</code> lists, then
it will be included.</p>
<p>If the resulting omit list includes <code>'dev'</code>, then the <code>NODE_ENV</code> environment
@@ -445,6 +444,8 @@ but can be useful for debugging.</p>
<code>npm start</code>, <code>npm stop</code>, <code>npm restart</code>, <code>npm test</code>, and <code>npm run</code> will still
run their intended script if <code>ignore-scripts</code> is set, but they will <em>not</em>
run any pre- or post-scripts.</p>
+<p>Setting <code>ignore-scripts</code> also disables <code>.npm-extension</code> execution, as if
+<code>ignore-extension</code> were set.</p>
<h4 id="include-attestations"><code>include-attestations</code></h4>
<ul>
<li>Default: false</li>
diff --git a/deps/npm/docs/output/commands/npm-bugs.html b/deps/npm/docs/output/commands/npm-bugs.html
index 63f4c29210a..f5fbbb0bc50 100644
--- a/deps/npm/docs/output/commands/npm-bugs.html
+++ b/deps/npm/docs/output/commands/npm-bugs.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-bugs----11191">
+<h1 id="----npm-bugs----1210">
<span>npm-bugs</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Report bugs for a package in a web browser</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-cache.html b/deps/npm/docs/output/commands/npm-cache.html
index 3377b00cc56..2d30ca6fea1 100644
--- a/deps/npm/docs/output/commands/npm-cache.html
+++ b/deps/npm/docs/output/commands/npm-cache.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-cache----11191">
+<h1 id="----npm-cache----1210">
<span>npm-cache</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Manipulates packages cache</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-ci.html b/deps/npm/docs/output/commands/npm-ci.html
index edde5bbdef6..ddd06430b22 100644
--- a/deps/npm/docs/output/commands/npm-ci.html
+++ b/deps/npm/docs/output/commands/npm-ci.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-ci----11191">
+<h1 id="----npm-ci----1210">
<span>npm-ci</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Clean install a project</span>
</header>
@@ -207,13 +207,12 @@ aliases: clean-install, ic, install-clean, isntall-clean
<p>This command is similar to <a href="../commands/npm-install.html"><code>npm install</code></a>, except it's meant to be used in automated environments such as test platforms, continuous integration, and deployment -- or any situation where you want to make sure you're doing a clean install of your dependencies.</p>
<p>The main differences between using <code>npm install</code> and <code>npm ci</code> are:</p>
<ul>
-<li>The project <strong>must</strong> have an existing <code>package-lock.json</code> or
-<code>npm-shrinkwrap.json</code>.</li>
+<li>The project <strong>must</strong> have an existing <code>package-lock.json</code>.</li>
<li>If dependencies in the package lock do not match those in <code>package.json</code>,
<code>npm ci</code> will exit with an error, instead of updating the package lock.</li>
<li><code>npm ci</code> can only install entire projects at a time: individual dependencies cannot be added with this command.</li>
<li>If a <code>node_modules</code> is already present, it will be automatically removed before <code>npm ci</code> begins its install.</li>
-<li>It will never write to <code>package.json</code> or any of the package-locks:
+<li>It will never write to <code>package.json</code> or <code>package-lock.json</code>:
installs are essentially frozen.</li>
</ul>
<p>NOTE: If you create your <code>package-lock.json</code> file by running <code>npm install</code> with flags that can affect the shape of your dependency tree, such as
@@ -288,8 +287,7 @@ on deeper dependencies. Sets <code>--install-strategy=shallow</code>.</p>
</ul>
<p>Dependency types to omit from the installation tree on disk.</p>
<p>Note that these dependencies <em>are</em> still resolved and added to the
-<code>package-lock.json</code> or <code>npm-shrinkwrap.json</code> file. They are just not
-physically installed on disk.</p>
+<code>package-lock.json</code> file. They are just not physically installed on disk.</p>
<p>If a package type appears in both the <code>--include</code> and <code>--omit</code> lists, then
it will be included.</p>
<p>If the resulting omit list includes <code>'dev'</code>, then the <code>NODE_ENV</code> environment
@@ -340,6 +338,8 @@ but can be useful for debugging.</p>
<code>npm start</code>, <code>npm stop</code>, <code>npm restart</code>, <code>npm test</code>, and <code>npm run</code> will still
run their intended script if <code>ignore-scripts</code> is set, but they will <em>not</em>
run any pre- or post-scripts.</p>
+<p>Setting <code>ignore-scripts</code> also disables <code>.npm-extension</code> execution, as if
+<code>ignore-extension</code> were set.</p>
<h4 id="allow-directory"><code>allow-directory</code></h4>
<ul>
<li>Default: "all"</li>
@@ -370,7 +370,7 @@ project's package.json to be installed. Also allows tarball file
dependencies to be used for other commands like <code>npm view</code></p>
<h4 id="allow-git"><code>allow-git</code></h4>
<ul>
-<li>Default: "all"</li>
+<li>Default: "none"</li>
<li>Type: "all", "none", or "root"</li>
</ul>
<p>Limits the ability for npm to fetch dependencies from git references. That
@@ -378,6 +378,10 @@ is, dependencies that point to a git repo instead of a version or semver
range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.</p>
+<p>As of npm 12 the default is <code>none</code>. Git dependencies run <code>git</code> against a
+remote repo and may install configuration the project does not control. Opt
+in explicitly per project (in <code>.npmrc</code>) or per command (on the CLI) when you
+need git deps.</p>
<p><code>all</code> allows any git dependencies to be fetched and installed. <code>none</code>
prevents any git dependencies from being fetched and installed. <code>root</code> only
allows git dependencies defined in your project's package.json to be fetched
@@ -385,7 +389,7 @@ and installed. Also allows git dependencies to be fetched for other commands
like <code>npm view</code></p>
<h4 id="allow-remote"><code>allow-remote</code></h4>
<ul>
-<li>Default: "all"</li>
+<li>Default: "none"</li>
<li>Type: "all", "none", or "root"</li>
</ul>
<p>Limits the ability for npm to fetch dependencies from urls. That is,
@@ -393,6 +397,12 @@ dependencies that point to a tarball url instead of a version or semver
range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.</p>
+<p>As of npm 12 the default is <code>none</code>. Tarballs that share a hostname with the
+configured registry (the typical case for the npm registry, GitHub Packages,
+and most private registries) are still installed normally. If your registry
+serves tarballs from a different host, set <code>replace-registry-host</code> or
+override this setting. Opt in explicitly per project (in <code>.npmrc</code>) or per
+command (on the CLI) when you intentionally install from a URL.</p>
<p><code>all</code> allows any url to be installed. <code>none</code> prevents any url from being
installed. <code>root</code> only allows urls defined in your project's package.json to
be installed. Also allows url dependencies to be used for other commands
@@ -414,16 +424,18 @@ project-scoped <code>npm install</code>, <code>ci</code>, <code>update</code>, o
<p>Each name is matched against a dependency's resolved identity, not against
the package's self-reported name. <code>--ignore-scripts</code> and
<code>--dangerously-allow-all-scripts</code> both override this setting.</p>
+<p>This value is not exported to the environment for child processes.</p>
<h4 id="strict-allow-scripts"><code>strict-allow-scripts</code></h4>
<ul>
<li>Default: false</li>
<li>Type: Boolean</li>
</ul>
<p>If <code>true</code>, turn the install-script policy from a warning into a hard error:
-any dependency with install scripts not covered by <code>allowScripts</code> will fail
-the install instead of running with a notice.</p>
+any dependency with install scripts that is not covered by <code>allowScripts</code>
+will fail the install instead of being blocked with a warning.</p>
<p>Dependencies explicitly denied with <code>false</code> in <code>allowScripts</code> are always
-silently skipped; this setting only affects unreviewed entries.
+silently skipped; this setting only affects unreviewed entries (packages
+with install scripts that are neither approved nor denied).
<code>--ignore-scripts</code> and <code>--dangerously-allow-all-scripts</code> both override this
setting.</p>
<p>Optional dependencies that cannot be installed on the current platform or
diff --git a/deps/npm/docs/output/commands/npm-completion.html b/deps/npm/docs/output/commands/npm-completion.html
index b5a6f445d45..09a6210f9eb 100644
--- a/deps/npm/docs/output/commands/npm-completion.html
+++ b/deps/npm/docs/output/commands/npm-completion.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-completion----11191">
+<h1 id="----npm-completion----1210">
<span>npm-completion</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Tab Completion for npm</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-config.html b/deps/npm/docs/output/commands/npm-config.html
index c9ea9080cf7..53289aa4feb 100644
--- a/deps/npm/docs/output/commands/npm-config.html
+++ b/deps/npm/docs/output/commands/npm-config.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-config----11191">
+<h1 id="----npm-config----1210">
<span>npm-config</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Manage the npm configuration files</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-dedupe.html b/deps/npm/docs/output/commands/npm-dedupe.html
index abe4a229e77..057d7f9a63c 100644
--- a/deps/npm/docs/output/commands/npm-dedupe.html
+++ b/deps/npm/docs/output/commands/npm-dedupe.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-dedupe----11191">
+<h1 id="----npm-dedupe----1210">
<span>npm-dedupe</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Reduce duplication in the package tree</span>
</header>
@@ -305,8 +305,7 @@ will also prevent <em>writing</em> <code>package-lock.json</code> if <code>save<
</ul>
<p>Dependency types to omit from the installation tree on disk.</p>
<p>Note that these dependencies <em>are</em> still resolved and added to the
-<code>package-lock.json</code> or <code>npm-shrinkwrap.json</code> file. They are just not
-physically installed on disk.</p>
+<code>package-lock.json</code> file. They are just not physically installed on disk.</p>
<p>If a package type appears in both the <code>--include</code> and <code>--omit</code> lists, then
it will be included.</p>
<p>If the resulting omit list includes <code>'dev'</code>, then the <code>NODE_ENV</code> environment
@@ -330,6 +329,8 @@ the order in which omit/include are specified on the command-line.</p>
<code>npm start</code>, <code>npm stop</code>, <code>npm restart</code>, <code>npm test</code>, and <code>npm run</code> will still
run their intended script if <code>ignore-scripts</code> is set, but they will <em>not</em>
run any pre- or post-scripts.</p>
+<p>Setting <code>ignore-scripts</code> also disables <code>.npm-extension</code> execution, as if
+<code>ignore-extension</code> were set.</p>
<h4 id="allow-directory"><code>allow-directory</code></h4>
<ul>
<li>Default: "all"</li>
@@ -360,7 +361,7 @@ project's package.json to be installed. Also allows tarball file
dependencies to be used for other commands like <code>npm view</code></p>
<h4 id="allow-git"><code>allow-git</code></h4>
<ul>
-<li>Default: "all"</li>
+<li>Default: "none"</li>
<li>Type: "all", "none", or "root"</li>
</ul>
<p>Limits the ability for npm to fetch dependencies from git references. That
@@ -368,6 +369,10 @@ is, dependencies that point to a git repo instead of a version or semver
range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.</p>
+<p>As of npm 12 the default is <code>none</code>. Git dependencies run <code>git</code> against a
+remote repo and may install configuration the project does not control. Opt
+in explicitly per project (in <code>.npmrc</code>) or per command (on the CLI) when you
+need git deps.</p>
<p><code>all</code> allows any git dependencies to be fetched and installed. <code>none</code>
prevents any git dependencies from being fetched and installed. <code>root</code> only
allows git dependencies defined in your project's package.json to be fetched
@@ -375,7 +380,7 @@ and installed. Also allows git dependencies to be fetched for other commands
like <code>npm view</code></p>
<h4 id="allow-remote"><code>allow-remote</code></h4>
<ul>
-<li>Default: "all"</li>
+<li>Default: "none"</li>
<li>Type: "all", "none", or "root"</li>
</ul>
<p>Limits the ability for npm to fetch dependencies from urls. That is,
@@ -383,6 +388,12 @@ dependencies that point to a tarball url instead of a version or semver
range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.</p>
+<p>As of npm 12 the default is <code>none</code>. Tarballs that share a hostname with the
+configured registry (the typical case for the npm registry, GitHub Packages,
+and most private registries) are still installed normally. If your registry
+serves tarballs from a different host, set <code>replace-registry-host</code> or
+override this setting. Opt in explicitly per project (in <code>.npmrc</code>) or per
+command (on the CLI) when you intentionally install from a URL.</p>
<p><code>all</code> allows any url to be installed. <code>none</code> prevents any url from being
installed. <code>root</code> only allows urls defined in your project's package.json to
be installed. Also allows url dependencies to be used for other commands
diff --git a/deps/npm/docs/output/commands/npm-deny-scripts.html b/deps/npm/docs/output/commands/npm-deny-scripts.html
index 3a56f32dc97..e11a5f0283c 100644
--- a/deps/npm/docs/output/commands/npm-deny-scripts.html
+++ b/deps/npm/docs/output/commands/npm-deny-scripts.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-deny-scripts----11191">
+<h1 id="----npm-deny-scripts----1210">
<span>npm-deny-scripts</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Deny install scripts for specific dependencies</span>
</header>
@@ -208,10 +208,10 @@ npm deny-scripts --all
Writes <code>false</code> entries into the <code>allowScripts</code> field of your project's
<code>package.json</code>, recording that a dependency must not run install scripts
even if a future version would otherwise be eligible.</p>
-<p>In the current release, install scripts still run by default, so <code>deny-scripts</code>
-only affects how installs of denied packages are reported. A future release
-will block unreviewed install scripts and respect deny entries at install
-time.</p>
+<p>Dependency install scripts are blocked by default. Adding a <code>false</code>
+entry with <code>deny-scripts</code> makes the denial explicit (so it survives
+<code>npm approve-scripts --all</code>) and excludes the package from any future
+<code>--allow-scripts-pending</code> review prompts.</p>
<pre><code class="language-bash">npm deny-scripts <pkg> [<pkg> ...]
npm deny-scripts --all
</code></pre>
diff --git a/deps/npm/docs/output/commands/npm-deprecate.html b/deps/npm/docs/output/commands/npm-deprecate.html
index 90f45466cad..15df0c2668a 100644
--- a/deps/npm/docs/output/commands/npm-deprecate.html
+++ b/deps/npm/docs/output/commands/npm-deprecate.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-deprecate----11191">
+<h1 id="----npm-deprecate----1210">
<span>npm-deprecate</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Deprecate a version of a package</span>
</header>
@@ -213,7 +213,7 @@ For example:</p>
</code></pre>
<p>In this case, a version <code>my-thing@1.0.0-beta.0</code> will also be deprecated.</p>
<p>You must be the package owner to deprecate something.
-See the <code>owner</code> and <code>adduser</code> help topics.</p>
+See the <code>owner</code> and <code>login</code> help topics.</p>
<p>To un-deprecate a package, specify an empty string (<code>""</code>) for the <code>message</code> argument.
Note that you must use double quotes with no space between them to format an empty string.</p>
<h3 id="configuration">Configuration</h3>
@@ -249,7 +249,7 @@ commands that modify your local installation, eg, <code>install</code>, <code>up
<li><a href="../commands/npm-publish.html">npm publish</a></li>
<li><a href="../using-npm/registry.html">npm registry</a></li>
<li><a href="../commands/npm-owner.html">npm owner</a></li>
-<li><a href="../commands/npm-adduser.html">npm adduser</a></li>
+<li><a href="../commands/npm-login.html">npm login</a></li>
</ul></div>
<footer id="edit">
diff --git a/deps/npm/docs/output/commands/npm-diff.html b/deps/npm/docs/output/commands/npm-diff.html
index fba245e3b33..a1b38379951 100644
--- a/deps/npm/docs/output/commands/npm-diff.html
+++ b/deps/npm/docs/output/commands/npm-diff.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-diff----11191">
+<h1 id="----npm-diff----1210">
<span>npm-diff</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">The registry diff command</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-dist-tag.html b/deps/npm/docs/output/commands/npm-dist-tag.html
index 2d42ee8e3e8..060b6745444 100644
--- a/deps/npm/docs/output/commands/npm-dist-tag.html
+++ b/deps/npm/docs/output/commands/npm-dist-tag.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-dist-tag----11191">
+<h1 id="----npm-dist-tag----1210">
<span>npm-dist-tag</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Modify package distribution tags</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-docs.html b/deps/npm/docs/output/commands/npm-docs.html
index 98295c7943e..561371f59c1 100644
--- a/deps/npm/docs/output/commands/npm-docs.html
+++ b/deps/npm/docs/output/commands/npm-docs.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-docs----11191">
+<h1 id="----npm-docs----1210">
<span>npm-docs</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Open documentation for a package in a web browser</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-doctor.html b/deps/npm/docs/output/commands/npm-doctor.html
index 096f12bf3b8..1a2b4ee0c02 100644
--- a/deps/npm/docs/output/commands/npm-doctor.html
+++ b/deps/npm/docs/output/commands/npm-doctor.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-doctor----11191">
+<h1 id="----npm-doctor----1210">
<span>npm-doctor</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Check the health of your npm environment</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-edit.html b/deps/npm/docs/output/commands/npm-edit.html
index 7a555a8f39a..563b42bb7f3 100644
--- a/deps/npm/docs/output/commands/npm-edit.html
+++ b/deps/npm/docs/output/commands/npm-edit.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-edit----11191">
+<h1 id="----npm-edit----1210">
<span>npm-edit</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Edit an installed package</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-exec.html b/deps/npm/docs/output/commands/npm-exec.html
index 94e8e68c05f..b2995a0e15a 100644
--- a/deps/npm/docs/output/commands/npm-exec.html
+++ b/deps/npm/docs/output/commands/npm-exec.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-exec----11191">
+<h1 id="----npm-exec----1210">
<span>npm-exec</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Run a command from a local or remote npm package</span>
</header>
@@ -324,16 +324,18 @@ project-scoped <code>npm install</code>, <code>ci</code>, <code>update</code>, o
<p>Each name is matched against a dependency's resolved identity, not against
the package's self-reported name. <code>--ignore-scripts</code> and
<code>--dangerously-allow-all-scripts</code> both override this setting.</p>
+<p>This value is not exported to the environment for child processes.</p>
<h4 id="strict-allow-scripts"><code>strict-allow-scripts</code></h4>
<ul>
<li>Default: false</li>
<li>Type: Boolean</li>
</ul>
<p>If <code>true</code>, turn the install-script policy from a warning into a hard error:
-any dependency with install scripts not covered by <code>allowScripts</code> will fail
-the install instead of running with a notice.</p>
+any dependency with install scripts that is not covered by <code>allowScripts</code>
+will fail the install instead of being blocked with a warning.</p>
<p>Dependencies explicitly denied with <code>false</code> in <code>allowScripts</code> are always
-silently skipped; this setting only affects unreviewed entries.
+silently skipped; this setting only affects unreviewed entries (packages
+with install scripts that are neither approved nor denied).
<code>--ignore-scripts</code> and <code>--dangerously-allow-all-scripts</code> both override this
setting.</p>
<p>Optional dependencies that cannot be installed on the current platform or
diff --git a/deps/npm/docs/output/commands/npm-explain.html b/deps/npm/docs/output/commands/npm-explain.html
index ccf68b22712..7faddfe0822 100644
--- a/deps/npm/docs/output/commands/npm-explain.html
+++ b/deps/npm/docs/output/commands/npm-explain.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-explain----11191">
+<h1 id="----npm-explain----1210">
<span>npm-explain</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Explain installed packages</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-explore.html b/deps/npm/docs/output/commands/npm-explore.html
index 7b4d6a2ed2c..d7ece3306b0 100644
--- a/deps/npm/docs/output/commands/npm-explore.html
+++ b/deps/npm/docs/output/commands/npm-explore.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-explore----11191">
+<h1 id="----npm-explore----1210">
<span>npm-explore</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Browse an installed package</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-find-dupes.html b/deps/npm/docs/output/commands/npm-find-dupes.html
index 19b5ae4ffcf..92666ec12dc 100644
--- a/deps/npm/docs/output/commands/npm-find-dupes.html
+++ b/deps/npm/docs/output/commands/npm-find-dupes.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-find-dupes----11191">
+<h1 id="----npm-find-dupes----1210">
<span>npm-find-dupes</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Find duplication in the package tree</span>
</header>
@@ -273,8 +273,7 @@ will also prevent <em>writing</em> <code>package-lock.json</code> if <code>save<
</ul>
<p>Dependency types to omit from the installation tree on disk.</p>
<p>Note that these dependencies <em>are</em> still resolved and added to the
-<code>package-lock.json</code> or <code>npm-shrinkwrap.json</code> file. They are just not
-physically installed on disk.</p>
+<code>package-lock.json</code> file. They are just not physically installed on disk.</p>
<p>If a package type appears in both the <code>--include</code> and <code>--omit</code> lists, then
it will be included.</p>
<p>If the resulting omit list includes <code>'dev'</code>, then the <code>NODE_ENV</code> environment
@@ -298,6 +297,8 @@ the order in which omit/include are specified on the command-line.</p>
<code>npm start</code>, <code>npm stop</code>, <code>npm restart</code>, <code>npm test</code>, and <code>npm run</code> will still
run their intended script if <code>ignore-scripts</code> is set, but they will <em>not</em>
run any pre- or post-scripts.</p>
+<p>Setting <code>ignore-scripts</code> also disables <code>.npm-extension</code> execution, as if
+<code>ignore-extension</code> were set.</p>
<h4 id="audit"><code>audit</code></h4>
<ul>
<li>Default: true</li>
diff --git a/deps/npm/docs/output/commands/npm-fund.html b/deps/npm/docs/output/commands/npm-fund.html
index c657d182afd..9d6d709b5fc 100644
--- a/deps/npm/docs/output/commands/npm-fund.html
+++ b/deps/npm/docs/output/commands/npm-fund.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-fund----11191">
+<h1 id="----npm-fund----1210">
<span>npm-fund</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Retrieve funding information</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-get.html b/deps/npm/docs/output/commands/npm-get.html
index 59eaf5e577c..673a11ba40e 100644
--- a/deps/npm/docs/output/commands/npm-get.html
+++ b/deps/npm/docs/output/commands/npm-get.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-get----11191">
+<h1 id="----npm-get----1210">
<span>npm-get</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Get a value from the npm configuration</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-help-search.html b/deps/npm/docs/output/commands/npm-help-search.html
index d4abfb29c36..9d9d013eaf2 100644
--- a/deps/npm/docs/output/commands/npm-help-search.html
+++ b/deps/npm/docs/output/commands/npm-help-search.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-help-search----11191">
+<h1 id="----npm-help-search----1210">
<span>npm-help-search</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Search npm help documentation</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-help.html b/deps/npm/docs/output/commands/npm-help.html
index d4fe535e8bd..60ed1a93011 100644
--- a/deps/npm/docs/output/commands/npm-help.html
+++ b/deps/npm/docs/output/commands/npm-help.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-help----11191">
+<h1 id="----npm-help----1210">
<span>npm-help</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Get help on npm</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-init.html b/deps/npm/docs/output/commands/npm-init.html
index af686f90a7a..bf0036a128d 100644
--- a/deps/npm/docs/output/commands/npm-init.html
+++ b/deps/npm/docs/output/commands/npm-init.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-init----11191">
+<h1 id="----npm-init----1210">
<span>npm-init</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Create a package.json file</span>
</header>
@@ -303,10 +303,11 @@ Similar to the previous example of creating a new React-based project using <a h
homepage.</p>
<h4 id="init-license"><code>init-license</code></h4>
<ul>
-<li>Default: "ISC"</li>
+<li>Default: ""</li>
<li>Type: String</li>
</ul>
-<p>The value <code>npm init</code> should use by default for the package license.</p>
+<p>The value <code>npm init</code> should use by default for the package license. If not
+set, the license field will be omitted from new packages.</p>
<h4 id="init-module"><code>init-module</code></h4>
<ul>
<li>Default: "~/.npm-init.js"</li>
diff --git a/deps/npm/docs/output/commands/npm-install-ci-test.html b/deps/npm/docs/output/commands/npm-install-ci-test.html
index bdf779e2eef..0c575108842 100644
--- a/deps/npm/docs/output/commands/npm-install-ci-test.html
+++ b/deps/npm/docs/output/commands/npm-install-ci-test.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-install-ci-test----11191">
+<h1 id="----npm-install-ci-test----1210">
<span>npm-install-ci-test</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Install a project with a clean slate and run tests</span>
</header>
@@ -252,8 +252,7 @@ on deeper dependencies. Sets <code>--install-strategy=shallow</code>.</p>
</ul>
<p>Dependency types to omit from the installation tree on disk.</p>
<p>Note that these dependencies <em>are</em> still resolved and added to the
-<code>package-lock.json</code> or <code>npm-shrinkwrap.json</code> file. They are just not
-physically installed on disk.</p>
+<code>package-lock.json</code> file. They are just not physically installed on disk.</p>
<p>If a package type appears in both the <code>--include</code> and <code>--omit</code> lists, then
it will be included.</p>
<p>If the resulting omit list includes <code>'dev'</code>, then the <code>NODE_ENV</code> environment
@@ -304,6 +303,8 @@ but can be useful for debugging.</p>
<code>npm start</code>, <code>npm stop</code>, <code>npm restart</code>, <code>npm test</code>, and <code>npm run</code> will still
run their intended script if <code>ignore-scripts</code> is set, but they will <em>not</em>
run any pre- or post-scripts.</p>
+<p>Setting <code>ignore-scripts</code> also disables <code>.npm-extension</code> execution, as if
+<code>ignore-extension</code> were set.</p>
<h4 id="allow-directory"><code>allow-directory</code></h4>
<ul>
<li>Default: "all"</li>
@@ -334,7 +335,7 @@ project's package.json to be installed. Also allows tarball file
dependencies to be used for other commands like <code>npm view</code></p>
<h4 id="allow-git"><code>allow-git</code></h4>
<ul>
-<li>Default: "all"</li>
+<li>Default: "none"</li>
<li>Type: "all", "none", or "root"</li>
</ul>
<p>Limits the ability for npm to fetch dependencies from git references. That
@@ -342,6 +343,10 @@ is, dependencies that point to a git repo instead of a version or semver
range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.</p>
+<p>As of npm 12 the default is <code>none</code>. Git dependencies run <code>git</code> against a
+remote repo and may install configuration the project does not control. Opt
+in explicitly per project (in <code>.npmrc</code>) or per command (on the CLI) when you
+need git deps.</p>
<p><code>all</code> allows any git dependencies to be fetched and installed. <code>none</code>
prevents any git dependencies from being fetched and installed. <code>root</code> only
allows git dependencies defined in your project's package.json to be fetched
@@ -349,7 +354,7 @@ and installed. Also allows git dependencies to be fetched for other commands
like <code>npm view</code></p>
<h4 id="allow-remote"><code>allow-remote</code></h4>
<ul>
-<li>Default: "all"</li>
+<li>Default: "none"</li>
<li>Type: "all", "none", or "root"</li>
</ul>
<p>Limits the ability for npm to fetch dependencies from urls. That is,
@@ -357,6 +362,12 @@ dependencies that point to a tarball url instead of a version or semver
range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.</p>
+<p>As of npm 12 the default is <code>none</code>. Tarballs that share a hostname with the
+configured registry (the typical case for the npm registry, GitHub Packages,
+and most private registries) are still installed normally. If your registry
+serves tarballs from a different host, set <code>replace-registry-host</code> or
+override this setting. Opt in explicitly per project (in <code>.npmrc</code>) or per
+command (on the CLI) when you intentionally install from a URL.</p>
<p><code>all</code> allows any url to be installed. <code>none</code> prevents any url from being
installed. <code>root</code> only allows urls defined in your project's package.json to
be installed. Also allows url dependencies to be used for other commands
@@ -378,16 +389,18 @@ project-scoped <code>npm install</code>, <code>ci</code>, <code>update</code>, o
<p>Each name is matched against a dependency's resolved identity, not against
the package's self-reported name. <code>--ignore-scripts</code> and
<code>--dangerously-allow-all-scripts</code> both override this setting.</p>
+<p>This value is not exported to the environment for child processes.</p>
<h4 id="strict-allow-scripts"><code>strict-allow-scripts</code></h4>
<ul>
<li>Default: false</li>
<li>Type: Boolean</li>
</ul>
<p>If <code>true</code>, turn the install-script policy from a warning into a hard error:
-any dependency with install scripts not covered by <code>allowScripts</code> will fail
-the install instead of running with a notice.</p>
+any dependency with install scripts that is not covered by <code>allowScripts</code>
+will fail the install instead of being blocked with a warning.</p>
<p>Dependencies explicitly denied with <code>false</code> in <code>allowScripts</code> are always
-silently skipped; this setting only affects unreviewed entries.
+silently skipped; this setting only affects unreviewed entries (packages
+with install scripts that are neither approved nor denied).
<code>--ignore-scripts</code> and <code>--dangerously-allow-all-scripts</code> both override this
setting.</p>
<p>Optional dependencies that cannot be installed on the current platform or
diff --git a/deps/npm/docs/output/commands/npm-install-scripts.html b/deps/npm/docs/output/commands/npm-install-scripts.html
index 8174e90a509..5060355e377 100644
--- a/deps/npm/docs/output/commands/npm-install-scripts.html
+++ b/deps/npm/docs/output/commands/npm-install-scripts.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-install-scripts----11191">
+<h1 id="----npm-install-scripts----1210">
<span>npm-install-scripts</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Manage install-script approvals for dependencies</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-install-test.html b/deps/npm/docs/output/commands/npm-install-test.html
index e75fb52d323..119d6f406c8 100644
--- a/deps/npm/docs/output/commands/npm-install-test.html
+++ b/deps/npm/docs/output/commands/npm-install-test.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-install-test----11191">
+<h1 id="----npm-install-test----1210">
<span>npm-install-test</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Install package(s) and run tests</span>
</header>
@@ -283,8 +283,7 @@ on deeper dependencies. Sets <code>--install-strategy=shallow</code>.</p>
</ul>
<p>Dependency types to omit from the installation tree on disk.</p>
<p>Note that these dependencies <em>are</em> still resolved and added to the
-<code>package-lock.json</code> or <code>npm-shrinkwrap.json</code> file. They are just not
-physically installed on disk.</p>
+<code>package-lock.json</code> file. They are just not physically installed on disk.</p>
<p>If a package type appears in both the <code>--include</code> and <code>--omit</code> lists, then
it will be included.</p>
<p>If the resulting omit list includes <code>'dev'</code>, then the <code>NODE_ENV</code> environment
@@ -360,6 +359,8 @@ but can be useful for debugging.</p>
<code>npm start</code>, <code>npm stop</code>, <code>npm restart</code>, <code>npm test</code>, and <code>npm run</code> will still
run their intended script if <code>ignore-scripts</code> is set, but they will <em>not</em>
run any pre- or post-scripts.</p>
+<p>Setting <code>ignore-scripts</code> also disables <code>.npm-extension</code> execution, as if
+<code>ignore-extension</code> were set.</p>
<h4 id="allow-directory"><code>allow-directory</code></h4>
<ul>
<li>Default: "all"</li>
@@ -390,7 +391,7 @@ project's package.json to be installed. Also allows tarball file
dependencies to be used for other commands like <code>npm view</code></p>
<h4 id="allow-git"><code>allow-git</code></h4>
<ul>
-<li>Default: "all"</li>
+<li>Default: "none"</li>
<li>Type: "all", "none", or "root"</li>
</ul>
<p>Limits the ability for npm to fetch dependencies from git references. That
@@ -398,6 +399,10 @@ is, dependencies that point to a git repo instead of a version or semver
range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.</p>
+<p>As of npm 12 the default is <code>none</code>. Git dependencies run <code>git</code> against a
+remote repo and may install configuration the project does not control. Opt
+in explicitly per project (in <code>.npmrc</code>) or per command (on the CLI) when you
+need git deps.</p>
<p><code>all</code> allows any git dependencies to be fetched and installed. <code>none</code>
prevents any git dependencies from being fetched and installed. <code>root</code> only
allows git dependencies defined in your project's package.json to be fetched
@@ -405,7 +410,7 @@ and installed. Also allows git dependencies to be fetched for other commands
like <code>npm view</code></p>
<h4 id="allow-remote"><code>allow-remote</code></h4>
<ul>
-<li>Default: "all"</li>
+<li>Default: "none"</li>
<li>Type: "all", "none", or "root"</li>
</ul>
<p>Limits the ability for npm to fetch dependencies from urls. That is,
@@ -413,6 +418,12 @@ dependencies that point to a tarball url instead of a version or semver
range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.</p>
+<p>As of npm 12 the default is <code>none</code>. Tarballs that share a hostname with the
+configured registry (the typical case for the npm registry, GitHub Packages,
+and most private registries) are still installed normally. If your registry
+serves tarballs from a different host, set <code>replace-registry-host</code> or
+override this setting. Opt in explicitly per project (in <code>.npmrc</code>) or per
+command (on the CLI) when you intentionally install from a URL.</p>
<p><code>all</code> allows any url to be installed. <code>none</code> prevents any url from being
installed. <code>root</code> only allows urls defined in your project's package.json to
be installed. Also allows url dependencies to be used for other commands
@@ -434,16 +445,18 @@ project-scoped <code>npm install</code>, <code>ci</code>, <code>update</code>, o
<p>Each name is matched against a dependency's resolved identity, not against
the package's self-reported name. <code>--ignore-scripts</code> and
<code>--dangerously-allow-all-scripts</code> both override this setting.</p>
+<p>This value is not exported to the environment for child processes.</p>
<h4 id="strict-allow-scripts"><code>strict-allow-scripts</code></h4>
<ul>
<li>Default: false</li>
<li>Type: Boolean</li>
</ul>
<p>If <code>true</code>, turn the install-script policy from a warning into a hard error:
-any dependency with install scripts not covered by <code>allowScripts</code> will fail
-the install instead of running with a notice.</p>
+any dependency with install scripts that is not covered by <code>allowScripts</code>
+will fail the install instead of being blocked with a warning.</p>
<p>Dependencies explicitly denied with <code>false</code> in <code>allowScripts</code> are always
-silently skipped; this setting only affects unreviewed entries.
+silently skipped; this setting only affects unreviewed entries (packages
+with install scripts that are neither approved nor denied).
<code>--ignore-scripts</code> and <code>--dangerously-allow-all-scripts</code> both override this
setting.</p>
<p>Optional dependencies that cannot be installed on the current platform or
diff --git a/deps/npm/docs/output/commands/npm-install.html b/deps/npm/docs/output/commands/npm-install.html
index ed78f6576bb..cb348fd03d8 100644
--- a/deps/npm/docs/output/commands/npm-install.html
+++ b/deps/npm/docs/output/commands/npm-install.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-install----11191">
+<h1 id="----npm-install----1210">
<span>npm-install</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Install a package</span>
</header>
@@ -205,13 +205,12 @@ aliases: add, i, in, ins, inst, insta, instal, isnt, isnta, isntal, isntall
</code></pre>
<h3 id="description">Description</h3>
<p>This command installs a package and any packages that it depends on.
-If the package has a package-lock, or an npm shrinkwrap file, or a yarn lock file, the installation of dependencies will be driven by that, respecting the following order of precedence:</p>
+If the package has a package-lock or a yarn lock file, the installation of dependencies will be driven by that, respecting the following order of precedence:</p>
<ul>
-<li><code>npm-shrinkwrap.json</code></li>
<li><code>package-lock.json</code></li>
<li><code>yarn.lock</code></li>
</ul>
-<p>See <a href="../configuring-npm/package-lock-json.html">package-lock.json</a> and <a href="../commands/npm-shrinkwrap.html"><code>npm shrinkwrap</code></a>.</p>
+<p>See <a href="../configuring-npm/package-lock-json.html">package-lock.json</a>.</p>
<h4 id="how-npm-install-uses-package-lockjson">How <code>npm install</code> uses <code>package-lock.json</code></h4>
<p>When you run <code>npm install</code> without arguments, npm compares <code>package.json</code> and <code>package-lock.json</code>:</p>
<ul>
@@ -322,7 +321,7 @@ This is the default unless <code>-D</code> or <code>-O</code> are present.</p>
<p><code>-B, --save-bundle</code>: Saved dependencies will also be added to your <code>bundleDependencies</code> list.</p>
</li>
</ul>
-<p>Further, if you have an <code>npm-shrinkwrap.json</code> or <code>package-lock.json</code> then it will be updated as well.</p>
+<p>Further, if you have a <code>package-lock.json</code> then it will be updated as well.</p>
<p><code><scope></code> is optional.
The package will be downloaded from the registry associated with the specified scope.
If no registry is associated with the given scope the default registry is assumed.
@@ -558,8 +557,7 @@ on deeper dependencies. Sets <code>--install-strategy=shallow</code>.</p>
</ul>
<p>Dependency types to omit from the installation tree on disk.</p>
<p>Note that these dependencies <em>are</em> still resolved and added to the
-<code>package-lock.json</code> or <code>npm-shrinkwrap.json</code> file. They are just not
-physically installed on disk.</p>
+<code>package-lock.json</code> file. They are just not physically installed on disk.</p>
<p>If a package type appears in both the <code>--include</code> and <code>--omit</code> lists, then
it will be included.</p>
<p>If the resulting omit list includes <code>'dev'</code>, then the <code>NODE_ENV</code> environment
@@ -635,6 +633,8 @@ but can be useful for debugging.</p>
<code>npm start</code>, <code>npm stop</code>, <code>npm restart</code>, <code>npm test</code>, and <code>npm run</code> will still
run their intended script if <code>ignore-scripts</code> is set, but they will <em>not</em>
run any pre- or post-scripts.</p>
+<p>Setting <code>ignore-scripts</code> also disables <code>.npm-extension</code> execution, as if
+<code>ignore-extension</code> were set.</p>
<h4 id="allow-directory"><code>allow-directory</code></h4>
<ul>
<li>Default: "all"</li>
@@ -665,7 +665,7 @@ project's package.json to be installed. Also allows tarball file
dependencies to be used for other commands like <code>npm view</code></p>
<h4 id="allow-git"><code>allow-git</code></h4>
<ul>
-<li>Default: "all"</li>
+<li>Default: "none"</li>
<li>Type: "all", "none", or "root"</li>
</ul>
<p>Limits the ability for npm to fetch dependencies from git references. That
@@ -673,6 +673,10 @@ is, dependencies that point to a git repo instead of a version or semver
range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.</p>
+<p>As of npm 12 the default is <code>none</code>. Git dependencies run <code>git</code> against a
+remote repo and may install configuration the project does not control. Opt
+in explicitly per project (in <code>.npmrc</code>) or per command (on the CLI) when you
+need git deps.</p>
<p><code>all</code> allows any git dependencies to be fetched and installed. <code>none</code>
prevents any git dependencies from being fetched and installed. <code>root</code> only
allows git dependencies defined in your project's package.json to be fetched
@@ -680,7 +684,7 @@ and installed. Also allows git dependencies to be fetched for other commands
like <code>npm view</code></p>
<h4 id="allow-remote"><code>allow-remote</code></h4>
<ul>
-<li>Default: "all"</li>
+<li>Default: "none"</li>
<li>Type: "all", "none", or "root"</li>
</ul>
<p>Limits the ability for npm to fetch dependencies from urls. That is,
@@ -688,6 +692,12 @@ dependencies that point to a tarball url instead of a version or semver
range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.</p>
+<p>As of npm 12 the default is <code>none</code>. Tarballs that share a hostname with the
+configured registry (the typical case for the npm registry, GitHub Packages,
+and most private registries) are still installed normally. If your registry
+serves tarballs from a different host, set <code>replace-registry-host</code> or
+override this setting. Opt in explicitly per project (in <code>.npmrc</code>) or per
+command (on the CLI) when you intentionally install from a URL.</p>
<p><code>all</code> allows any url to be installed. <code>none</code> prevents any url from being
installed. <code>root</code> only allows urls defined in your project's package.json to
be installed. Also allows url dependencies to be used for other commands
@@ -709,16 +719,18 @@ project-scoped <code>npm install</code>, <code>ci</code>, <code>update</code>, o
<p>Each name is matched against a dependency's resolved identity, not against
the package's self-reported name. <code>--ignore-scripts</code> and
<code>--dangerously-allow-all-scripts</code> both override this setting.</p>
+<p>This value is not exported to the environment for child processes.</p>
<h4 id="strict-allow-scripts"><code>strict-allow-scripts</code></h4>
<ul>
<li>Default: false</li>
<li>Type: Boolean</li>
</ul>
<p>If <code>true</code>, turn the install-script policy from a warning into a hard error:
-any dependency with install scripts not covered by <code>allowScripts</code> will fail
-the install instead of running with a notice.</p>
+any dependency with install scripts that is not covered by <code>allowScripts</code>
+will fail the install instead of being blocked with a warning.</p>
<p>Dependencies explicitly denied with <code>false</code> in <code>allowScripts</code> are always
-silently skipped; this setting only affects unreviewed entries.
+silently skipped; this setting only affects unreviewed entries (packages
+with install scripts that are neither approved nor denied).
<code>--ignore-scripts</code> and <code>--dangerously-allow-all-scripts</code> both override this
setting.</p>
<p>Optional dependencies that cannot be installed on the current platform or
@@ -943,7 +955,6 @@ This algorithm is deterministic, but different trees may be produced if two depe
<li><a href="../using-npm/registry.html">npm registry</a></li>
<li><a href="../commands/npm-dist-tag.html">npm dist-tag</a></li>
<li><a href="../commands/npm-uninstall.html">npm uninstall</a></li>
-<li><a href="../commands/npm-shrinkwrap.html">npm shrinkwrap</a></li>
<li><a href="../configuring-npm/package-json.html">package.json</a></li>
<li><a href="../using-npm/workspaces.html">workspaces</a></li>
</ul></div>
diff --git a/deps/npm/docs/output/commands/npm-link.html b/deps/npm/docs/output/commands/npm-link.html
index aa01ff7a259..14648f939fd 100644
--- a/deps/npm/docs/output/commands/npm-link.html
+++ b/deps/npm/docs/output/commands/npm-link.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-link----11191">
+<h1 id="----npm-link----1210">
<span>npm-link</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Symlink a package folder</span>
</header>
@@ -348,8 +348,7 @@ will also prevent <em>writing</em> <code>package-lock.json</code> if <code>save<
</ul>
<p>Dependency types to omit from the installation tree on disk.</p>
<p>Note that these dependencies <em>are</em> still resolved and added to the
-<code>package-lock.json</code> or <code>npm-shrinkwrap.json</code> file. They are just not
-physically installed on disk.</p>
+<code>package-lock.json</code> file. They are just not physically installed on disk.</p>
<p>If a package type appears in both the <code>--include</code> and <code>--omit</code> lists, then
it will be included.</p>
<p>If the resulting omit list includes <code>'dev'</code>, then the <code>NODE_ENV</code> environment
@@ -373,6 +372,8 @@ the order in which omit/include are specified on the command-line.</p>
<code>npm start</code>, <code>npm stop</code>, <code>npm restart</code>, <code>npm test</code>, and <code>npm run</code> will still
run their intended script if <code>ignore-scripts</code> is set, but they will <em>not</em>
run any pre- or post-scripts.</p>
+<p>Setting <code>ignore-scripts</code> also disables <code>.npm-extension</code> execution, as if
+<code>ignore-extension</code> were set.</p>
<h4 id="allow-directory"><code>allow-directory</code></h4>
<ul>
<li>Default: "all"</li>
@@ -403,7 +404,7 @@ project's package.json to be installed. Also allows tarball file
dependencies to be used for other commands like <code>npm view</code></p>
<h4 id="allow-git"><code>allow-git</code></h4>
<ul>
-<li>Default: "all"</li>
+<li>Default: "none"</li>
<li>Type: "all", "none", or "root"</li>
</ul>
<p>Limits the ability for npm to fetch dependencies from git references. That
@@ -411,6 +412,10 @@ is, dependencies that point to a git repo instead of a version or semver
range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.</p>
+<p>As of npm 12 the default is <code>none</code>. Git dependencies run <code>git</code> against a
+remote repo and may install configuration the project does not control. Opt
+in explicitly per project (in <code>.npmrc</code>) or per command (on the CLI) when you
+need git deps.</p>
<p><code>all</code> allows any git dependencies to be fetched and installed. <code>none</code>
prevents any git dependencies from being fetched and installed. <code>root</code> only
allows git dependencies defined in your project's package.json to be fetched
@@ -418,7 +423,7 @@ and installed. Also allows git dependencies to be fetched for other commands
like <code>npm view</code></p>
<h4 id="allow-remote"><code>allow-remote</code></h4>
<ul>
-<li>Default: "all"</li>
+<li>Default: "none"</li>
<li>Type: "all", "none", or "root"</li>
</ul>
<p>Limits the ability for npm to fetch dependencies from urls. That is,
@@ -426,6 +431,12 @@ dependencies that point to a tarball url instead of a version or semver
range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.</p>
+<p>As of npm 12 the default is <code>none</code>. Tarballs that share a hostname with the
+configured registry (the typical case for the npm registry, GitHub Packages,
+and most private registries) are still installed normally. If your registry
+serves tarballs from a different host, set <code>replace-registry-host</code> or
+override this setting. Opt in explicitly per project (in <code>.npmrc</code>) or per
+command (on the CLI) when you intentionally install from a URL.</p>
<p><code>all</code> allows any url to be installed. <code>none</code> prevents any url from being
installed. <code>root</code> only allows urls defined in your project's package.json to
be installed. Also allows url dependencies to be used for other commands
diff --git a/deps/npm/docs/output/commands/npm-ll.html b/deps/npm/docs/output/commands/npm-ll.html
index f8df2515bfa..edaa98e8843 100644
--- a/deps/npm/docs/output/commands/npm-ll.html
+++ b/deps/npm/docs/output/commands/npm-ll.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-ll----11191">
+<h1 id="----npm-ll----1210">
<span>npm-ll</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">List installed packages</span>
</header>
@@ -269,8 +269,7 @@ project. If <code>--all</code> is set, then npm will show all dependencies by de
</ul>
<p>Dependency types to omit from the installation tree on disk.</p>
<p>Note that these dependencies <em>are</em> still resolved and added to the
-<code>package-lock.json</code> or <code>npm-shrinkwrap.json</code> file. They are just not
-physically installed on disk.</p>
+<code>package-lock.json</code> file. They are just not physically installed on disk.</p>
<p>If a package type appears in both the <code>--include</code> and <code>--omit</code> lists, then
it will be included.</p>
<p>If the resulting omit list includes <code>'dev'</code>, then the <code>NODE_ENV</code> environment
diff --git a/deps/npm/docs/output/commands/npm-login.html b/deps/npm/docs/output/commands/npm-login.html
index 1c6d938ec6c..30dca5d0862 100644
--- a/deps/npm/docs/output/commands/npm-login.html
+++ b/deps/npm/docs/output/commands/npm-login.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-login----11191">
+<h1 id="----npm-login----1210">
<span>npm-login</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Login to a registry user account</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-logout.html b/deps/npm/docs/output/commands/npm-logout.html
index cf319a086f8..b88deae7077 100644
--- a/deps/npm/docs/output/commands/npm-logout.html
+++ b/deps/npm/docs/output/commands/npm-logout.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-logout----11191">
+<h1 id="----npm-logout----1210">
<span>npm-logout</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Log out of the registry</span>
</header>
@@ -238,7 +238,7 @@ npm init --scope=@foo --yes
</code></pre>
<h3 id="see-also">See Also</h3>
<ul>
-<li><a href="../commands/npm-adduser.html">npm adduser</a></li>
+<li><a href="../commands/npm-login.html">npm login</a></li>
<li><a href="../using-npm/registry.html">npm registry</a></li>
<li><a href="../commands/npm-config.html">npm config</a></li>
<li><a href="../commands/npm-whoami.html">npm whoami</a></li>
diff --git a/deps/npm/docs/output/commands/npm-ls.html b/deps/npm/docs/output/commands/npm-ls.html
index b733762be37..4b65c5e8636 100644
--- a/deps/npm/docs/output/commands/npm-ls.html
+++ b/deps/npm/docs/output/commands/npm-ls.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-ls----11191">
+<h1 id="----npm-ls----1210">
<span>npm-ls</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">List installed packages</span>
</header>
@@ -209,7 +209,7 @@ alias: list
<p>Positional arguments are <code>name@version-range</code> identifiers, which will limit 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 npm's source tree will show:</p>
-<pre><code class="language-bash">npm@11.19.1 /path/to/npm
+<pre><code class="language-bash">npm@12.1.0 /path/to/npm
└─┬ init-package-json@0.0.4
└── promzard@0.1.5
</code></pre>
@@ -281,8 +281,7 @@ project. If <code>--all</code> is set, then npm will show all dependencies by de
</ul>
<p>Dependency types to omit from the installation tree on disk.</p>
<p>Note that these dependencies <em>are</em> still resolved and added to the
-<code>package-lock.json</code> or <code>npm-shrinkwrap.json</code> file. They are just not
-physically installed on disk.</p>
+<code>package-lock.json</code> file. They are just not physically installed on disk.</p>
<p>If a package type appears in both the <code>--include</code> and <code>--omit</code> lists, then
it will be included.</p>
<p>If the resulting omit list includes <code>'dev'</code>, then the <code>NODE_ENV</code> environment
diff --git a/deps/npm/docs/output/commands/npm-org.html b/deps/npm/docs/output/commands/npm-org.html
index 6a2c22951a6..075e12018f8 100644
--- a/deps/npm/docs/output/commands/npm-org.html
+++ b/deps/npm/docs/output/commands/npm-org.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-org----11191">
+<h1 id="----npm-org----1210">
<span>npm-org</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Manage orgs</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-outdated.html b/deps/npm/docs/output/commands/npm-outdated.html
index b85880371cd..a3045a6ec76 100644
--- a/deps/npm/docs/output/commands/npm-outdated.html
+++ b/deps/npm/docs/output/commands/npm-outdated.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-outdated----11191">
+<h1 id="----npm-outdated----1210">
<span>npm-outdated</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Check for outdated packages</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-owner.html b/deps/npm/docs/output/commands/npm-owner.html
index 6b8afff7ba3..6f2220a9d7e 100644
--- a/deps/npm/docs/output/commands/npm-owner.html
+++ b/deps/npm/docs/output/commands/npm-owner.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-owner----11191">
+<h1 id="----npm-owner----1210">
<span>npm-owner</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Manage package owners</span>
</header>
@@ -276,7 +276,7 @@ other things (test, exec, publish, etc.) will operate on the root project,
<li><a href="../commands/npm-profile.html">npm profile</a></li>
<li><a href="../commands/npm-publish.html">npm publish</a></li>
<li><a href="../using-npm/registry.html">npm registry</a></li>
-<li><a href="../commands/npm-adduser.html">npm adduser</a></li>
+<li><a href="../commands/npm-login.html">npm login</a></li>
</ul></div>
<footer id="edit">
diff --git a/deps/npm/docs/output/commands/npm-pack.html b/deps/npm/docs/output/commands/npm-pack.html
index d7f148d92ed..a58f0d925bf 100644
--- a/deps/npm/docs/output/commands/npm-pack.html
+++ b/deps/npm/docs/output/commands/npm-pack.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-pack----11191">
+<h1 id="----npm-pack----1210">
<span>npm-pack</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Create a tarball from a package</span>
</header>
@@ -285,6 +285,8 @@ the specified workspaces, and not on the root project.</p>
<code>npm start</code>, <code>npm stop</code>, <code>npm restart</code>, <code>npm test</code>, and <code>npm run</code> will still
run their intended script if <code>ignore-scripts</code> is set, but they will <em>not</em>
run any pre- or post-scripts.</p>
+<p>Setting <code>ignore-scripts</code> also disables <code>.npm-extension</code> execution, as if
+<code>ignore-extension</code> were set.</p>
<h3 id="description">Description</h3>
<p>For anything that's installable (that is, a package folder, tarball, tarball url, git url, name@tag, name@version, name, or scoped name), this command will fetch it to the cache, copy the tarball to the current working directory as <code><name>-<version>.tgz</code>, and then write the filenames out to stdout.</p>
<p>If the same package is specified multiple times, then the file will be overwritten the second time.</p>
diff --git a/deps/npm/docs/output/commands/npm-patch.html b/deps/npm/docs/output/commands/npm-patch.html
new file mode 100644
index 00000000000..37e99ca958f
--- /dev/null
+++ b/deps/npm/docs/output/commands/npm-patch.html
@@ -0,0 +1,335 @@
+<!DOCTYPE html><html><head>
+<meta charset="utf-8">
+<title>npm-patch</title>
+<style>
+body {
+ background-color: #ffffff;
+ color: #24292e;
+
+ margin: 0;
+
+ line-height: 1.5;
+
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
+}
+#rainbar {
+ height: 10px;
+ background-image: linear-gradient(139deg, #fb8817, #ff4b01, #c12127, #e02aff);
+}
+
+a {
+ text-decoration: none;
+ color: #0366d6;
+}
+a:hover {
+ text-decoration: underline;
+}
+
+pre {
+ margin: 1em 0px;
+ padding: 1em;
+ border: solid 1px #e1e4e8;
+ border-radius: 6px;
+
+ display: block;
+ overflow: auto;
+
+ white-space: pre;
+
+ background-color: #f6f8fa;
+ color: #393a34;
+}
+code {
+ font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace;
+ font-size: 85%;
+ padding: 0.2em 0.4em;
+ background-color: #f6f8fa;
+ color: #393a34;
+}
+pre > code {
+ padding: 0;
+ background-color: inherit;
+ color: inherit;
+}
+h1, h2, h3 {
+ font-weight: 600;
+}
+
+#logobar {
+ background-color: #333333;
+ margin: 0 auto;
+ padding: 1em 4em;
+}
+#logobar .logo {
+ float: left;
+}
+#logobar .title {
+ font-weight: 600;
+ color: #dddddd;
+ float: left;
+ margin: 5px 0 0 1em;
+}
+#logobar:after {
+ content: "";
+ display: block;
+ clear: both;
+}
+
+#content {
+ margin: 0 auto;
+ padding: 0 4em;
+}
+
+#table_of_contents > h2 {
+ font-size: 1.17em;
+}
+#table_of_contents ul:first-child {
+ border: solid 1px #e1e4e8;
+ border-radius: 6px;
+ padding: 1em;
+ background-color: #f6f8fa;
+ color: #393a34;
+}
+#table_of_contents ul {
+ list-style-type: none;
+ padding-left: 1.5em;
+}
+#table_of_contents li {
+ font-size: 0.9em;
+}
+#table_of_contents li a {
+ color: #000000;
+}
+
+header.title {
+ border-bottom: solid 1px #e1e4e8;
+}
+header.title > h1 {
+ margin-bottom: 0.25em;
+}
+header.title > .description {
+ display: block;
+ margin-bottom: 0.5em;
+ line-height: 1;
+}
+
+header.title .version {
+ font-size: 0.8em;
+ color: #666666;
+}
+
+footer#edit {
+ border-top: solid 1px #e1e4e8;
+ margin: 3em 0 4em 0;
+ padding-top: 2em;
+}
+
+table {
+ width: 100%;
+ margin: 1em 0;
+ border-radius: 6px;
+ border: 1px solid #e1e4e8;
+ overflow: hidden;
+ border-collapse: separate;
+ border-spacing: 0;
+}
+
+table thead {
+ background-color: #f6f8fa;
+}
+
+table tbody {
+ background-color: #ffffff;
+}
+
+table th,
+table td {
+ padding: 0.75em;
+ text-align: left;
+ border-right: 1px solid #e1e4e8;
+ border-bottom: 1px solid #e1e4e8;
+}
+
+table th:last-child,
+table td:last-child {
+ border-right: none;
+}
+
+table tbody tr:last-child td {
+ border-bottom: none;
+}
+
+table th {
+ font-weight: 600;
+ background-color: #f6f8fa;
+}
+
+table code {
+ white-space: nowrap;
+}
+
+</style>
+</head>
+<body>
+<div id="banner">
+<div id="rainbar"></div>
+<div id="logobar">
+<svg class="logo" role="img" height="32" width="32" viewBox="0 0 700 700">
+<polygon fill="#cb0000" points="0,700 700,700 700,0 0,0"></polygon>
+<polygon fill="#ffffff" points="150,550 350,550 350,250 450,250 450,550 550,550 550,150 150,150"></polygon>
+</svg>
+<div class="title">
+npm command-line interface
+</div>
+</div>
+</div>
+
+<section id="content">
+<header class="title">
+<h1 id="----npm-patch----1210">
+ <span>npm-patch</span>
+ <span class="version">@12.1.0</span>
+</h1>
+<span class="description">Apply local patches to installed dependencies</span>
+</header>
+
+<section id="table_of_contents">
+<h2 id="table-of-contents">Table of contents</h2>
+<div id="_table_of_contents"><ul><li><a href="#see-also">See Also</a></li></ul></div>
+</section>
+
+<div id="_content"><h3 id="synopsis">Synopsis</h3>
+<pre><code class="language-bash">npm patch <pkg>[@<version>]
+npm patch add <pkg>[@<version>] [--edit-dir <path>] [--ignore-existing]
+npm patch commit <edit-dir> [--patches-dir <dir>] [--keep-edit-dir]
+npm patch update <pkg>[@<old-version>] [--to <new-version>] [--patches-dir <dir>]
+npm patch ls
+npm patch rm <pkg>[@<version>]
+</code></pre>
+<p>Note: This command is unaware of workspaces.</p>
+<h3 id="description">Description</h3>
+<p><code>npm patch</code> lets you apply small, local modifications to an installed
+dependency and have them re-applied automatically on every install. Patches
+are declared in the <code>patchedDependencies</code> field of your root <code>package.json</code>,
+stored as plain unified diffs under the <code>patches/</code> directory, and recorded with
+a content hash in <code>package-lock.json</code>.</p>
+<p>Because patches are applied during the install itself, they work regardless of
+<code>install-strategy</code>, apply to transitive dependencies, and are <strong>not</strong> disabled
+by <code>--ignore-scripts</code>.</p>
+<p>The bare form <code>npm patch <pkg></code> is shorthand for <code>npm patch add <pkg></code>. A
+package literally named like a subcommand must use the explicit form, e.g.
+<code>npm patch add add</code>.</p>
+<ul>
+<li>
+<p><code>npm patch add <pkg>[@<version>]</code></p>
+<p>Prepares a package for editing. npm extracts a clean copy of the resolved
+package tarball into a temporary directory outside <code>node_modules</code> and prints
+its path. Edit the files there, then run <code>npm patch commit</code>.</p>
+<p>If more than one version of <code><pkg></code> is installed, re-run with an exact
+selector such as <code>npm patch add lodash@4.17.21</code>.</p>
+</li>
+<li>
+<p><code>npm patch commit <edit-dir></code></p>
+<p>Diffs the edited directory against a clean copy of the original tarball,
+writes the unified diff to <code><patches-dir>/<name>@<version>.patch</code>, adds the
+entry to <code>patchedDependencies</code>, and updates <code>package-lock.json</code>.</p>
+</li>
+<li>
+<p><code>npm patch ls</code></p>
+<p>Lists registered patches and how many installed nodes each one matches.</p>
+</li>
+<li>
+<p><code>npm patch rm <pkg>[@<version>]</code></p>
+<p>Removes the matching entries from <code>patchedDependencies</code>, deletes the patch
+file when no other entry references it, and updates <code>package-lock.json</code>. If
+<code><version></code> is omitted, all entries for <code><pkg></code> are removed.</p>
+</li>
+</ul>
+<h3 id="failure-modes">Failure modes</h3>
+<p>By default any patch problem is a hard error that aborts the install: a patch
+that fails to apply, a registered patch that matches no installed package, a
+missing patch file, or a patch whose hash does not match the lockfile.</p>
+<p>Two CLI-only flags relax this for one-off cases: <code>--allow-unused-patches</code> and
+<code>--ignore-patch-failures</code>.</p>
+<h3 id="configuration">Configuration</h3>
+<h4 id="patches-dir"><code>patches-dir</code></h4>
+<ul>
+<li>Default: "patches"</li>
+<li>Type: String</li>
+</ul>
+<p>The directory, relative to the project root, where <code>npm patch commit</code> writes
+patch files for <code>patchedDependencies</code>.</p>
+<h4 id="allow-unused-patches"><code>allow-unused-patches</code></h4>
+<ul>
+<li>Default: false</li>
+<li>Type: Boolean</li>
+</ul>
+<p>Install even when a registered patch in <code>patchedDependencies</code> matches no
+installed package. Does not silence patch apply failures.</p>
+<p>This flag is only honored when passed on the command line; it is ignored in
+<code>.npmrc</code> and environment variables, and rejected by <code>npm ci</code>.</p>
+<h4 id="ignore-patch-failures"><code>ignore-patch-failures</code></h4>
+<ul>
+<li>Default: false</li>
+<li>Type: Boolean</li>
+</ul>
+<p>Install even when a registered patch fails to apply, with a warning per
+failure. Intended for incident response only.</p>
+<p>This flag is only honored when passed on the command line; it is ignored in
+<code>.npmrc</code> and environment variables, and rejected by <code>npm ci</code>.</p>
+<h4 id="edit-dir"><code>edit-dir</code></h4>
+<ul>
+<li>Default: null</li>
+<li>Type: null or Path</li>
+</ul>
+<p>Override the temporary directory used by <code>npm patch add</code> to prepare a
+package for editing.</p>
+<h4 id="ignore-existing"><code>ignore-existing</code></h4>
+<ul>
+<li>Default: false</li>
+<li>Type: Boolean</li>
+</ul>
+<p>With <code>npm patch add</code>, discard a previous unfinished edit directory and start
+fresh.</p>
+<h4 id="keep-edit-dir"><code>keep-edit-dir</code></h4>
+<ul>
+<li>Default: false</li>
+<li>Type: Boolean</li>
+</ul>
+<p>With <code>npm patch commit</code>, do not remove the edit directory after committing
+the patch.</p>
+<h4 id="to"><code>to</code></h4>
+<ul>
+<li>Default: null</li>
+<li>Type: null or String</li>
+</ul>
+<p>Used by <code>npm patch update</code> to set the version to rebase a patch onto when it
+cannot be read from <code>package-lock.json</code> — for example an exact-version
+selector, or a version that has not been installed yet.</p>
+<h4 id="registry"><code>registry</code></h4>
+<ul>
+<li>Default: "<a href="https://registry.npmjs.org/">https://registry.npmjs.org/</a>"</li>
+<li>Type: URL</li>
+</ul>
+<p>The base URL of the npm registry.</p>
+<h2 id="see-also">See Also</h2>
+<ul>
+<li><a href="../commands/npm-install.html">npm install</a></li>
+<li><a href="../commands/npm-ci.html">npm ci</a></li>
+<li><a href="../configuring-npm/package-lock-json.html">package-lock.json</a></li>
+<li><a href="../commands/npm-config.html">config</a></li>
+</ul></div>
+
+<footer id="edit">
+<a href="https://github.com/npm/cli/edit/latest/docs/lib/content/commands/npm-patch.md">
+<svg role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentcolor" style="vertical-align: text-bottom; margin-right: 0.3em;">
+<path fill-rule="evenodd" d="M11.013 1.427a1.75 1.75 0 012.474 0l1.086 1.086a1.75 1.75 0 010 2.474l-8.61 8.61c-.21.21-.47.364-.756.445l-3.251.93a.75.75 0 01-.927-.928l.929-3.25a1.75 1.75 0 01.445-.758l8.61-8.61zm1.414 1.06a.25.25 0 00-.354 0L10.811 3.75l1.439 1.44 1.263-1.263a.25.25 0 000-.354l-1.086-1.086zM11.189 6.25L9.75 4.81l-6.286 6.287a.25.25 0 00-.064.108l-.558 1.953 1.953-.558a.249.249 0 00.108-.064l6.286-6.286z"></path>
+</svg>
+Edit this page on GitHub
+</a>
+</footer>
+</section>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/deps/npm/docs/output/commands/npm-ping.html b/deps/npm/docs/output/commands/npm-ping.html
index 3c49a071316..cd16085a33f 100644
--- a/deps/npm/docs/output/commands/npm-ping.html
+++ b/deps/npm/docs/output/commands/npm-ping.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-ping----11191">
+<h1 id="----npm-ping----1210">
<span>npm-ping</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Ping npm registry</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-pkg.html b/deps/npm/docs/output/commands/npm-pkg.html
index d80ac21f9af..c0370531f9e 100644
--- a/deps/npm/docs/output/commands/npm-pkg.html
+++ b/deps/npm/docs/output/commands/npm-pkg.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-pkg----11191">
+<h1 id="----npm-pkg----1210">
<span>npm-pkg</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Manages your package.json</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-prefix.html b/deps/npm/docs/output/commands/npm-prefix.html
index 1592a1d3048..be2b1f263c5 100644
--- a/deps/npm/docs/output/commands/npm-prefix.html
+++ b/deps/npm/docs/output/commands/npm-prefix.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-prefix----11191">
+<h1 id="----npm-prefix----1210">
<span>npm-prefix</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Display prefix</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-profile.html b/deps/npm/docs/output/commands/npm-profile.html
index 24f5db6d7f3..9965a851aec 100644
--- a/deps/npm/docs/output/commands/npm-profile.html
+++ b/deps/npm/docs/output/commands/npm-profile.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-profile----11191">
+<h1 id="----npm-profile----1210">
<span>npm-profile</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Change settings on your registry profile</span>
</header>
@@ -217,8 +217,6 @@ email: e@example.com (verified)
two-factor auth: auth-and-writes
fullname: Example User
homepage:
-freenode:
-twitter:
github:
created: 2015-02-26T01:38:35.892Z
updated: 2017-10-02T21:29:45.922Z
@@ -226,7 +224,7 @@ updated: 2017-10-02T21:29:45.922Z
<ul>
<li>
<p><code>npm profile set <property> <value></code>: Set the value of a profile property.
-You can set the following properties this way: email, fullname, homepage, freenode, twitter, github</p>
+You can set the following properties this way: email, fullname, homepage, github</p>
</li>
<li>
<p><code>npm profile set password</code>: Change your password.
@@ -285,7 +283,7 @@ when publishing or changing package permissions with <code>npm access</code>.</p
password, npm will prompt on the command line for one.</p>
<h3 id="see-also">See Also</h3>
<ul>
-<li><a href="../commands/npm-adduser.html">npm adduser</a></li>
+<li><a href="../commands/npm-login.html">npm login</a></li>
<li><a href="../using-npm/registry.html">npm registry</a></li>
<li><a href="../commands/npm-config.html">npm config</a></li>
<li><a href="../configuring-npm/npmrc.html">npmrc</a></li>
diff --git a/deps/npm/docs/output/commands/npm-prune.html b/deps/npm/docs/output/commands/npm-prune.html
index 736620c0a24..2a029255b86 100644
--- a/deps/npm/docs/output/commands/npm-prune.html
+++ b/deps/npm/docs/output/commands/npm-prune.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-prune----11191">
+<h1 id="----npm-prune----1210">
<span>npm-prune</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Remove extraneous packages</span>
</header>
@@ -219,8 +219,7 @@ However, in the real world, operation is not always "normal". When crashes or m
</ul>
<p>Dependency types to omit from the installation tree on disk.</p>
<p>Note that these dependencies <em>are</em> still resolved and added to the
-<code>package-lock.json</code> or <code>npm-shrinkwrap.json</code> file. They are just not
-physically installed on disk.</p>
+<code>package-lock.json</code> file. They are just not physically installed on disk.</p>
<p>If a package type appears in both the <code>--include</code> and <code>--omit</code> lists, then
it will be included.</p>
<p>If the resulting omit list includes <code>'dev'</code>, then the <code>NODE_ENV</code> environment
@@ -277,6 +276,8 @@ but can be useful for debugging.</p>
<code>npm start</code>, <code>npm stop</code>, <code>npm restart</code>, <code>npm test</code>, and <code>npm run</code> will still
run their intended script if <code>ignore-scripts</code> is set, but they will <em>not</em>
run any pre- or post-scripts.</p>
+<p>Setting <code>ignore-scripts</code> also disables <code>.npm-extension</code> execution, as if
+<code>ignore-extension</code> were set.</p>
<h4 id="workspace"><code>workspace</code></h4>
<ul>
<li>Default:</li>
diff --git a/deps/npm/docs/output/commands/npm-publish.html b/deps/npm/docs/output/commands/npm-publish.html
index a20d56b8d10..5669c4329d4 100644
--- a/deps/npm/docs/output/commands/npm-publish.html
+++ b/deps/npm/docs/output/commands/npm-publish.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-publish----11191">
+<h1 id="----npm-publish----1210">
<span>npm-publish</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Publish a package</span>
</header>
@@ -360,6 +360,8 @@ the specified workspaces, and not on the root project.</p>
</ul>
<p>When publishing from a supported cloud CI/CD system, the package will be
publicly linked to where it was built and published from.</p>
+<p>When the <code>provenance-file</code> config is set, it takes precedence and automatic
+provenance generation (including via trusted publishing/OIDC) is skipped.</p>
<p>This config cannot be used with: <code>provenance-file</code></p>
<h4 id="provenance-file"><code>provenance-file</code></h4>
<ul>
@@ -367,6 +369,8 @@ publicly linked to where it was built and published from.</p>
<li>Type: Path</li>
</ul>
<p>When publishing, the provenance bundle at the given path will be used.</p>
+<p>This takes precedence over automatic provenance generation in trusted
+publishing flows.</p>
<p>This config cannot be used with: <code>provenance</code></p>
<h3 id="see-also">See Also</h3>
<ul>
@@ -374,7 +378,7 @@ publicly linked to where it was built and published from.</p>
<li><a href="http://npm.im/npm-packlist">npm-packlist package</a></li>
<li><a href="../using-npm/registry.html">npm registry</a></li>
<li><a href="../using-npm/scope.html">npm scope</a></li>
-<li><a href="../commands/npm-adduser.html">npm adduser</a></li>
+<li><a href="../commands/npm-login.html">npm login</a></li>
<li><a href="../commands/npm-owner.html">npm owner</a></li>
<li><a href="../commands/npm-deprecate.html">npm deprecate</a></li>
<li><a href="../commands/npm-dist-tag.html">npm dist-tag</a></li>
diff --git a/deps/npm/docs/output/commands/npm-query.html b/deps/npm/docs/output/commands/npm-query.html
index a74342cf278..1cc69249ccd 100644
--- a/deps/npm/docs/output/commands/npm-query.html
+++ b/deps/npm/docs/output/commands/npm-query.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-query----11191">
+<h1 id="----npm-query----1210">
<span>npm-query</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Dependency selector query</span>
</header>
@@ -326,7 +326,7 @@ You can use the <code>--expect-results</code> or <code>--expect-result-count</co
<pre><code class="language-sh">$ npm query ':root>:outdated(in-range).prod' --no-expect-results
</code></pre>
<h3 id="package-lock-only-mode">Package lock only mode</h3>
-<p>If package-lock-only is enabled, only the information in the package lock (or shrinkwrap) is loaded.
+<p>If package-lock-only is enabled, only the information in the package lock is loaded.
This means that information from the package.json files of your dependencies will not be included in the result set (e.g. description, homepage, engines).</p>
<h3 id="configuration">Configuration</h3>
<h4 id="global"><code>global</code></h4>
diff --git a/deps/npm/docs/output/commands/npm-rebuild.html b/deps/npm/docs/output/commands/npm-rebuild.html
index 39403a70941..6752812a8b6 100644
--- a/deps/npm/docs/output/commands/npm-rebuild.html
+++ b/deps/npm/docs/output/commands/npm-rebuild.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-rebuild----11191">
+<h1 id="----npm-rebuild----1210">
<span>npm-rebuild</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Rebuild a package</span>
</header>
@@ -269,6 +269,8 @@ but can be useful for debugging.</p>
<code>npm start</code>, <code>npm stop</code>, <code>npm restart</code>, <code>npm test</code>, and <code>npm run</code> will still
run their intended script if <code>ignore-scripts</code> is set, but they will <em>not</em>
run any pre- or post-scripts.</p>
+<p>Setting <code>ignore-scripts</code> also disables <code>.npm-extension</code> execution, as if
+<code>ignore-extension</code> were set.</p>
<h4 id="allow-scripts"><code>allow-scripts</code></h4>
<ul>
<li>Default: ""</li>
@@ -286,16 +288,18 @@ project-scoped <code>npm install</code>, <code>ci</code>, <code>update</code>, o
<p>Each name is matched against a dependency's resolved identity, not against
the package's self-reported name. <code>--ignore-scripts</code> and
<code>--dangerously-allow-all-scripts</code> both override this setting.</p>
+<p>This value is not exported to the environment for child processes.</p>
<h4 id="strict-allow-scripts"><code>strict-allow-scripts</code></h4>
<ul>
<li>Default: false</li>
<li>Type: Boolean</li>
</ul>
<p>If <code>true</code>, turn the install-script policy from a warning into a hard error:
-any dependency with install scripts not covered by <code>allowScripts</code> will fail
-the install instead of running with a notice.</p>
+any dependency with install scripts that is not covered by <code>allowScripts</code>
+will fail the install instead of being blocked with a warning.</p>
<p>Dependencies explicitly denied with <code>false</code> in <code>allowScripts</code> are always
-silently skipped; this setting only affects unreviewed entries.
+silently skipped; this setting only affects unreviewed entries (packages
+with install scripts that are neither approved nor denied).
<code>--ignore-scripts</code> and <code>--dangerously-allow-all-scripts</code> both override this
setting.</p>
<p>Optional dependencies that cannot be installed on the current platform or
diff --git a/deps/npm/docs/output/commands/npm-repo.html b/deps/npm/docs/output/commands/npm-repo.html
index 5337679c824..9cc209cdb62 100644
--- a/deps/npm/docs/output/commands/npm-repo.html
+++ b/deps/npm/docs/output/commands/npm-repo.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-repo----11191">
+<h1 id="----npm-repo----1210">
<span>npm-repo</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Open package repository page in the browser</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-restart.html b/deps/npm/docs/output/commands/npm-restart.html
index 0786bdc34a5..cf71fecbd44 100644
--- a/deps/npm/docs/output/commands/npm-restart.html
+++ b/deps/npm/docs/output/commands/npm-restart.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-restart----11191">
+<h1 id="----npm-restart----1210">
<span>npm-restart</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Restart a package</span>
</header>
@@ -232,6 +232,8 @@ It is equivalent to running <code>npm run restart</code>.</p>
<code>npm start</code>, <code>npm stop</code>, <code>npm restart</code>, <code>npm test</code>, and <code>npm run</code> will still
run their intended script if <code>ignore-scripts</code> is set, but they will <em>not</em>
run any pre- or post-scripts.</p>
+<p>Setting <code>ignore-scripts</code> also disables <code>.npm-extension</code> execution, as if
+<code>ignore-extension</code> were set.</p>
<h4 id="script-shell"><code>script-shell</code></h4>
<ul>
<li>Default: '/bin/sh' on POSIX systems, 'cmd.exe' on Windows</li>
diff --git a/deps/npm/docs/output/commands/npm-root.html b/deps/npm/docs/output/commands/npm-root.html
index 165223c6fdb..c347f124e45 100644
--- a/deps/npm/docs/output/commands/npm-root.html
+++ b/deps/npm/docs/output/commands/npm-root.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-root----11191">
+<h1 id="----npm-root----1210">
<span>npm-root</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Display npm root</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-run.html b/deps/npm/docs/output/commands/npm-run.html
index 15ca998eb8a..c0cc6c4102d 100644
--- a/deps/npm/docs/output/commands/npm-run.html
+++ b/deps/npm/docs/output/commands/npm-run.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-run----11191">
+<h1 id="----npm-run----1210">
<span>npm-run</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Run arbitrary package scripts</span>
</header>
@@ -333,6 +333,8 @@ CI setup.</p>
<code>npm start</code>, <code>npm stop</code>, <code>npm restart</code>, <code>npm test</code>, and <code>npm run</code> will still
run their intended script if <code>ignore-scripts</code> is set, but they will <em>not</em>
run any pre- or post-scripts.</p>
+<p>Setting <code>ignore-scripts</code> also disables <code>.npm-extension</code> execution, as if
+<code>ignore-extension</code> were set.</p>
<h4 id="foreground-scripts"><code>foreground-scripts</code></h4>
<ul>
<li>Default: <code>false</code> unless when using <code>npm pack</code> or <code>npm publish</code> where it
diff --git a/deps/npm/docs/output/commands/npm-sbom.html b/deps/npm/docs/output/commands/npm-sbom.html
index fe84c36327a..fa5f951401c 100644
--- a/deps/npm/docs/output/commands/npm-sbom.html
+++ b/deps/npm/docs/output/commands/npm-sbom.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-sbom----11191">
+<h1 id="----npm-sbom----1210">
<span>npm-sbom</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Generate a Software Bill of Materials (SBOM)</span>
</header>
@@ -389,7 +389,7 @@ SBOMs can be generated in either <a href="https://spdx.dev/">SPDX</a> or <a href
}
</code></pre>
<h3 id="package-lock-only-mode">Package lock only mode</h3>
-<p>If package-lock-only is enabled, only the information in the package lock (or shrinkwrap) is loaded.
+<p>If package-lock-only is enabled, only the information in the package lock is loaded.
This means that information from the package.json files of your dependencies will not be included in the result set (e.g.
description, homepage, engines).</p>
<h3 id="configuration">Configuration</h3>
@@ -401,8 +401,7 @@ description, homepage, engines).</p>
</ul>
<p>Dependency types to omit from the installation tree on disk.</p>
<p>Note that these dependencies <em>are</em> still resolved and added to the
-<code>package-lock.json</code> or <code>npm-shrinkwrap.json</code> file. They are just not
-physically installed on disk.</p>
+<code>package-lock.json</code> file. They are just not physically installed on disk.</p>
<p>If a package type appears in both the <code>--include</code> and <code>--omit</code> lists, then
it will be included.</p>
<p>If the resulting omit list includes <code>'dev'</code>, then the <code>NODE_ENV</code> environment
diff --git a/deps/npm/docs/output/commands/npm-search.html b/deps/npm/docs/output/commands/npm-search.html
index 98006e7d225..3c1bdd66f9e 100644
--- a/deps/npm/docs/output/commands/npm-search.html
+++ b/deps/npm/docs/output/commands/npm-search.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-search----11191">
+<h1 id="----npm-search----1210">
<span>npm-search</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Search for packages</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-set.html b/deps/npm/docs/output/commands/npm-set.html
index 6202cdf7b3c..c3e4d258187 100644
--- a/deps/npm/docs/output/commands/npm-set.html
+++ b/deps/npm/docs/output/commands/npm-set.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-set----11191">
+<h1 id="----npm-set----1210">
<span>npm-set</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Set a value in the npm configuration</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-shrinkwrap.html b/deps/npm/docs/output/commands/npm-shrinkwrap.html
deleted file mode 100644
index abb9c216e6d..00000000000
--- a/deps/npm/docs/output/commands/npm-shrinkwrap.html
+++ /dev/null
@@ -1,232 +0,0 @@
-<!DOCTYPE html><html><head>
-<meta charset="utf-8">
-<title>npm-shrinkwrap</title>
-<style>
-body {
- background-color: #ffffff;
- color: #24292e;
-
- margin: 0;
-
- line-height: 1.5;
-
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
-}
-#rainbar {
- height: 10px;
- background-image: linear-gradient(139deg, #fb8817, #ff4b01, #c12127, #e02aff);
-}
-
-a {
- text-decoration: none;
- color: #0366d6;
-}
-a:hover {
- text-decoration: underline;
-}
-
-pre {
- margin: 1em 0px;
- padding: 1em;
- border: solid 1px #e1e4e8;
- border-radius: 6px;
-
- display: block;
- overflow: auto;
-
- white-space: pre;
-
- background-color: #f6f8fa;
- color: #393a34;
-}
-code {
- font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace;
- font-size: 85%;
- padding: 0.2em 0.4em;
- background-color: #f6f8fa;
- color: #393a34;
-}
-pre > code {
- padding: 0;
- background-color: inherit;
- color: inherit;
-}
-h1, h2, h3 {
- font-weight: 600;
-}
-
-#logobar {
- background-color: #333333;
- margin: 0 auto;
- padding: 1em 4em;
-}
-#logobar .logo {
- float: left;
-}
-#logobar .title {
- font-weight: 600;
- color: #dddddd;
- float: left;
- margin: 5px 0 0 1em;
-}
-#logobar:after {
- content: "";
- display: block;
- clear: both;
-}
-
-#content {
- margin: 0 auto;
- padding: 0 4em;
-}
-
-#table_of_contents > h2 {
- font-size: 1.17em;
-}
-#table_of_contents ul:first-child {
- border: solid 1px #e1e4e8;
- border-radius: 6px;
- padding: 1em;
- background-color: #f6f8fa;
- color: #393a34;
-}
-#table_of_contents ul {
- list-style-type: none;
- padding-left: 1.5em;
-}
-#table_of_contents li {
- font-size: 0.9em;
-}
-#table_of_contents li a {
- color: #000000;
-}
-
-header.title {
- border-bottom: solid 1px #e1e4e8;
-}
-header.title > h1 {
- margin-bottom: 0.25em;
-}
-header.title > .description {
- display: block;
- margin-bottom: 0.5em;
- line-height: 1;
-}
-
-header.title .version {
- font-size: 0.8em;
- color: #666666;
-}
-
-footer#edit {
- border-top: solid 1px #e1e4e8;
- margin: 3em 0 4em 0;
- padding-top: 2em;
-}
-
-table {
- width: 100%;
- margin: 1em 0;
- border-radius: 6px;
- border: 1px solid #e1e4e8;
- overflow: hidden;
- border-collapse: separate;
- border-spacing: 0;
-}
-
-table thead {
- background-color: #f6f8fa;
-}
-
-table tbody {
- background-color: #ffffff;
-}
-
-table th,
-table td {
- padding: 0.75em;
- text-align: left;
- border-right: 1px solid #e1e4e8;
- border-bottom: 1px solid #e1e4e8;
-}
-
-table th:last-child,
-table td:last-child {
- border-right: none;
-}
-
-table tbody tr:last-child td {
- border-bottom: none;
-}
-
-table th {
- font-weight: 600;
- background-color: #f6f8fa;
-}
-
-table code {
- white-space: nowrap;
-}
-
-</style>
-</head>
-<body>
-<div id="banner">
-<div id="rainbar"></div>
-<div id="logobar">
-<svg class="logo" role="img" height="32" width="32" viewBox="0 0 700 700">
-<polygon fill="#cb0000" points="0,700 700,700 700,0 0,0"></polygon>
-<polygon fill="#ffffff" points="150,550 350,550 350,250 450,250 450,550 550,550 550,150 150,150"></polygon>
-</svg>
-<div class="title">
-npm command-line interface
-</div>
-</div>
-</div>
-
-<section id="content">
-<header class="title">
-<h1 id="----npm-shrinkwrap----11191">
- <span>npm-shrinkwrap</span>
- <span class="version">@11.19.1</span>
-</h1>
-<span class="description">Lock down dependency versions for publication</span>
-</header>
-
-<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="#see-also">See Also</a></li></ul></div>
-</section>
-
-<div id="_content"><h3 id="synopsis">Synopsis</h3>
-<pre><code class="language-bash">npm shrinkwrap
-</code></pre>
-<p>Note: This command is unaware of workspaces.</p>
-<h3 id="description">Description</h3>
-<p>This command repurposes <code>package-lock.json</code> into a publishable <code>npm-shrinkwrap.json</code> or simply creates a new one.
-The file created and updated by this command will then take precedence over any other existing or future <code>package-lock.json</code> files.
-For a detailed explanation of the design and purpose of package locks in npm, see <a href="../configuring-npm/package-lock-json.html">package-lock-json</a>.</p>
-<h3 id="see-also">See Also</h3>
-<ul>
-<li><a href="../commands/npm-install.html">npm install</a></li>
-<li><a href="../commands/npm-run.html">npm run</a></li>
-<li><a href="../using-npm/scripts.html">npm scripts</a></li>
-<li><a href="../configuring-npm/package-json.html">package.json</a></li>
-<li><a href="../configuring-npm/package-lock-json.html">package-lock.json</a></li>
-<li><a href="../configuring-npm/npm-shrinkwrap-json.html">npm-shrinkwrap.json</a></li>
-<li><a href="../commands/npm-ls.html">npm ls</a></li>
-</ul></div>
-
-<footer id="edit">
-<a href="https://github.com/npm/cli/edit/latest/docs/lib/content/commands/npm-shrinkwrap.md">
-<svg role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentcolor" style="vertical-align: text-bottom; margin-right: 0.3em;">
-<path fill-rule="evenodd" d="M11.013 1.427a1.75 1.75 0 012.474 0l1.086 1.086a1.75 1.75 0 010 2.474l-8.61 8.61c-.21.21-.47.364-.756.445l-3.251.93a.75.75 0 01-.927-.928l.929-3.25a1.75 1.75 0 01.445-.758l8.61-8.61zm1.414 1.06a.25.25 0 00-.354 0L10.811 3.75l1.439 1.44 1.263-1.263a.25.25 0 000-.354l-1.086-1.086zM11.189 6.25L9.75 4.81l-6.286 6.287a.25.25 0 00-.064.108l-.558 1.953 1.953-.558a.249.249 0 00.108-.064l6.286-6.286z"></path>
-</svg>
-Edit this page on GitHub
-</a>
-</footer>
-</section>
-
-
-
-</body></html>
\ No newline at end of file
diff --git a/deps/npm/docs/output/commands/npm-stage.html b/deps/npm/docs/output/commands/npm-stage.html
index 74c4f7acddf..f127dbea3b9 100644
--- a/deps/npm/docs/output/commands/npm-stage.html
+++ b/deps/npm/docs/output/commands/npm-stage.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-stage----11191">
+<h1 id="----npm-stage----1210">
<span>npm-stage</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Stage packages for publishing</span>
</header>
@@ -433,7 +433,7 @@ relationships and disable <code>npm publish</code>.</p>
<td><code>--provenance</code></td>
<td>false</td>
<td>Boolean</td>
-<td>When publishing from a supported cloud CI/CD system, the package will be publicly linked to where it was built and published from.</td>
+<td>When publishing from a supported cloud CI/CD system, the package will be publicly linked to where it was built and published from. When the <code>provenance-file</code> config is set, it takes precedence and automatic provenance generation (including via trusted publishing/OIDC) is skipped.</td>
</tr>
</tbody>
</table>
diff --git a/deps/npm/docs/output/commands/npm-star.html b/deps/npm/docs/output/commands/npm-star.html
deleted file mode 100644
index 4ba2f61b179..00000000000
--- a/deps/npm/docs/output/commands/npm-star.html
+++ /dev/null
@@ -1,263 +0,0 @@
-<!DOCTYPE html><html><head>
-<meta charset="utf-8">
-<title>npm-star</title>
-<style>
-body {
- background-color: #ffffff;
- color: #24292e;
-
- margin: 0;
-
- line-height: 1.5;
-
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
-}
-#rainbar {
- height: 10px;
- background-image: linear-gradient(139deg, #fb8817, #ff4b01, #c12127, #e02aff);
-}
-
-a {
- text-decoration: none;
- color: #0366d6;
-}
-a:hover {
- text-decoration: underline;
-}
-
-pre {
- margin: 1em 0px;
- padding: 1em;
- border: solid 1px #e1e4e8;
- border-radius: 6px;
-
- display: block;
- overflow: auto;
-
- white-space: pre;
-
- background-color: #f6f8fa;
- color: #393a34;
-}
-code {
- font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace;
- font-size: 85%;
- padding: 0.2em 0.4em;
- background-color: #f6f8fa;
- color: #393a34;
-}
-pre > code {
- padding: 0;
- background-color: inherit;
- color: inherit;
-}
-h1, h2, h3 {
- font-weight: 600;
-}
-
-#logobar {
- background-color: #333333;
- margin: 0 auto;
- padding: 1em 4em;
-}
-#logobar .logo {
- float: left;
-}
-#logobar .title {
- font-weight: 600;
- color: #dddddd;
- float: left;
- margin: 5px 0 0 1em;
-}
-#logobar:after {
- content: "";
- display: block;
- clear: both;
-}
-
-#content {
- margin: 0 auto;
- padding: 0 4em;
-}
-
-#table_of_contents > h2 {
- font-size: 1.17em;
-}
-#table_of_contents ul:first-child {
- border: solid 1px #e1e4e8;
- border-radius: 6px;
- padding: 1em;
- background-color: #f6f8fa;
- color: #393a34;
-}
-#table_of_contents ul {
- list-style-type: none;
- padding-left: 1.5em;
-}
-#table_of_contents li {
- font-size: 0.9em;
-}
-#table_of_contents li a {
- color: #000000;
-}
-
-header.title {
- border-bottom: solid 1px #e1e4e8;
-}
-header.title > h1 {
- margin-bottom: 0.25em;
-}
-header.title > .description {
- display: block;
- margin-bottom: 0.5em;
- line-height: 1;
-}
-
-header.title .version {
- font-size: 0.8em;
- color: #666666;
-}
-
-footer#edit {
- border-top: solid 1px #e1e4e8;
- margin: 3em 0 4em 0;
- padding-top: 2em;
-}
-
-table {
- width: 100%;
- margin: 1em 0;
- border-radius: 6px;
- border: 1px solid #e1e4e8;
- overflow: hidden;
- border-collapse: separate;
- border-spacing: 0;
-}
-
-table thead {
- background-color: #f6f8fa;
-}
-
-table tbody {
- background-color: #ffffff;
-}
-
-table th,
-table td {
- padding: 0.75em;
- text-align: left;
- border-right: 1px solid #e1e4e8;
- border-bottom: 1px solid #e1e4e8;
-}
-
-table th:last-child,
-table td:last-child {
- border-right: none;
-}
-
-table tbody tr:last-child td {
- border-bottom: none;
-}
-
-table th {
- font-weight: 600;
- background-color: #f6f8fa;
-}
-
-table code {
- white-space: nowrap;
-}
-
-</style>
-</head>
-<body>
-<div id="banner">
-<div id="rainbar"></div>
-<div id="logobar">
-<svg class="logo" role="img" height="32" width="32" viewBox="0 0 700 700">
-<polygon fill="#cb0000" points="0,700 700,700 700,0 0,0"></polygon>
-<polygon fill="#ffffff" points="150,550 350,550 350,250 450,250 450,550 550,550 550,150 150,150"></polygon>
-</svg>
-<div class="title">
-npm command-line interface
-</div>
-</div>
-</div>
-
-<section id="content">
-<header class="title">
-<h1 id="----npm-star----11191">
- <span>npm-star</span>
- <span class="version">@11.19.1</span>
-</h1>
-<span class="description">Mark your favorite packages</span>
-</header>
-
-<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="#more">More</a></li><ul><li><a href="#unstar">Unstar</a></li><li><a href="#listing-stars">Listing stars</a></li></ul><li><a href="#configuration">Configuration</a></li><ul><li><a href="#registry"><code>registry</code></a></li><li><a href="#unicode"><code>unicode</code></a></li><li><a href="#otp"><code>otp</code></a></li></ul><li><a href="#see-also">See Also</a></li></ul></div>
-</section>
-
-<div id="_content"><h3 id="synopsis">Synopsis</h3>
-<pre><code class="language-bash">npm star [<package-spec>...]
-</code></pre>
-<p>Note: This command is unaware of workspaces.</p>
-<h3 id="description">Description</h3>
-<p>"Starring" a package means that you have some interest in it.
-It's a vaguely positive way to show that you care.</p>
-<p>It's a boolean thing.
-Starring repeatedly has no additional effect.</p>
-<h3 id="more">More</h3>
-<p>There's also these extra commands to help you manage your favorite packages:</p>
-<h4 id="unstar">Unstar</h4>
-<p>You can also "unstar" a package using <a href="../commands/npm-unstar.html"><code>npm unstar</code></a></p>
-<p>"Unstarring" is the same thing, but in reverse.</p>
-<h4 id="listing-stars">Listing stars</h4>
-<p>You can see all your starred packages using <a href="../commands/npm-stars.html"><code>npm stars</code></a></p>
-<h3 id="configuration">Configuration</h3>
-<h4 id="registry"><code>registry</code></h4>
-<ul>
-<li>Default: "<a href="https://registry.npmjs.org/">https://registry.npmjs.org/</a>"</li>
-<li>Type: URL</li>
-</ul>
-<p>The base URL of the npm registry.</p>
-<h4 id="unicode"><code>unicode</code></h4>
-<ul>
-<li>Default: false on windows, true on mac/unix systems with a unicode locale,
-as defined by the <code>LC_ALL</code>, <code>LC_CTYPE</code>, or <code>LANG</code> environment variables.</li>
-<li>Type: Boolean</li>
-</ul>
-<p>When set to true, npm uses unicode characters in the tree output. When
-false, it uses ascii characters instead of unicode glyphs.</p>
-<h4 id="otp"><code>otp</code></h4>
-<ul>
-<li>Default: null</li>
-<li>Type: null or String</li>
-</ul>
-<p>This is a one-time password from a two-factor authenticator. It's needed
-when publishing or changing package permissions with <code>npm access</code>.</p>
-<p>If not set, and a registry response fails with a challenge for a one-time
-password, npm will prompt on the command line for one.</p>
-<h3 id="see-also">See Also</h3>
-<ul>
-<li><a href="../using-npm/package-spec.html">package spec</a></li>
-<li><a href="../commands/npm-unstar.html">npm unstar</a></li>
-<li><a href="../commands/npm-stars.html">npm stars</a></li>
-<li><a href="../commands/npm-view.html">npm view</a></li>
-<li><a href="../commands/npm-whoami.html">npm whoami</a></li>
-<li><a href="../commands/npm-adduser.html">npm adduser</a></li>
-</ul></div>
-
-<footer id="edit">
-<a href="https://github.com/npm/cli/edit/latest/docs/lib/content/commands/npm-star.md">
-<svg role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentcolor" style="vertical-align: text-bottom; margin-right: 0.3em;">
-<path fill-rule="evenodd" d="M11.013 1.427a1.75 1.75 0 012.474 0l1.086 1.086a1.75 1.75 0 010 2.474l-8.61 8.61c-.21.21-.47.364-.756.445l-3.251.93a.75.75 0 01-.927-.928l.929-3.25a1.75 1.75 0 01.445-.758l8.61-8.61zm1.414 1.06a.25.25 0 00-.354 0L10.811 3.75l1.439 1.44 1.263-1.263a.25.25 0 000-.354l-1.086-1.086zM11.189 6.25L9.75 4.81l-6.286 6.287a.25.25 0 00-.064.108l-.558 1.953 1.953-.558a.249.249 0 00.108-.064l6.286-6.286z"></path>
-</svg>
-Edit this page on GitHub
-</a>
-</footer>
-</section>
-
-
-
-</body></html>
\ No newline at end of file
diff --git a/deps/npm/docs/output/commands/npm-stars.html b/deps/npm/docs/output/commands/npm-stars.html
deleted file mode 100644
index a1c7c0a4fd9..00000000000
--- a/deps/npm/docs/output/commands/npm-stars.html
+++ /dev/null
@@ -1,236 +0,0 @@
-<!DOCTYPE html><html><head>
-<meta charset="utf-8">
-<title>npm-stars</title>
-<style>
-body {
- background-color: #ffffff;
- color: #24292e;
-
- margin: 0;
-
- line-height: 1.5;
-
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
-}
-#rainbar {
- height: 10px;
- background-image: linear-gradient(139deg, #fb8817, #ff4b01, #c12127, #e02aff);
-}
-
-a {
- text-decoration: none;
- color: #0366d6;
-}
-a:hover {
- text-decoration: underline;
-}
-
-pre {
- margin: 1em 0px;
- padding: 1em;
- border: solid 1px #e1e4e8;
- border-radius: 6px;
-
- display: block;
- overflow: auto;
-
- white-space: pre;
-
- background-color: #f6f8fa;
- color: #393a34;
-}
-code {
- font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace;
- font-size: 85%;
- padding: 0.2em 0.4em;
- background-color: #f6f8fa;
- color: #393a34;
-}
-pre > code {
- padding: 0;
- background-color: inherit;
- color: inherit;
-}
-h1, h2, h3 {
- font-weight: 600;
-}
-
-#logobar {
- background-color: #333333;
- margin: 0 auto;
- padding: 1em 4em;
-}
-#logobar .logo {
- float: left;
-}
-#logobar .title {
- font-weight: 600;
- color: #dddddd;
- float: left;
- margin: 5px 0 0 1em;
-}
-#logobar:after {
- content: "";
- display: block;
- clear: both;
-}
-
-#content {
- margin: 0 auto;
- padding: 0 4em;
-}
-
-#table_of_contents > h2 {
- font-size: 1.17em;
-}
-#table_of_contents ul:first-child {
- border: solid 1px #e1e4e8;
- border-radius: 6px;
- padding: 1em;
- background-color: #f6f8fa;
- color: #393a34;
-}
-#table_of_contents ul {
- list-style-type: none;
- padding-left: 1.5em;
-}
-#table_of_contents li {
- font-size: 0.9em;
-}
-#table_of_contents li a {
- color: #000000;
-}
-
-header.title {
- border-bottom: solid 1px #e1e4e8;
-}
-header.title > h1 {
- margin-bottom: 0.25em;
-}
-header.title > .description {
- display: block;
- margin-bottom: 0.5em;
- line-height: 1;
-}
-
-header.title .version {
- font-size: 0.8em;
- color: #666666;
-}
-
-footer#edit {
- border-top: solid 1px #e1e4e8;
- margin: 3em 0 4em 0;
- padding-top: 2em;
-}
-
-table {
- width: 100%;
- margin: 1em 0;
- border-radius: 6px;
- border: 1px solid #e1e4e8;
- overflow: hidden;
- border-collapse: separate;
- border-spacing: 0;
-}
-
-table thead {
- background-color: #f6f8fa;
-}
-
-table tbody {
- background-color: #ffffff;
-}
-
-table th,
-table td {
- padding: 0.75em;
- text-align: left;
- border-right: 1px solid #e1e4e8;
- border-bottom: 1px solid #e1e4e8;
-}
-
-table th:last-child,
-table td:last-child {
- border-right: none;
-}
-
-table tbody tr:last-child td {
- border-bottom: none;
-}
-
-table th {
- font-weight: 600;
- background-color: #f6f8fa;
-}
-
-table code {
- white-space: nowrap;
-}
-
-</style>
-</head>
-<body>
-<div id="banner">
-<div id="rainbar"></div>
-<div id="logobar">
-<svg class="logo" role="img" height="32" width="32" viewBox="0 0 700 700">
-<polygon fill="#cb0000" points="0,700 700,700 700,0 0,0"></polygon>
-<polygon fill="#ffffff" points="150,550 350,550 350,250 450,250 450,550 550,550 550,150 150,150"></polygon>
-</svg>
-<div class="title">
-npm command-line interface
-</div>
-</div>
-</div>
-
-<section id="content">
-<header class="title">
-<h1 id="----npm-stars----11191">
- <span>npm-stars</span>
- <span class="version">@11.19.1</span>
-</h1>
-<span class="description">View packages marked as favorites</span>
-</header>
-
-<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"><code>registry</code></a></li></ul><li><a href="#see-also">See Also</a></li></ul></div>
-</section>
-
-<div id="_content"><h3 id="synopsis">Synopsis</h3>
-<pre><code class="language-bash">npm stars [<user>]
-</code></pre>
-<p>Note: This command is unaware of workspaces.</p>
-<h3 id="description">Description</h3>
-<p>If you have starred a lot of neat things and want to find them again quickly this command lets you do just that.</p>
-<p>You may also want to see your friend's favorite packages, in this case you will most certainly enjoy this command.</p>
-<h3 id="configuration">Configuration</h3>
-<h4 id="registry"><code>registry</code></h4>
-<ul>
-<li>Default: "<a href="https://registry.npmjs.org/">https://registry.npmjs.org/</a>"</li>
-<li>Type: URL</li>
-</ul>
-<p>The base URL of the npm registry.</p>
-<h3 id="see-also">See Also</h3>
-<ul>
-<li><a href="../commands/npm-star.html">npm star</a></li>
-<li><a href="../commands/npm-unstar.html">npm unstar</a></li>
-<li><a href="../commands/npm-view.html">npm view</a></li>
-<li><a href="../commands/npm-whoami.html">npm whoami</a></li>
-<li><a href="../commands/npm-adduser.html">npm adduser</a></li>
-</ul></div>
-
-<footer id="edit">
-<a href="https://github.com/npm/cli/edit/latest/docs/lib/content/commands/npm-stars.md">
-<svg role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentcolor" style="vertical-align: text-bottom; margin-right: 0.3em;">
-<path fill-rule="evenodd" d="M11.013 1.427a1.75 1.75 0 012.474 0l1.086 1.086a1.75 1.75 0 010 2.474l-8.61 8.61c-.21.21-.47.364-.756.445l-3.251.93a.75.75 0 01-.927-.928l.929-3.25a1.75 1.75 0 01.445-.758l8.61-8.61zm1.414 1.06a.25.25 0 00-.354 0L10.811 3.75l1.439 1.44 1.263-1.263a.25.25 0 000-.354l-1.086-1.086zM11.189 6.25L9.75 4.81l-6.286 6.287a.25.25 0 00-.064.108l-.558 1.953 1.953-.558a.249.249 0 00.108-.064l6.286-6.286z"></path>
-</svg>
-Edit this page on GitHub
-</a>
-</footer>
-</section>
-
-
-
-</body></html>
\ No newline at end of file
diff --git a/deps/npm/docs/output/commands/npm-start.html b/deps/npm/docs/output/commands/npm-start.html
index 063ac6b3d80..4a2ea8acc75 100644
--- a/deps/npm/docs/output/commands/npm-start.html
+++ b/deps/npm/docs/output/commands/npm-start.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-start----11191">
+<h1 id="----npm-start----1210">
<span>npm-start</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Start a package</span>
</header>
@@ -233,6 +233,8 @@ Refer to <a href="../commands/npm-run.html"><code>npm run</code></a> for more de
<code>npm start</code>, <code>npm stop</code>, <code>npm restart</code>, <code>npm test</code>, and <code>npm run</code> will still
run their intended script if <code>ignore-scripts</code> is set, but they will <em>not</em>
run any pre- or post-scripts.</p>
+<p>Setting <code>ignore-scripts</code> also disables <code>.npm-extension</code> execution, as if
+<code>ignore-extension</code> were set.</p>
<h4 id="script-shell"><code>script-shell</code></h4>
<ul>
<li>Default: '/bin/sh' on POSIX systems, 'cmd.exe' on Windows</li>
diff --git a/deps/npm/docs/output/commands/npm-stop.html b/deps/npm/docs/output/commands/npm-stop.html
index b4e84d2488d..4af840d6c4d 100644
--- a/deps/npm/docs/output/commands/npm-stop.html
+++ b/deps/npm/docs/output/commands/npm-stop.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-stop----11191">
+<h1 id="----npm-stop----1210">
<span>npm-stop</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Stop a package</span>
</header>
@@ -230,6 +230,8 @@ npm command-line interface
<code>npm start</code>, <code>npm stop</code>, <code>npm restart</code>, <code>npm test</code>, and <code>npm run</code> will still
run their intended script if <code>ignore-scripts</code> is set, but they will <em>not</em>
run any pre- or post-scripts.</p>
+<p>Setting <code>ignore-scripts</code> also disables <code>.npm-extension</code> execution, as if
+<code>ignore-extension</code> were set.</p>
<h4 id="script-shell"><code>script-shell</code></h4>
<ul>
<li>Default: '/bin/sh' on POSIX systems, 'cmd.exe' on Windows</li>
diff --git a/deps/npm/docs/output/commands/npm-team.html b/deps/npm/docs/output/commands/npm-team.html
index c9a7504b91f..d9234d26591 100644
--- a/deps/npm/docs/output/commands/npm-team.html
+++ b/deps/npm/docs/output/commands/npm-team.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-team----11191">
+<h1 id="----npm-team----1210">
<span>npm-team</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Manage organization teams and team memberships</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-test.html b/deps/npm/docs/output/commands/npm-test.html
index bbb30678ba8..56d5f356abe 100644
--- a/deps/npm/docs/output/commands/npm-test.html
+++ b/deps/npm/docs/output/commands/npm-test.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-test----11191">
+<h1 id="----npm-test----1210">
<span>npm-test</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Test a package</span>
</header>
@@ -229,6 +229,8 @@ aliases: tst, t
<code>npm start</code>, <code>npm stop</code>, <code>npm restart</code>, <code>npm test</code>, and <code>npm run</code> will still
run their intended script if <code>ignore-scripts</code> is set, but they will <em>not</em>
run any pre- or post-scripts.</p>
+<p>Setting <code>ignore-scripts</code> also disables <code>.npm-extension</code> execution, as if
+<code>ignore-extension</code> were set.</p>
<h4 id="script-shell"><code>script-shell</code></h4>
<ul>
<li>Default: '/bin/sh' on POSIX systems, 'cmd.exe' on Windows</li>
diff --git a/deps/npm/docs/output/commands/npm-token.html b/deps/npm/docs/output/commands/npm-token.html
index 680c2aa534f..8aa1c136181 100644
--- a/deps/npm/docs/output/commands/npm-token.html
+++ b/deps/npm/docs/output/commands/npm-token.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-token----11191">
+<h1 id="----npm-token----1210">
<span>npm-token</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Manage your authentication tokens</span>
</header>
@@ -268,11 +268,14 @@ the token access to specific organizations.</p>
<h4 id="packages-and-scopes-permission"><code>packages-and-scopes-permission</code></h4>
<ul>
<li>Default: null</li>
-<li>Type: null, "read-only", "read-write", or "no-access"</li>
+<li>Type: null, "read-only", "read-write", "read-write-stage-only", or
+"no-access"</li>
</ul>
<p>When creating a Granular Access Token with <code>npm token create</code>, sets the
permission level for packages and scopes. Options are "read-only",
-"read-write", or "no-access".</p>
+"read-write", "read-write-stage-only", or "no-access".
+"read-write-stage-only" grants publish access that stages releases instead
+of publishing them directly.</p>
<h4 id="orgs-permission"><code>orgs-permission</code></h4>
<ul>
<li>Default: null</li>
@@ -327,7 +330,7 @@ password, npm will prompt on the command line for one.</p>
access tokens with the <code>npm token create</code> command.</p>
<h3 id="see-also">See Also</h3>
<ul>
-<li><a href="../commands/npm-adduser.html">npm adduser</a></li>
+<li><a href="../commands/npm-login.html">npm login</a></li>
<li><a href="../using-npm/registry.html">npm registry</a></li>
<li><a href="../commands/npm-config.html">npm config</a></li>
<li><a href="../configuring-npm/npmrc.html">npmrc</a></li>
diff --git a/deps/npm/docs/output/commands/npm-trust.html b/deps/npm/docs/output/commands/npm-trust.html
index 6d531484035..3ddacb29564 100644
--- a/deps/npm/docs/output/commands/npm-trust.html
+++ b/deps/npm/docs/output/commands/npm-trust.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-trust----11191">
+<h1 id="----npm-trust----1210">
<span>npm-trust</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Manage trusted publishing relationships between packages and CI/CD providers</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-undeprecate.html b/deps/npm/docs/output/commands/npm-undeprecate.html
index d5239ca0cac..ce42db0b19b 100644
--- a/deps/npm/docs/output/commands/npm-undeprecate.html
+++ b/deps/npm/docs/output/commands/npm-undeprecate.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-undeprecate----11191">
+<h1 id="----npm-undeprecate----1210">
<span>npm-undeprecate</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Undeprecate a version of a package</span>
</header>
diff --git a/deps/npm/docs/output/commands/npm-uninstall.html b/deps/npm/docs/output/commands/npm-uninstall.html
index 26991d034bd..4a67748cb04 100644
--- a/deps/npm/docs/output/commands/npm-uninstall.html
+++ b/deps/npm/docs/output/commands/npm-uninstall.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-uninstall----11191">
+<h1 id="----npm-uninstall----1210">
<span>npm-uninstall</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Remove a package</span>
</header>
@@ -207,9 +207,9 @@ aliases: unlink, remove, rm, r, un
<p>This uninstalls a package, completely removing everything npm installed on its behalf.</p>
<p>It also removes the package from the <code>dependencies</code>, <code>devDependencies</code>,
<code>optionalDependencies</code>, and <code>peerDependencies</code> objects in your <code>package.json</code>.</p>
-<p>Further, if you have an <code>npm-shrinkwrap.json</code> or <code>package-lock.json</code>, npm will update those files as well.</p>
-<p><code>--no-save</code> will tell npm not to remove the package from your <code>package.json</code>, <code>npm-shrinkwrap.json</code>, or <code>package-lock.json</code> files.</p>
-<p><code>--save</code> or <code>-S</code> will tell npm to remove the package from your <code>package.json</code>, <code>npm-shrinkwrap.json</code>, and <code>package-lock.json</code> files.
+<p>Further, if you have a <code>package-lock.json</code>, npm will update that file as well.</p>
+<p><code>--no-save</code> will tell npm not to remove the package from your <code>package.json</code> or <code>package-lock.json</code> files.</p>
+<p><code>--save</code> or <code>-S</code> will tell npm to remove the package from your <code>package.json</code> and <code>package-lock.json</code> files.
This is the default, but you may need to use this if you have for instance <code>save=false</code> in your <code>npmrc</code> file</p>
<p>In global mode (ie, with <code>-g</code> or <code>--global</code> appended to the command), it uninstalls the current package context as a global package.
<code>--no-save</code> is ignored in this case.</p>
@@ -217,11 +217,11 @@ This is the default, but you may need to use this if you have for instance <code
<h3 id="examples">Examples</h3>
<pre><code class="language-bash">npm uninstall sax
</code></pre>
-<p><code>sax</code> will no longer be in your <code>package.json</code>, <code>npm-shrinkwrap.json</code>, or <code>package-lock.json</code> files.</p>
+<p><code>sax</code> will no longer be in your <code>package.json</code> or <code>package-lock.json</code> files.</p>
<pre><code class="language-bash">npm uninstall lodash --no-save
</code></pre>
-<p><code>lodash</code> will not be removed from your <code>package.json</code>,
-<code>npm-shrinkwrap.json</code>, or <code>package-lock.json</code> files.</p>
+<p><code>lodash</code> will not be removed from your <code>package.json</code> or
+<code>package-lock.json</code> files.</p>
<h3 id="configuration">Configuration</h3>
<h4 id="save"><code>save</code></h4>
<ul>
diff --git a/deps/npm/docs/output/commands/npm-unpublish.html b/deps/npm/docs/output/commands/npm-unpublish.html
index 4fda332a961..8c53acd5dd4 100644
--- a/deps/npm/docs/output/commands/npm-unpublish.html
+++ b/deps/npm/docs/output/commands/npm-unpublish.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-unpublish----11191">
+<h1 id="----npm-unpublish----1210">
<span>npm-unpublish</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Remove a package from the registry</span>
</header>
@@ -206,7 +206,7 @@ npm command-line interface
<p>Consider using the <a href="../commands/npm-deprecate.html"><code>deprecate</code></a> command instead, if your intent is to encourage users to upgrade, or if you no longer want to maintain a package.</p>
<h3 id="description">Description</h3>
<p>This removes a package version from the registry, deleting its entry and removing the tarball.</p>
-<p>The npm registry will return an error if you are not <a href="../commands/npm-adduser.html">logged in</a>.</p>
+<p>The npm registry will return an error if you are not <a href="../commands/npm-login.html">logged in</a>.</p>
<p>If you do not specify a package name at all, the name and version to be unpublished will be pulled from the project in the current directory.</p>
<p>If you specify a package name but do not specify a version or if you remove all of a package's versions then the registry will remove the root package entry entirely.</p>
<p>Even if you unpublish a package version, that specific name and version combination can never be reused.
@@ -290,9 +290,8 @@ other things (test, exec, publish, etc.) will operate on the root project,
<li><a href="../commands/npm-deprecate.html">npm deprecate</a></li>
<li><a href="../commands/npm-publish.html">npm publish</a></li>
<li><a href="../using-npm/registry.html">npm registry</a></li>
-<li><a href="../commands/npm-adduser.html">npm adduser</a></li>
<li><a href="../commands/npm-owner.html">npm owner</a></li>
-<li><a href="../commands/npm-adduser.html">npm login</a></li>
+<li><a href="../commands/npm-login.html">npm login</a></li>
</ul></div>
<footer id="edit">
diff --git a/deps/npm/docs/output/commands/npm-unstar.html b/deps/npm/docs/output/commands/npm-unstar.html
deleted file mode 100644
index 25db54715dd..00000000000
--- a/deps/npm/docs/output/commands/npm-unstar.html
+++ /dev/null
@@ -1,258 +0,0 @@
-<!DOCTYPE html><html><head>
-<meta charset="utf-8">
-<title>npm-unstar</title>
-<style>
-body {
- background-color: #ffffff;
- color: #24292e;
-
- margin: 0;
-
- line-height: 1.5;
-
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
-}
-#rainbar {
- height: 10px;
- background-image: linear-gradient(139deg, #fb8817, #ff4b01, #c12127, #e02aff);
-}
-
-a {
- text-decoration: none;
- color: #0366d6;
-}
-a:hover {
- text-decoration: underline;
-}
-
-pre {
- margin: 1em 0px;
- padding: 1em;
- border: solid 1px #e1e4e8;
- border-radius: 6px;
-
- display: block;
- overflow: auto;
-
- white-space: pre;
-
- background-color: #f6f8fa;
- color: #393a34;
-}
-code {
- font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace;
- font-size: 85%;
- padding: 0.2em 0.4em;
- background-color: #f6f8fa;
- color: #393a34;
-}
-pre > code {
- padding: 0;
- background-color: inherit;
- color: inherit;
-}
-h1, h2, h3 {
- font-weight: 600;
-}
-
-#logobar {
- background-color: #333333;
- margin: 0 auto;
- padding: 1em 4em;
-}
-#logobar .logo {
- float: left;
-}
-#logobar .title {
- font-weight: 600;
- color: #dddddd;
- float: left;
- margin: 5px 0 0 1em;
-}
-#logobar:after {
- content: "";
- display: block;
- clear: both;
-}
-
-#content {
- margin: 0 auto;
- padding: 0 4em;
-}
-
-#table_of_contents > h2 {
- font-size: 1.17em;
-}
-#table_of_contents ul:first-child {
- border: solid 1px #e1e4e8;
- border-radius: 6px;
- padding: 1em;
- background-color: #f6f8fa;
- color: #393a34;
-}
-#table_of_contents ul {
- list-style-type: none;
- padding-left: 1.5em;
-}
-#table_of_contents li {
- font-size: 0.9em;
-}
-#table_of_contents li a {
- color: #000000;
-}
-
-header.title {
- border-bottom: solid 1px #e1e4e8;
-}
-header.title > h1 {
- margin-bottom: 0.25em;
-}
-header.title > .description {
- display: block;
- margin-bottom: 0.5em;
- line-height: 1;
-}
-
-header.title .version {
- font-size: 0.8em;
- color: #666666;
-}
-
-footer#edit {
- border-top: solid 1px #e1e4e8;
- margin: 3em 0 4em 0;
- padding-top: 2em;
-}
-
-table {
- width: 100%;
- margin: 1em 0;
- border-radius: 6px;
- border: 1px solid #e1e4e8;
- overflow: hidden;
- border-collapse: separate;
- border-spacing: 0;
-}
-
-table thead {
- background-color: #f6f8fa;
-}
-
-table tbody {
- background-color: #ffffff;
-}
-
-table th,
-table td {
- padding: 0.75em;
- text-align: left;
- border-right: 1px solid #e1e4e8;
- border-bottom: 1px solid #e1e4e8;
-}
-
-table th:last-child,
-table td:last-child {
- border-right: none;
-}
-
-table tbody tr:last-child td {
- border-bottom: none;
-}
-
-table th {
- font-weight: 600;
- background-color: #f6f8fa;
-}
-
-table code {
- white-space: nowrap;
-}
-
-</style>
-</head>
-<body>
-<div id="banner">
-<div id="rainbar"></div>
-<div id="logobar">
-<svg class="logo" role="img" height="32" width="32" viewBox="0 0 700 700">
-<polygon fill="#cb0000" points="0,700 700,700 700,0 0,0"></polygon>
-<polygon fill="#ffffff" points="150,550 350,550 350,250 450,250 450,550 550,550 550,150 150,150"></polygon>
-</svg>
-<div class="title">
-npm command-line interface
-</div>
-</div>
-</div>
-
-<section id="content">
-<header class="title">
-<h1 id="----npm-unstar----11191">
- <span>npm-unstar</span>
- <span class="version">@11.19.1</span>
-</h1>
-<span class="description">Remove an item from your favorite packages</span>
-</header>
-
-<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="#more">More</a></li><ul><li><a href="#star">Star</a></li><li><a href="#listing-stars">Listing stars</a></li></ul><li><a href="#configuration">Configuration</a></li><ul><li><a href="#registry"><code>registry</code></a></li><li><a href="#unicode"><code>unicode</code></a></li><li><a href="#otp"><code>otp</code></a></li></ul><li><a href="#see-also">See Also</a></li></ul></div>
-</section>
-
-<div id="_content"><h3 id="synopsis">Synopsis</h3>
-<pre><code class="language-bash">npm unstar [<package-spec>...]
-</code></pre>
-<p>Note: This command is unaware of workspaces.</p>
-<h3 id="description">Description</h3>
-<p>"Unstarring" a package is the opposite of <a href="../commands/npm-star.html"><code>npm star</code></a>, it removes an item from your list of favorite packages.</p>
-<h3 id="more">More</h3>
-<p>There's also these extra commands to help you manage your favorite packages:</p>
-<h4 id="star">Star</h4>
-<p>You can "star" a package using <a href="../commands/npm-star.html"><code>npm star</code></a></p>
-<h4 id="listing-stars">Listing stars</h4>
-<p>You can see all your starred packages using <a href="../commands/npm-stars.html"><code>npm stars</code></a></p>
-<h3 id="configuration">Configuration</h3>
-<h4 id="registry"><code>registry</code></h4>
-<ul>
-<li>Default: "<a href="https://registry.npmjs.org/">https://registry.npmjs.org/</a>"</li>
-<li>Type: URL</li>
-</ul>
-<p>The base URL of the npm registry.</p>
-<h4 id="unicode"><code>unicode</code></h4>
-<ul>
-<li>Default: false on windows, true on mac/unix systems with a unicode locale,
-as defined by the <code>LC_ALL</code>, <code>LC_CTYPE</code>, or <code>LANG</code> environment variables.</li>
-<li>Type: Boolean</li>
-</ul>
-<p>When set to true, npm uses unicode characters in the tree output. When
-false, it uses ascii characters instead of unicode glyphs.</p>
-<h4 id="otp"><code>otp</code></h4>
-<ul>
-<li>Default: null</li>
-<li>Type: null or String</li>
-</ul>
-<p>This is a one-time password from a two-factor authenticator. It's needed
-when publishing or changing package permissions with <code>npm access</code>.</p>
-<p>If not set, and a registry response fails with a challenge for a one-time
-password, npm will prompt on the command line for one.</p>
-<h3 id="see-also">See Also</h3>
-<ul>
-<li><a href="../commands/npm-star.html">npm star</a></li>
-<li><a href="../commands/npm-stars.html">npm stars</a></li>
-<li><a href="../commands/npm-view.html">npm view</a></li>
-<li><a href="../commands/npm-whoami.html">npm whoami</a></li>
-<li><a href="../commands/npm-adduser.html">npm adduser</a></li>
-</ul></div>
-
-<footer id="edit">
-<a href="https://github.com/npm/cli/edit/latest/docs/lib/content/commands/npm-unstar.md">
-<svg role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentcolor" style="vertical-align: text-bottom; margin-right: 0.3em;">
-<path fill-rule="evenodd" d="M11.013 1.427a1.75 1.75 0 012.474 0l1.086 1.086a1.75 1.75 0 010 2.474l-8.61 8.61c-.21.21-.47.364-.756.445l-3.251.93a.75.75 0 01-.927-.928l.929-3.25a1.75 1.75 0 01.445-.758l8.61-8.61zm1.414 1.06a.25.25 0 00-.354 0L10.811 3.75l1.439 1.44 1.263-1.263a.25.25 0 000-.354l-1.086-1.086zM11.189 6.25L9.75 4.81l-6.286 6.287a.25.25 0 00-.064.108l-.558 1.953 1.953-.558a.249.249 0 00.108-.064l6.286-6.286z"></path>
-</svg>
-Edit this page on GitHub
-</a>
-</footer>
-</section>
-
-
-
-</body></html>
\ No newline at end of file
diff --git a/deps/npm/docs/output/commands/npm-update.html b/deps/npm/docs/output/commands/npm-update.html
index fff2f70073c..db6463c2b47 100644
--- a/deps/npm/docs/output/commands/npm-update.html
+++ b/deps/npm/docs/output/commands/npm-update.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-update----11191">
+<h1 id="----npm-update----1210">
<span>npm-update</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Update packages</span>
</header>
@@ -354,8 +354,7 @@ on deeper dependencies. Sets <code>--install-strategy=shallow</code>.</p>
</ul>
<p>Dependency types to omit from the installation tree on disk.</p>
<p>Note that these dependencies <em>are</em> still resolved and added to the
-<code>package-lock.json</code> or <code>npm-shrinkwrap.json</code> file. They are just not
-physically installed on disk.</p>
+<code>package-lock.json</code> file. They are just not physically installed on disk.</p>
<p>If a package type appears in both the <code>--include</code> and <code>--omit</code> lists, then
it will be included.</p>
<p>If the resulting omit list includes <code>'dev'</code>, then the <code>NODE_ENV</code> environment
@@ -413,6 +412,8 @@ but can be useful for debugging.</p>
<code>npm start</code>, <code>npm stop</code>, <code>npm restart</code>, <code>npm test</code>, and <code>npm run</code> will still
run their intended script if <code>ignore-scripts</code> is set, but they will <em>not</em>
run any pre- or post-scripts.</p>
+<p>Setting <code>ignore-scripts</code> also disables <code>.npm-extension</code> execution, as if
+<code>ignore-extension</code> were set.</p>
<h4 id="allow-scripts"><code>allow-scripts</code></h4>
<ul>
<li>Default: ""</li>
@@ -430,16 +431,18 @@ project-scoped <code>npm install</code>, <code>ci</code>, <code>update</code>, o
<p>Each name is matched against a dependency's resolved identity, not against
the package's self-reported name. <code>--ignore-scripts</code> and
<code>--dangerously-allow-all-scripts</code> both override this setting.</p>
+<p>This value is not exported to the environment for child processes.</p>
<h4 id="strict-allow-scripts"><code>strict-allow-scripts</code></h4>
<ul>
<li>Default: false</li>
<li>Type: Boolean</li>
</ul>
<p>If <code>true</code>, turn the install-script policy from a warning into a hard error:
-any dependency with install scripts not covered by <code>allowScripts</code> will fail
-the install instead of running with a notice.</p>
+any dependency with install scripts that is not covered by <code>allowScripts</code>
+will fail the install instead of being blocked with a warning.</p>
<p>Dependencies explicitly denied with <code>false</code> in <code>allowScripts</code> are always
-silently skipped; this setting only affects unreviewed entries.
+silently skipped; this setting only affects unreviewed entries (packages
+with install scripts that are neither approved nor denied).
<code>--ignore-scripts</code> and <code>--dangerously-allow-all-scripts</code> both override this
setting.</p>
<p>Optional dependencies that cannot be installed on the current platform or
@@ -614,7 +617,6 @@ workspaces.</p>
<ul>
<li><a href="../commands/npm-install.html">npm install</a></li>
<li><a href="../commands/npm-outdated.html">npm outdated</a></li>
-<li><a href="../commands/npm-shrinkwrap.html">npm shrinkwrap</a></li>
<li><a href="../using-npm/registry.html">npm registry</a></li>
<li><a href="../configuring-npm/folders.html">npm folders</a></li>
<li><a href="../commands/npm-ls.html">npm ls</a></li>
diff --git a/deps/npm/docs/output/commands/npm-version.html b/deps/npm/docs/output/commands/npm-version.html
index 310abe5db90..3afedb515df 100644
--- a/deps/npm/docs/output/commands/npm-version.html
+++ b/deps/npm/docs/output/commands/npm-version.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-version----11191">
+<h1 id="----npm-version----1210">
<span>npm-version</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Bump a package version</span>
</header>
@@ -322,9 +322,10 @@ the specified workspaces, and not on the root project.</p>
<code>npm start</code>, <code>npm stop</code>, <code>npm restart</code>, <code>npm test</code>, and <code>npm run</code> will still
run their intended script if <code>ignore-scripts</code> is set, but they will <em>not</em>
run any pre- or post-scripts.</p>
+<p>Setting <code>ignore-scripts</code> also disables <code>.npm-extension</code> execution, as if
+<code>ignore-extension</code> were set.</p>
<h3 id="description">Description</h3>
-<p>Run this in a package directory to bump the version and write the new data back to <code>package.json</code>, <code>package-lock.json</code>, and, if present,
-<code>npm-shrinkwrap.json</code>.</p>
+<p>Run this in a package directory to bump the version and write the new data back to <code>package.json</code> and <code>package-lock.json</code>.</p>
<p>The <code>newversion</code> argument should be a valid semver string, a valid second argument to <a href="https://github.com/npm/node-semver#functions">semver.inc</a> (one of <code>patch</code>, <code>minor</code>, <code>major</code>, <code>prepatch</code>, <code>preminor</code>, <code>premajor</code>, <code>prerelease</code>), or <code>from-git</code>.
In the second case, the existing version will be incremented by 1 in the specified field.
<code>from-git</code> will try to read the latest git tag, and use that as the new npm version.</p>
diff --git a/deps/npm/docs/output/commands/npm-view.html b/deps/npm/docs/output/commands/npm-view.html
index 18f28fe1707..6507648475c 100644
--- a/deps/npm/docs/output/commands/npm-view.html
+++ b/deps/npm/docs/output/commands/npm-view.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-view----11191">
+<h1 id="----npm-view----1210">
<span>npm-view</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">View registry info</span>
</header>
@@ -355,7 +355,10 @@ the specified workspaces, and not on the root project.</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 another command.
If the field is an object, it will be output as a JavaScript object literal.</p>
-<p>If the <code>--json</code> flag is given, the outputted fields will be JSON.</p>
+<p>If the <code>--json</code> flag is given, the outputted fields will be JSON.
+Scalar and object results are returned in an array, even if only a single version matches.
+When the output contains one array-valued result, that array is returned directly without an additional result wrapper.
+Multiple array-valued results remain separate items in the outer results array.</p>
<p>If the version range matches multiple versions then each printed value will be prefixed with the version it applies to.</p>
<p>If multiple fields are requested, then each of them is prefixed with the field name.</p>
<h3 id="see-also">See Also</h3>
diff --git a/deps/npm/docs/output/commands/npm-whoami.html b/deps/npm/docs/output/commands/npm-whoami.html
index 91a7d6e2288..0f6128a5abe 100644
--- a/deps/npm/docs/output/commands/npm-whoami.html
+++ b/deps/npm/docs/output/commands/npm-whoami.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm-whoami----11191">
+<h1 id="----npm-whoami----1210">
<span>npm-whoami</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Display npm username</span>
</header>
@@ -217,7 +217,7 @@ npm command-line interface
<ul>
<li><a href="../commands/npm-config.html">npm config</a></li>
<li><a href="../configuring-npm/npmrc.html">npmrc</a></li>
-<li><a href="../commands/npm-adduser.html">npm adduser</a></li>
+<li><a href="../commands/npm-login.html">npm login</a></li>
</ul></div>
<footer id="edit">
diff --git a/deps/npm/docs/output/commands/npm.html b/deps/npm/docs/output/commands/npm.html
index 99674e1362d..f2c1114e3b5 100644
--- a/deps/npm/docs/output/commands/npm.html
+++ b/deps/npm/docs/output/commands/npm.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npm----11191">
+<h1 id="----npm----1210">
<span>npm</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">javascript package manager</span>
</header>
@@ -203,7 +203,7 @@ npm command-line interface
</code></pre>
<p>Note: This command is unaware of workspaces.</p>
<h3 id="version">Version</h3>
-<p>11.19.1</p>
+<p>12.1.0</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 conflicts intelligently.</p>
@@ -251,8 +251,8 @@ Use <a href="../commands/npm-link.html"><code>npm link</code></a> to do this.</l
<li>install:
It's a good idea to install things if you don't need the symbolic link.
Especially, installing other peoples code from the registry is done via <a href="../commands/npm-install.html"><code>npm install</code></a></li>
-<li>adduser:
-Create an account or log in.
+<li>login:
+Log in to the registry and store credentials.
When you do this, npm will store credentials in the user config file.</li>
<li>publish:
Use the <a href="../commands/npm-publish.html"><code>npm publish</code></a> command to upload your code to the registry.</li>
diff --git a/deps/npm/docs/output/commands/npx.html b/deps/npm/docs/output/commands/npx.html
index d3cb1e00cc5..ad3401fc1f5 100644
--- a/deps/npm/docs/output/commands/npx.html
+++ b/deps/npm/docs/output/commands/npx.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npx----11191">
+<h1 id="----npx----1210">
<span>npx</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Run a command from a local or remote npm package</span>
</header>
diff --git a/deps/npm/docs/output/configuring-npm/folders.html b/deps/npm/docs/output/configuring-npm/folders.html
index 3e86bf9a9ee..16ec237c7cf 100644
--- a/deps/npm/docs/output/configuring-npm/folders.html
+++ b/deps/npm/docs/output/configuring-npm/folders.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----folders----11191">
+<h1 id="----folders----1210">
<span>Folders</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Folder structures used by npm</span>
</header>
diff --git a/deps/npm/docs/output/configuring-npm/install.html b/deps/npm/docs/output/configuring-npm/install.html
index 610fc057a13..7fc1b0835af 100644
--- a/deps/npm/docs/output/configuring-npm/install.html
+++ b/deps/npm/docs/output/configuring-npm/install.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----install----11191">
+<h1 id="----install----1210">
<span>Install</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Download and install node and npm</span>
</header>
diff --git a/deps/npm/docs/output/configuring-npm/npm-extension.html b/deps/npm/docs/output/configuring-npm/npm-extension.html
new file mode 100644
index 00000000000..477d79a1651
--- /dev/null
+++ b/deps/npm/docs/output/configuring-npm/npm-extension.html
@@ -0,0 +1,272 @@
+<!DOCTYPE html><html><head>
+<meta charset="utf-8">
+<title>.npm-extension</title>
+<style>
+body {
+ background-color: #ffffff;
+ color: #24292e;
+
+ margin: 0;
+
+ line-height: 1.5;
+
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
+}
+#rainbar {
+ height: 10px;
+ background-image: linear-gradient(139deg, #fb8817, #ff4b01, #c12127, #e02aff);
+}
+
+a {
+ text-decoration: none;
+ color: #0366d6;
+}
+a:hover {
+ text-decoration: underline;
+}
+
+pre {
+ margin: 1em 0px;
+ padding: 1em;
+ border: solid 1px #e1e4e8;
+ border-radius: 6px;
+
+ display: block;
+ overflow: auto;
+
+ white-space: pre;
+
+ background-color: #f6f8fa;
+ color: #393a34;
+}
+code {
+ font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace;
+ font-size: 85%;
+ padding: 0.2em 0.4em;
+ background-color: #f6f8fa;
+ color: #393a34;
+}
+pre > code {
+ padding: 0;
+ background-color: inherit;
+ color: inherit;
+}
+h1, h2, h3 {
+ font-weight: 600;
+}
+
+#logobar {
+ background-color: #333333;
+ margin: 0 auto;
+ padding: 1em 4em;
+}
+#logobar .logo {
+ float: left;
+}
+#logobar .title {
+ font-weight: 600;
+ color: #dddddd;
+ float: left;
+ margin: 5px 0 0 1em;
+}
+#logobar:after {
+ content: "";
+ display: block;
+ clear: both;
+}
+
+#content {
+ margin: 0 auto;
+ padding: 0 4em;
+}
+
+#table_of_contents > h2 {
+ font-size: 1.17em;
+}
+#table_of_contents ul:first-child {
+ border: solid 1px #e1e4e8;
+ border-radius: 6px;
+ padding: 1em;
+ background-color: #f6f8fa;
+ color: #393a34;
+}
+#table_of_contents ul {
+ list-style-type: none;
+ padding-left: 1.5em;
+}
+#table_of_contents li {
+ font-size: 0.9em;
+}
+#table_of_contents li a {
+ color: #000000;
+}
+
+header.title {
+ border-bottom: solid 1px #e1e4e8;
+}
+header.title > h1 {
+ margin-bottom: 0.25em;
+}
+header.title > .description {
+ display: block;
+ margin-bottom: 0.5em;
+ line-height: 1;
+}
+
+header.title .version {
+ font-size: 0.8em;
+ color: #666666;
+}
+
+footer#edit {
+ border-top: solid 1px #e1e4e8;
+ margin: 3em 0 4em 0;
+ padding-top: 2em;
+}
+
+table {
+ width: 100%;
+ margin: 1em 0;
+ border-radius: 6px;
+ border: 1px solid #e1e4e8;
+ overflow: hidden;
+ border-collapse: separate;
+ border-spacing: 0;
+}
+
+table thead {
+ background-color: #f6f8fa;
+}
+
+table tbody {
+ background-color: #ffffff;
+}
+
+table th,
+table td {
+ padding: 0.75em;
+ text-align: left;
+ border-right: 1px solid #e1e4e8;
+ border-bottom: 1px solid #e1e4e8;
+}
+
+table th:last-child,
+table td:last-child {
+ border-right: none;
+}
+
+table tbody tr:last-child td {
+ border-bottom: none;
+}
+
+table th {
+ font-weight: 600;
+ background-color: #f6f8fa;
+}
+
+table code {
+ white-space: nowrap;
+}
+
+</style>
+</head>
+<body>
+<div id="banner">
+<div id="rainbar"></div>
+<div id="logobar">
+<svg class="logo" role="img" height="32" width="32" viewBox="0 0 700 700">
+<polygon fill="#cb0000" points="0,700 700,700 700,0 0,0"></polygon>
+<polygon fill="#ffffff" points="150,550 350,550 350,250 450,250 450,550 550,550 550,150 150,150"></polygon>
+</svg>
+<div class="title">
+npm command-line interface
+</div>
+</div>
+</div>
+
+<section id="content">
+<header class="title">
+<h1 id="----npm-extension----1210">
+ <span>.npm-extension</span>
+ <span class="version">@12.1.0</span>
+</h1>
+<span class="description">Imperative, root-owned manifest repairs</span>
+</header>
+
+<section id="table_of_contents">
+<h2 id="table-of-contents">Table of contents</h2>
+<div id="_table_of_contents"><ul><li><a href="#description">Description</a></li><li><a href="#example">Example</a></li><li><a href="#the-transformmanifest-function">The <code>transformManifest</code> function</a></li><li><a href="#supported-mutations">Supported mutations</a></li><li><a href="#discovery-and-extension-file">Discovery and <code>extension-file</code></a></li><li><a href="#interaction-with-packageextensions-and-overrides">Interaction with <code>packageExtensions</code> and <code>overrides</code></a></li><li><a href="#lockfile-and-npm-ci">Lockfile and <code>npm ci</code></a></li><li><a href="#disabling">Disabling</a></li><li><a href="#publishing">Publishing</a></li><li><a href="#see-also">See also</a></li></ul></div>
+</section>
+
+<div id="_content"><h3 id="description">Description</h3>
+<p>A root-owned <code>.npm-extension.mjs</code> or <code>.npm-extension.cjs</code> file lets a project imperatively repair the manifests of third-party dependencies before npm resolves the dependency tree. It exports a <code>transformManifest(pkg, context)</code> function that receives a candidate dependency manifest and returns the effective manifest npm should use.</p>
+<p><code>.npm-extension</code> is the imperative counterpart to the declarative <a href="../configuring-npm/package-json#packageextensions.html"><code>packageExtensions</code></a> field, and runs in the same pre-resolution phase, <strong>before</strong> <code>packageExtensions</code>. Prefer <code>packageExtensions</code> for simple, data-only repairs; reach for <code>.npm-extension</code> when you need comments and links explaining a repair, conditional logic, repeated repairs expressed as code, deletion or range rewrites, stale-repair guards, or a policy location outside <code>package.json</code>.</p>
+<h3 id="example">Example</h3>
+<pre><code class="language-js">// .npm-extension.mjs
+export function transformManifest (pkg, context) {
+ if (pkg.name === 'foo' && pkg.version.startsWith('1.')) {
+ pkg.dependencies = { ...pkg.dependencies, bar: '^2.0.0' }
+ context.log(`added bar to ${pkg.name}@${pkg.version}`)
+ }
+ return pkg
+}
+</code></pre>
+<p>The <code>.cjs</code> form uses CommonJS exports instead:</p>
+<pre><code class="language-js">// .npm-extension.cjs
+module.exports = {
+ transformManifest (pkg, context) {
+ return pkg
+ },
+}
+</code></pre>
+<h3 id="the-transformmanifest-function">The <code>transformManifest</code> function</h3>
+<p><code>transformManifest(pkg, context)</code> receives a deeply isolated copy of a candidate dependency manifest. It may mutate and return that copy, or return a new manifest object. It <strong>must</strong> return a manifest object synchronously; returning <code>null</code>, <code>undefined</code>, a primitive, an array, or a promise fails the install.</p>
+<p>The <code>context</code> argument is intentionally small:</p>
+<ul>
+<li><code>context.log(message)</code> writes an npm debug log message.</li>
+<li><code>context.root</code> is the absolute path to the project root.</li>
+<li><code>context.extensionPoint</code> is the string <code>"transformManifest"</code>.</li>
+</ul>
+<p>npm provides no registry, fetch, lockfile, or extraction helpers. Keep the extension file self-contained or limited to Node builtins; npm does not guarantee that project dependencies are available when the file is loaded.</p>
+<h3 id="supported-mutations">Supported mutations</h3>
+<p>Only the four resolution-affecting fields may change:</p>
+<ul>
+<li><code>dependencies</code></li>
+<li><code>optionalDependencies</code></li>
+<li><code>peerDependencies</code></li>
+<li><code>peerDependenciesMeta</code></li>
+</ul>
+<p>Within those fields you may add, replace, or delete entries. Changing any other field (such as <code>scripts</code>, <code>bin</code>, <code>engines</code>, <code>os</code>, <code>cpu</code>, <code>exports</code>, or <code>main</code>) is rejected, and the install fails with an error naming <code>.npm-extension</code> and the package being processed. The package tarball and the installed <code>node_modules/<pkg>/package.json</code> are never rewritten.</p>
+<h3 id="discovery-and-extension-file">Discovery and <code>extension-file</code></h3>
+<p>npm looks for a single <code>.npm-extension.mjs</code> or <code>.npm-extension.cjs</code> at the project root (the workspace root in a workspace project). Having both files present is an error. A <code>.npm-extension</code> file in a dependency or in a non-root workspace is ignored; a non-root workspace file produces a warning.</p>
+<p>The <a href="../using-npm/config#extension-file.html"><code>extension-file</code></a> config selects a different project-local file. It must resolve inside the project root and use a <code>.mjs</code> or <code>.cjs</code> extension, and it is honored only from project config or the command line — never from user, global, or builtin config.</p>
+<h3 id="interaction-with-packageextensions-and-overrides">Interaction with <code>packageExtensions</code> and <code>overrides</code></h3>
+<p>When both are present, <code>transformManifest</code> runs first and <code>packageExtensions</code> is applied to its output. Avoid targeting the same package with both unless you intend to rely on that ordering. <code>overrides</code> still controls the final resolution target of any edge, including edges created by <code>transformManifest</code>.</p>
+<h3 id="lockfile-and-npm-ci">Lockfile and <code>npm ci</code></h3>
+<p>A lockfile influenced by <code>.npm-extension</code> records an <code>npmExtensionHash</code> (a digest of the selected file's bytes and module format) on its root entry, and minimal <code>npmExtensionApplied</code> provenance on each affected package entry. Extension state requires <code>lockfileVersion: 4</code>.</p>
+<p>Changing the file's contents makes <code>npm install</code> re-resolve the affected packages. <code>npm ci</code> does <strong>not</strong> import or execute <code>.npm-extension</code>; it verifies the recorded hash against the file and reifies the locked graph, failing if the file and lockfile disagree (or if one has extension state and the other does not).</p>
+<p>The hash proves only that the install uses the same extension file bytes that generated the lockfile. It does not make arbitrary JavaScript deterministic: extension output that depends on environment variables, the network, the clock, or files imported by the extension can still produce non-reproducible installs. Treat <code>.npm-extension</code> as trusted, deterministic project code, and only enable it in repositories you trust.</p>
+<h3 id="disabling">Disabling</h3>
+<p>Set <a href="../using-npm/config#ignore-extension.html"><code>ignore-extension</code></a> to skip importing and executing <code>.npm-extension</code>. <a href="../using-npm/config#ignore-scripts.html"><code>ignore-scripts</code></a> implies <code>ignore-extension</code>, since both disable root-owned install-time code. <code>npm ci</code> still verifies the file hash even when execution is disabled.</p>
+<h3 id="publishing">Publishing</h3>
+<p><code>.npm-extension.mjs</code> and <code>.npm-extension.cjs</code> are project configuration, not package contents. npm excludes the root file from the package tarball produced by <code>npm pack</code> and <code>npm publish</code>, even when the package's <code>files</code> list would include it, so a public package can keep <code>.npm-extension</code> in its repository for local use without publishing it.</p>
+<h3 id="see-also">See also</h3>
+<ul>
+<li><a href="../configuring-npm/package-json#packageextensions.html">package.json <code>packageExtensions</code></a></li>
+<li><a href="../configuring-npm/package-lock-json.html">package-lock.json</a></li>
+<li><a href="../using-npm/config.html">config</a></li>
+</ul></div>
+
+<footer id="edit">
+<a href="https://github.com/npm/cli/edit/latest/docs/lib/content/configuring-npm/npm-extension.md">
+<svg role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentcolor" style="vertical-align: text-bottom; margin-right: 0.3em;">
+<path fill-rule="evenodd" d="M11.013 1.427a1.75 1.75 0 012.474 0l1.086 1.086a1.75 1.75 0 010 2.474l-8.61 8.61c-.21.21-.47.364-.756.445l-3.251.93a.75.75 0 01-.927-.928l.929-3.25a1.75 1.75 0 01.445-.758l8.61-8.61zm1.414 1.06a.25.25 0 00-.354 0L10.811 3.75l1.439 1.44 1.263-1.263a.25.25 0 000-.354l-1.086-1.086zM11.189 6.25L9.75 4.81l-6.286 6.287a.25.25 0 00-.064.108l-.558 1.953 1.953-.558a.249.249 0 00.108-.064l6.286-6.286z"></path>
+</svg>
+Edit this page on GitHub
+</a>
+</footer>
+</section>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/deps/npm/docs/output/configuring-npm/npm-global.html b/deps/npm/docs/output/configuring-npm/npm-global.html
index 3e86bf9a9ee..16ec237c7cf 100644
--- a/deps/npm/docs/output/configuring-npm/npm-global.html
+++ b/deps/npm/docs/output/configuring-npm/npm-global.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----folders----11191">
+<h1 id="----folders----1210">
<span>Folders</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Folder structures used by npm</span>
</header>
diff --git a/deps/npm/docs/output/configuring-npm/npm-json.html b/deps/npm/docs/output/configuring-npm/npm-json.html
index 97a03a6d617..148a01c926b 100644
--- a/deps/npm/docs/output/configuring-npm/npm-json.html
+++ b/deps/npm/docs/output/configuring-npm/npm-json.html
@@ -186,16 +186,16 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----packagejson----11191">
+<h1 id="----packagejson----1210">
<span>package.json</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Specifics of npm's package.json handling</span>
</header>
<section id="table_of_contents">
<h2 id="table-of-contents">Table of contents</h2>
-<div id="_table_of_contents"><ul><li><a href="#description">Description</a></li><li><a href="#name">name</a></li><li><a href="#version">version</a></li><li><a href="#description2">description</a></li><li><a href="#keywords">keywords</a></li><li><a href="#homepage">homepage</a></li><li><a href="#bugs">bugs</a></li><li><a href="#license">license</a></li><li><a href="#people-fields-author-contributors">people fields: author, contributors</a></li><li><a href="#funding">funding</a></li><li><a href="#files">files</a></li><li><a href="#exports">exports</a></li><li><a href="#main">main</a></li><li><a href="#type">type</a></li><li><a href="#browser">browser</a></li><li><a href="#bin">bin</a></li><li><a href="#man">man</a></li><li><a href="#directories">directories</a></li><ul><li><a href="#directoriesbin">directories.bin</a></li><li><a href="#directoriesman">directories.man</a></li></ul><li><a href="#repository">repository</a></li><li><a href="#scripts">scripts</a></li><li><a href="#gypfile">gypfile</a></li><li><a href="#config">config</a></li><li><a href="#dependencies">dependencies</a></li><ul><li><a href="#urls-as-dependencies">URLs as Dependencies</a></li><li><a href="#git-urls-as-dependencies">Git URLs as Dependencies</a></li><li><a href="#github-urls">GitHub URLs</a></li><li><a href="#local-paths">Local Paths</a></li></ul><li><a href="#devdependencies">devDependencies</a></li><li><a href="#peerdependencies">peerDependencies</a></li><li><a href="#peerdependenciesmeta">peerDependenciesMeta</a></li><li><a href="#bundledependencies">bundleDependencies</a></li><li><a href="#optionaldependencies">optionalDependencies</a></li><li><a href="#overrides">overrides</a></li><ul><li><a href="#replacing-a-dependency-with-a-fork">Replacing a dependency with a fork</a></li></ul><li><a href="#engines">engines</a></li><li><a href="#os">os</a></li><li><a href="#cpu">cpu</a></li><li><a href="#libc">libc</a></li><li><a href="#devengines">devEngines</a></li><li><a href="#private">private</a></li><li><a href="#publishconfig">publishConfig</a></li><li><a href="#workspaces">workspaces</a></li><li><a href="#default-values">DEFAULT VALUES</a></li><li><a href="#see-also">SEE ALSO</a></li></ul></div>
+<div id="_table_of_contents"><ul><li><a href="#description">Description</a></li><li><a href="#name">name</a></li><li><a href="#version">version</a></li><li><a href="#description2">description</a></li><li><a href="#keywords">keywords</a></li><li><a href="#homepage">homepage</a></li><li><a href="#bugs">bugs</a></li><li><a href="#license">license</a></li><li><a href="#people-fields-author-contributors">people fields: author, contributors</a></li><li><a href="#funding">funding</a></li><li><a href="#files">files</a></li><li><a href="#exports">exports</a></li><li><a href="#main">main</a></li><li><a href="#type">type</a></li><li><a href="#browser">browser</a></li><li><a href="#bin">bin</a></li><li><a href="#man">man</a></li><li><a href="#directories">directories</a></li><ul><li><a href="#directoriesbin">directories.bin</a></li><li><a href="#directoriesman">directories.man</a></li></ul><li><a href="#repository">repository</a></li><li><a href="#scripts">scripts</a></li><li><a href="#gypfile">gypfile</a></li><li><a href="#config">config</a></li><li><a href="#dependencies">dependencies</a></li><ul><li><a href="#urls-as-dependencies">URLs as Dependencies</a></li><li><a href="#git-urls-as-dependencies">Git URLs as Dependencies</a></li><li><a href="#github-urls">GitHub URLs</a></li><li><a href="#local-paths">Local Paths</a></li></ul><li><a href="#devdependencies">devDependencies</a></li><li><a href="#peerdependencies">peerDependencies</a></li><li><a href="#peerdependenciesmeta">peerDependenciesMeta</a></li><li><a href="#bundledependencies">bundleDependencies</a></li><li><a href="#optionaldependencies">optionalDependencies</a></li><li><a href="#overrides">overrides</a></li><ul><li><a href="#replacing-a-dependency-with-a-fork">Replacing a dependency with a fork</a></li></ul><li><a href="#packageextensions">packageExtensions</a></li><li><a href="#engines">engines</a></li><li><a href="#os">os</a></li><li><a href="#cpu">cpu</a></li><li><a href="#libc">libc</a></li><li><a href="#devengines">devEngines</a></li><li><a href="#private">private</a></li><li><a href="#publishconfig">publishConfig</a></li><li><a href="#workspaces">workspaces</a></li><li><a href="#default-values">DEFAULT VALUES</a></li><li><a href="#see-also">SEE ALSO</a></li></ul></div>
</section>
<div id="_content"><h3 id="description">Description</h3>
@@ -418,7 +418,7 @@ If there is a <code>.gitignore</code> file, and <code>.npmignore</code> is missi
<li><code>config.gypi</code></li>
<li><code>node_modules</code></li>
<li><code>npm-debug.log</code></li>
-<li><code>package-lock.json</code> (use <a href="../configuring-npm/npm-shrinkwrap-json.html"><code>npm-shrinkwrap.json</code></a> if you wish it to be published)</li>
+<li><code>package-lock.json</code></li>
<li><code>pnpm-lock.yaml</code></li>
<li><code>yarn.lock</code></li>
<li><code>bun.lockb</code></li>
@@ -485,8 +485,11 @@ For example:</p>
<p>Note that you can also set the executable files using <a href="#directoriesbin">directories.bin</a>.</p>
<p>See <a href="../configuring-npm/folders#executables.html">folders</a> for more info on executables.</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>
-<p>If only a single file is provided, then it's installed such that it is the result from <code>man <pkgname></code>, regardless of its actual filename.
+<blockquote>
+<p><strong>Note:</strong> As of npm v12, man pages are no longer registered with the system <code>man</code> program. This field is retained for backward compatibility with package metadata and tools that consume it, but <code>man <pkgname></code> will not work after a global install. Use <code>npm help <pkgname></code> instead where supported.</p>
+</blockquote>
+<p>Specify either a single file or an array of filenames to include as man pages.</p>
+<p>If only a single file is provided, then it corresponds to <code>man <pkgname></code>, regardless of its actual filename.
For example:</p>
<pre><code class="language-json">{
"name": "foo",
@@ -496,7 +499,7 @@ For example:</p>
"man": "./man/doc.1"
}
</code></pre>
-<p>would link the <code>./man/doc.1</code> file in such that it is the target for <code>man foo</code></p>
+<p>would associate the <code>./man/doc.1</code> file such that it is the target for <code>man foo</code></p>
<p>If the filename doesn't start with the package name, then it's prefixed.
So, this:</p>
<pre><code class="language-json">{
@@ -510,9 +513,9 @@ So, this:</p>
]
}
</code></pre>
-<p>will create files to do <code>man foo</code> and <code>man foo-bar</code>.</p>
+<p>will correspond to <code>man foo</code> and <code>man foo-bar</code>.</p>
<p>Man files must end with a number, and optionally a <code>.gz</code> suffix if they are compressed.
-The number dictates which man section the file is installed into.</p>
+The number dictates which man section the file belongs to.</p>
<pre><code class="language-json">{
"name": "foo",
"version": "1.2.3",
@@ -535,7 +538,7 @@ If you look at <a href="https://registry.npmjs.org/npm/latest">npm's package.jso
If you want to specify individual files, use <code>bin</code>, and for all the files in an existing <code>bin</code> directory, use <code>directories.bin</code>.</p>
<h4 id="directoriesman">directories.man</h4>
<p>A folder that is full of man pages.
-Sugar to generate a "man" array by walking the folder.</p>
+Sugar to generate a "man" array by walking the folder. See the note on <a href="#man"><code>man</code></a> above: as of npm v12, these are no longer installed into the system <code>man</code> path.</p>
<h3 id="repository">repository</h3>
<p>Specify the place where your code lives.
This is helpful for people who want to contribute.
@@ -805,6 +808,13 @@ A value of <code>true</code> will bundle all dependencies, a value of <code>fals
This is a map of package name to version or URL, just like the <code>dependencies</code> object.
The difference is that build failures do not cause installation to fail.
Running <code>npm install --omit=optional</code> will prevent these dependencies from being installed.</p>
+<p>For example:</p>
+<pre><code class="language-json">{
+ "optionalDependencies": {
+ "@npm/foo": "^1.0.0"
+ }
+}
+</code></pre>
<p>It is still your program's responsibility to handle the lack of the dependency.
For example, something like this:</p>
<pre><code class="language-js">try {
@@ -830,7 +840,7 @@ if (foo) {
These changes can be scoped as specific or as vague as desired.</p>
<p>Overrides are only considered in the root <code>package.json</code> file for a project.
Overrides in installed dependencies (including <a href="../using-npm/workspaces.html">workspaces</a>) are not considered in dependency tree resolution.
-Published packages may dictate their resolutions by pinning dependencies or using an <a href="../configuring-npm/npm-shrinkwrap-json.html"><code>npm-shrinkwrap.json</code></a> file.</p>
+Published packages may dictate their resolutions by pinning dependencies or using <a href="#bundledependencies"><code>bundleDependencies</code></a>.</p>
<p>To make sure the package <code>@npm/foo</code> is always installed as version <code>1.0.0</code> no matter what version your dependencies rely on:</p>
<pre><code class="language-json">{
"overrides": {
@@ -942,6 +952,56 @@ For example, to replace a transitive dependency with a fork:</p>
}
}
</code></pre>
+<h3 id="packageextensions">packageExtensions</h3>
+<p><code>packageExtensions</code> lets a project apply small, declarative repairs to the manifests of third-party dependencies before npm resolves the dependency tree.
+Use it to add a missing <code>dependencies</code>, <code>optionalDependencies</code>, or <code>peerDependencies</code> entry, or to correct <code>peerDependencies</code> and <code>peerDependenciesMeta</code>, while you wait for the upstream package to publish a fix.</p>
+<p>This is especially useful with <a href="../using-npm/config#install-strategy.html"><code>install-strategy=linked</code></a>, where dependencies are fully isolated and a package only sees what it actually declared.
+A package that worked under a hoisted layout because a dependency happened to be hoisted above it can fail under <code>linked</code>; <code>packageExtensions</code> records the missing edge as explicit, reviewable, root-owned policy.</p>
+<p><code>packageExtensions</code> complements <a href="#overrides"><code>overrides</code></a>: <code>overrides</code> changes what an existing dependency edge resolves to, while <code>packageExtensions</code> adds or corrects the dependency metadata that creates the edge in the first place.
+For changing the resolved version of a dependency that is already declared, use <code>overrides</code>.</p>
+<p>Like <code>overrides</code>, <code>packageExtensions</code> is only honored in the root <code>package.json</code> of a project (the workspace root in a workspace).
+The field in installed dependencies and in non-root workspace packages is ignored.
+Because it is root-only project policy, npm refuses to publish a non-private package that contains <code>packageExtensions</code>; it remains available to private packages and unpublished local projects.</p>
+<p>Each key is a package selector: a package name with an optional semver range.</p>
+<pre><code class="language-json">{
+ "packageExtensions": {
+ "broken-package@1": {
+ "dependencies": {
+ "missing-runtime-dep": "^2.0.0"
+ }
+ },
+ "typescript-plugin@4.3.0": {
+ "peerDependencies": {
+ "typescript": ">=5"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "@scope/uses-types@2": {
+ "dependencies": {
+ "@types/node": "^22.0.0"
+ }
+ }
+ }
+}
+</code></pre>
+<ul>
+<li><code>"foo"</code> matches all versions of <code>foo</code>.</li>
+<li><code>"foo@1"</code> matches versions satisfying <code>1</code>.</li>
+<li><code>"@scope/foo@^2.3.0"</code> matches versions satisfying <code>^2.3.0</code>.</li>
+</ul>
+<p>Selectors match a candidate package's own <code>name</code> and <code>version</code>. They do not accept dist-tags, git, file, directory, URL, or <code>npm:</code> alias specs. For aliases, the selector matches the underlying package name. At most one selector may match a given package; overlapping selectors that both match the same package fail the install.</p>
+<p>Only <code>dependencies</code>, <code>optionalDependencies</code>, <code>peerDependencies</code>, and <code>peerDependenciesMeta</code> may be extended. The merge rules are:</p>
+<ul>
+<li><code>dependencies</code> and <code>optionalDependencies</code> entries add a missing dependency only. Adding a name that the package already declares in either field is an error; use <code>overrides</code> to change a version.</li>
+<li><code>peerDependencies</code> entries are merged by name, replacing an existing range.</li>
+<li><code>peerDependenciesMeta</code> entries are merged by name and then by key, so you can add <code>optional: true</code> without dropping other metadata. Every <code>peerDependenciesMeta</code> entry must correspond to a <code>peerDependencies</code> entry.</li>
+</ul>
+<p>Deletion is not supported; a <code>null</code>, <code>false</code>, or <code>"-"</code> value is an error.</p>
+<p><code>packageExtensions</code> does not rewrite the installed package's <code>package.json</code> on disk and does not modify <code>bundleDependencies</code>. Affected packages are recorded in <code>package-lock.json</code> and surfaced by <a href="../commands/npm-explain.html"><code>npm explain</code></a> and <a href="../commands/npm-ls.html"><code>npm ls</code></a>, so each repair is easy to audit and to remove once upstream is fixed.</p>
<h3 id="engines">engines</h3>
<p>You can specify the version of node that your stuff works on:</p>
<pre><code class="language-json">{
diff --git a/deps/npm/docs/output/configuring-npm/npm-shrinkwrap-json.html b/deps/npm/docs/output/configuring-npm/npm-shrinkwrap-json.html
deleted file mode 100644
index 134524b16af..00000000000
--- a/deps/npm/docs/output/configuring-npm/npm-shrinkwrap-json.html
+++ /dev/null
@@ -1,229 +0,0 @@
-<!DOCTYPE html><html><head>
-<meta charset="utf-8">
-<title>npm-shrinkwrap.json</title>
-<style>
-body {
- background-color: #ffffff;
- color: #24292e;
-
- margin: 0;
-
- line-height: 1.5;
-
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
-}
-#rainbar {
- height: 10px;
- background-image: linear-gradient(139deg, #fb8817, #ff4b01, #c12127, #e02aff);
-}
-
-a {
- text-decoration: none;
- color: #0366d6;
-}
-a:hover {
- text-decoration: underline;
-}
-
-pre {
- margin: 1em 0px;
- padding: 1em;
- border: solid 1px #e1e4e8;
- border-radius: 6px;
-
- display: block;
- overflow: auto;
-
- white-space: pre;
-
- background-color: #f6f8fa;
- color: #393a34;
-}
-code {
- font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace;
- font-size: 85%;
- padding: 0.2em 0.4em;
- background-color: #f6f8fa;
- color: #393a34;
-}
-pre > code {
- padding: 0;
- background-color: inherit;
- color: inherit;
-}
-h1, h2, h3 {
- font-weight: 600;
-}
-
-#logobar {
- background-color: #333333;
- margin: 0 auto;
- padding: 1em 4em;
-}
-#logobar .logo {
- float: left;
-}
-#logobar .title {
- font-weight: 600;
- color: #dddddd;
- float: left;
- margin: 5px 0 0 1em;
-}
-#logobar:after {
- content: "";
- display: block;
- clear: both;
-}
-
-#content {
- margin: 0 auto;
- padding: 0 4em;
-}
-
-#table_of_contents > h2 {
- font-size: 1.17em;
-}
-#table_of_contents ul:first-child {
- border: solid 1px #e1e4e8;
- border-radius: 6px;
- padding: 1em;
- background-color: #f6f8fa;
- color: #393a34;
-}
-#table_of_contents ul {
- list-style-type: none;
- padding-left: 1.5em;
-}
-#table_of_contents li {
- font-size: 0.9em;
-}
-#table_of_contents li a {
- color: #000000;
-}
-
-header.title {
- border-bottom: solid 1px #e1e4e8;
-}
-header.title > h1 {
- margin-bottom: 0.25em;
-}
-header.title > .description {
- display: block;
- margin-bottom: 0.5em;
- line-height: 1;
-}
-
-header.title .version {
- font-size: 0.8em;
- color: #666666;
-}
-
-footer#edit {
- border-top: solid 1px #e1e4e8;
- margin: 3em 0 4em 0;
- padding-top: 2em;
-}
-
-table {
- width: 100%;
- margin: 1em 0;
- border-radius: 6px;
- border: 1px solid #e1e4e8;
- overflow: hidden;
- border-collapse: separate;
- border-spacing: 0;
-}
-
-table thead {
- background-color: #f6f8fa;
-}
-
-table tbody {
- background-color: #ffffff;
-}
-
-table th,
-table td {
- padding: 0.75em;
- text-align: left;
- border-right: 1px solid #e1e4e8;
- border-bottom: 1px solid #e1e4e8;
-}
-
-table th:last-child,
-table td:last-child {
- border-right: none;
-}
-
-table tbody tr:last-child td {
- border-bottom: none;
-}
-
-table th {
- font-weight: 600;
- background-color: #f6f8fa;
-}
-
-table code {
- white-space: nowrap;
-}
-
-</style>
-</head>
-<body>
-<div id="banner">
-<div id="rainbar"></div>
-<div id="logobar">
-<svg class="logo" role="img" height="32" width="32" viewBox="0 0 700 700">
-<polygon fill="#cb0000" points="0,700 700,700 700,0 0,0"></polygon>
-<polygon fill="#ffffff" points="150,550 350,550 350,250 450,250 450,550 550,550 550,150 150,150"></polygon>
-</svg>
-<div class="title">
-npm command-line interface
-</div>
-</div>
-</div>
-
-<section id="content">
-<header class="title">
-<h1 id="----npm-shrinkwrapjson----11191">
- <span>npm-shrinkwrap.json</span>
- <span class="version">@11.19.1</span>
-</h1>
-<span class="description">A publishable lockfile</span>
-</header>
-
-<section id="table_of_contents">
-<h2 id="table-of-contents">Table of contents</h2>
-<div id="_table_of_contents"><ul><li><a href="#description">Description</a></li><li><a href="#see-also">See also</a></li></ul></div>
-</section>
-
-<div id="_content"><h3 id="description">Description</h3>
-<p><code>npm-shrinkwrap.json</code> is a file created by <a href="../commands/npm-shrinkwrap.html"><code>npm shrinkwrap</code></a>.
-It is identical to <code>package-lock.json</code>, with one major caveat: Unlike <code>package-lock.json</code>,
-<code>npm-shrinkwrap.json</code> may be included when publishing a package.</p>
-<p>The recommended use-case for <code>npm-shrinkwrap.json</code> is applications deployed through the publishing process on the registry: for example, daemons and command-line tools intended as global installs or <code>devDependencies</code>.
-It's strongly discouraged for library authors to publish this file, since that would prevent end users from having control over transitive dependency updates.</p>
-<p>If both <code>package-lock.json</code> and <code>npm-shrinkwrap.json</code> are present in a package root, <code>npm-shrinkwrap.json</code> will be preferred over the <code>package-lock.json</code> file.</p>
-<p>For full details and description of the <code>npm-shrinkwrap.json</code> file format, refer to the manual page for <a href="../configuring-npm/package-lock-json.html">package-lock.json</a>.</p>
-<h3 id="see-also">See also</h3>
-<ul>
-<li><a href="../commands/npm-shrinkwrap.html">npm shrinkwrap</a></li>
-<li><a href="../configuring-npm/package-lock-json.html">package-lock.json</a></li>
-<li><a href="../configuring-npm/package-json.html">package.json</a></li>
-<li><a href="../commands/npm-install.html">npm install</a></li>
-</ul></div>
-
-<footer id="edit">
-<a href="https://github.com/npm/cli/edit/latest/docs/lib/content/configuring-npm/npm-shrinkwrap-json.md">
-<svg role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentcolor" style="vertical-align: text-bottom; margin-right: 0.3em;">
-<path fill-rule="evenodd" d="M11.013 1.427a1.75 1.75 0 012.474 0l1.086 1.086a1.75 1.75 0 010 2.474l-8.61 8.61c-.21.21-.47.364-.756.445l-3.251.93a.75.75 0 01-.927-.928l.929-3.25a1.75 1.75 0 01.445-.758l8.61-8.61zm1.414 1.06a.25.25 0 00-.354 0L10.811 3.75l1.439 1.44 1.263-1.263a.25.25 0 000-.354l-1.086-1.086zM11.189 6.25L9.75 4.81l-6.286 6.287a.25.25 0 00-.064.108l-.558 1.953 1.953-.558a.249.249 0 00.108-.064l6.286-6.286z"></path>
-</svg>
-Edit this page on GitHub
-</a>
-</footer>
-</section>
-
-
-
-</body></html>
\ No newline at end of file
diff --git a/deps/npm/docs/output/configuring-npm/npmrc.html b/deps/npm/docs/output/configuring-npm/npmrc.html
index a5eb291b57c..5ac70ba1ba7 100644
--- a/deps/npm/docs/output/configuring-npm/npmrc.html
+++ b/deps/npm/docs/output/configuring-npm/npmrc.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----npmrc----11191">
+<h1 id="----npmrc----1210">
<span>.npmrc</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">The npm config files</span>
</header>
diff --git a/deps/npm/docs/output/configuring-npm/package-json.html b/deps/npm/docs/output/configuring-npm/package-json.html
index 97a03a6d617..148a01c926b 100644
--- a/deps/npm/docs/output/configuring-npm/package-json.html
+++ b/deps/npm/docs/output/configuring-npm/package-json.html
@@ -186,16 +186,16 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----packagejson----11191">
+<h1 id="----packagejson----1210">
<span>package.json</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Specifics of npm's package.json handling</span>
</header>
<section id="table_of_contents">
<h2 id="table-of-contents">Table of contents</h2>
-<div id="_table_of_contents"><ul><li><a href="#description">Description</a></li><li><a href="#name">name</a></li><li><a href="#version">version</a></li><li><a href="#description2">description</a></li><li><a href="#keywords">keywords</a></li><li><a href="#homepage">homepage</a></li><li><a href="#bugs">bugs</a></li><li><a href="#license">license</a></li><li><a href="#people-fields-author-contributors">people fields: author, contributors</a></li><li><a href="#funding">funding</a></li><li><a href="#files">files</a></li><li><a href="#exports">exports</a></li><li><a href="#main">main</a></li><li><a href="#type">type</a></li><li><a href="#browser">browser</a></li><li><a href="#bin">bin</a></li><li><a href="#man">man</a></li><li><a href="#directories">directories</a></li><ul><li><a href="#directoriesbin">directories.bin</a></li><li><a href="#directoriesman">directories.man</a></li></ul><li><a href="#repository">repository</a></li><li><a href="#scripts">scripts</a></li><li><a href="#gypfile">gypfile</a></li><li><a href="#config">config</a></li><li><a href="#dependencies">dependencies</a></li><ul><li><a href="#urls-as-dependencies">URLs as Dependencies</a></li><li><a href="#git-urls-as-dependencies">Git URLs as Dependencies</a></li><li><a href="#github-urls">GitHub URLs</a></li><li><a href="#local-paths">Local Paths</a></li></ul><li><a href="#devdependencies">devDependencies</a></li><li><a href="#peerdependencies">peerDependencies</a></li><li><a href="#peerdependenciesmeta">peerDependenciesMeta</a></li><li><a href="#bundledependencies">bundleDependencies</a></li><li><a href="#optionaldependencies">optionalDependencies</a></li><li><a href="#overrides">overrides</a></li><ul><li><a href="#replacing-a-dependency-with-a-fork">Replacing a dependency with a fork</a></li></ul><li><a href="#engines">engines</a></li><li><a href="#os">os</a></li><li><a href="#cpu">cpu</a></li><li><a href="#libc">libc</a></li><li><a href="#devengines">devEngines</a></li><li><a href="#private">private</a></li><li><a href="#publishconfig">publishConfig</a></li><li><a href="#workspaces">workspaces</a></li><li><a href="#default-values">DEFAULT VALUES</a></li><li><a href="#see-also">SEE ALSO</a></li></ul></div>
+<div id="_table_of_contents"><ul><li><a href="#description">Description</a></li><li><a href="#name">name</a></li><li><a href="#version">version</a></li><li><a href="#description2">description</a></li><li><a href="#keywords">keywords</a></li><li><a href="#homepage">homepage</a></li><li><a href="#bugs">bugs</a></li><li><a href="#license">license</a></li><li><a href="#people-fields-author-contributors">people fields: author, contributors</a></li><li><a href="#funding">funding</a></li><li><a href="#files">files</a></li><li><a href="#exports">exports</a></li><li><a href="#main">main</a></li><li><a href="#type">type</a></li><li><a href="#browser">browser</a></li><li><a href="#bin">bin</a></li><li><a href="#man">man</a></li><li><a href="#directories">directories</a></li><ul><li><a href="#directoriesbin">directories.bin</a></li><li><a href="#directoriesman">directories.man</a></li></ul><li><a href="#repository">repository</a></li><li><a href="#scripts">scripts</a></li><li><a href="#gypfile">gypfile</a></li><li><a href="#config">config</a></li><li><a href="#dependencies">dependencies</a></li><ul><li><a href="#urls-as-dependencies">URLs as Dependencies</a></li><li><a href="#git-urls-as-dependencies">Git URLs as Dependencies</a></li><li><a href="#github-urls">GitHub URLs</a></li><li><a href="#local-paths">Local Paths</a></li></ul><li><a href="#devdependencies">devDependencies</a></li><li><a href="#peerdependencies">peerDependencies</a></li><li><a href="#peerdependenciesmeta">peerDependenciesMeta</a></li><li><a href="#bundledependencies">bundleDependencies</a></li><li><a href="#optionaldependencies">optionalDependencies</a></li><li><a href="#overrides">overrides</a></li><ul><li><a href="#replacing-a-dependency-with-a-fork">Replacing a dependency with a fork</a></li></ul><li><a href="#packageextensions">packageExtensions</a></li><li><a href="#engines">engines</a></li><li><a href="#os">os</a></li><li><a href="#cpu">cpu</a></li><li><a href="#libc">libc</a></li><li><a href="#devengines">devEngines</a></li><li><a href="#private">private</a></li><li><a href="#publishconfig">publishConfig</a></li><li><a href="#workspaces">workspaces</a></li><li><a href="#default-values">DEFAULT VALUES</a></li><li><a href="#see-also">SEE ALSO</a></li></ul></div>
</section>
<div id="_content"><h3 id="description">Description</h3>
@@ -418,7 +418,7 @@ If there is a <code>.gitignore</code> file, and <code>.npmignore</code> is missi
<li><code>config.gypi</code></li>
<li><code>node_modules</code></li>
<li><code>npm-debug.log</code></li>
-<li><code>package-lock.json</code> (use <a href="../configuring-npm/npm-shrinkwrap-json.html"><code>npm-shrinkwrap.json</code></a> if you wish it to be published)</li>
+<li><code>package-lock.json</code></li>
<li><code>pnpm-lock.yaml</code></li>
<li><code>yarn.lock</code></li>
<li><code>bun.lockb</code></li>
@@ -485,8 +485,11 @@ For example:</p>
<p>Note that you can also set the executable files using <a href="#directoriesbin">directories.bin</a>.</p>
<p>See <a href="../configuring-npm/folders#executables.html">folders</a> for more info on executables.</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>
-<p>If only a single file is provided, then it's installed such that it is the result from <code>man <pkgname></code>, regardless of its actual filename.
+<blockquote>
+<p><strong>Note:</strong> As of npm v12, man pages are no longer registered with the system <code>man</code> program. This field is retained for backward compatibility with package metadata and tools that consume it, but <code>man <pkgname></code> will not work after a global install. Use <code>npm help <pkgname></code> instead where supported.</p>
+</blockquote>
+<p>Specify either a single file or an array of filenames to include as man pages.</p>
+<p>If only a single file is provided, then it corresponds to <code>man <pkgname></code>, regardless of its actual filename.
For example:</p>
<pre><code class="language-json">{
"name": "foo",
@@ -496,7 +499,7 @@ For example:</p>
"man": "./man/doc.1"
}
</code></pre>
-<p>would link the <code>./man/doc.1</code> file in such that it is the target for <code>man foo</code></p>
+<p>would associate the <code>./man/doc.1</code> file such that it is the target for <code>man foo</code></p>
<p>If the filename doesn't start with the package name, then it's prefixed.
So, this:</p>
<pre><code class="language-json">{
@@ -510,9 +513,9 @@ So, this:</p>
]
}
</code></pre>
-<p>will create files to do <code>man foo</code> and <code>man foo-bar</code>.</p>
+<p>will correspond to <code>man foo</code> and <code>man foo-bar</code>.</p>
<p>Man files must end with a number, and optionally a <code>.gz</code> suffix if they are compressed.
-The number dictates which man section the file is installed into.</p>
+The number dictates which man section the file belongs to.</p>
<pre><code class="language-json">{
"name": "foo",
"version": "1.2.3",
@@ -535,7 +538,7 @@ If you look at <a href="https://registry.npmjs.org/npm/latest">npm's package.jso
If you want to specify individual files, use <code>bin</code>, and for all the files in an existing <code>bin</code> directory, use <code>directories.bin</code>.</p>
<h4 id="directoriesman">directories.man</h4>
<p>A folder that is full of man pages.
-Sugar to generate a "man" array by walking the folder.</p>
+Sugar to generate a "man" array by walking the folder. See the note on <a href="#man"><code>man</code></a> above: as of npm v12, these are no longer installed into the system <code>man</code> path.</p>
<h3 id="repository">repository</h3>
<p>Specify the place where your code lives.
This is helpful for people who want to contribute.
@@ -805,6 +808,13 @@ A value of <code>true</code> will bundle all dependencies, a value of <code>fals
This is a map of package name to version or URL, just like the <code>dependencies</code> object.
The difference is that build failures do not cause installation to fail.
Running <code>npm install --omit=optional</code> will prevent these dependencies from being installed.</p>
+<p>For example:</p>
+<pre><code class="language-json">{
+ "optionalDependencies": {
+ "@npm/foo": "^1.0.0"
+ }
+}
+</code></pre>
<p>It is still your program's responsibility to handle the lack of the dependency.
For example, something like this:</p>
<pre><code class="language-js">try {
@@ -830,7 +840,7 @@ if (foo) {
These changes can be scoped as specific or as vague as desired.</p>
<p>Overrides are only considered in the root <code>package.json</code> file for a project.
Overrides in installed dependencies (including <a href="../using-npm/workspaces.html">workspaces</a>) are not considered in dependency tree resolution.
-Published packages may dictate their resolutions by pinning dependencies or using an <a href="../configuring-npm/npm-shrinkwrap-json.html"><code>npm-shrinkwrap.json</code></a> file.</p>
+Published packages may dictate their resolutions by pinning dependencies or using <a href="#bundledependencies"><code>bundleDependencies</code></a>.</p>
<p>To make sure the package <code>@npm/foo</code> is always installed as version <code>1.0.0</code> no matter what version your dependencies rely on:</p>
<pre><code class="language-json">{
"overrides": {
@@ -942,6 +952,56 @@ For example, to replace a transitive dependency with a fork:</p>
}
}
</code></pre>
+<h3 id="packageextensions">packageExtensions</h3>
+<p><code>packageExtensions</code> lets a project apply small, declarative repairs to the manifests of third-party dependencies before npm resolves the dependency tree.
+Use it to add a missing <code>dependencies</code>, <code>optionalDependencies</code>, or <code>peerDependencies</code> entry, or to correct <code>peerDependencies</code> and <code>peerDependenciesMeta</code>, while you wait for the upstream package to publish a fix.</p>
+<p>This is especially useful with <a href="../using-npm/config#install-strategy.html"><code>install-strategy=linked</code></a>, where dependencies are fully isolated and a package only sees what it actually declared.
+A package that worked under a hoisted layout because a dependency happened to be hoisted above it can fail under <code>linked</code>; <code>packageExtensions</code> records the missing edge as explicit, reviewable, root-owned policy.</p>
+<p><code>packageExtensions</code> complements <a href="#overrides"><code>overrides</code></a>: <code>overrides</code> changes what an existing dependency edge resolves to, while <code>packageExtensions</code> adds or corrects the dependency metadata that creates the edge in the first place.
+For changing the resolved version of a dependency that is already declared, use <code>overrides</code>.</p>
+<p>Like <code>overrides</code>, <code>packageExtensions</code> is only honored in the root <code>package.json</code> of a project (the workspace root in a workspace).
+The field in installed dependencies and in non-root workspace packages is ignored.
+Because it is root-only project policy, npm refuses to publish a non-private package that contains <code>packageExtensions</code>; it remains available to private packages and unpublished local projects.</p>
+<p>Each key is a package selector: a package name with an optional semver range.</p>
+<pre><code class="language-json">{
+ "packageExtensions": {
+ "broken-package@1": {
+ "dependencies": {
+ "missing-runtime-dep": "^2.0.0"
+ }
+ },
+ "typescript-plugin@4.3.0": {
+ "peerDependencies": {
+ "typescript": ">=5"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "@scope/uses-types@2": {
+ "dependencies": {
+ "@types/node": "^22.0.0"
+ }
+ }
+ }
+}
+</code></pre>
+<ul>
+<li><code>"foo"</code> matches all versions of <code>foo</code>.</li>
+<li><code>"foo@1"</code> matches versions satisfying <code>1</code>.</li>
+<li><code>"@scope/foo@^2.3.0"</code> matches versions satisfying <code>^2.3.0</code>.</li>
+</ul>
+<p>Selectors match a candidate package's own <code>name</code> and <code>version</code>. They do not accept dist-tags, git, file, directory, URL, or <code>npm:</code> alias specs. For aliases, the selector matches the underlying package name. At most one selector may match a given package; overlapping selectors that both match the same package fail the install.</p>
+<p>Only <code>dependencies</code>, <code>optionalDependencies</code>, <code>peerDependencies</code>, and <code>peerDependenciesMeta</code> may be extended. The merge rules are:</p>
+<ul>
+<li><code>dependencies</code> and <code>optionalDependencies</code> entries add a missing dependency only. Adding a name that the package already declares in either field is an error; use <code>overrides</code> to change a version.</li>
+<li><code>peerDependencies</code> entries are merged by name, replacing an existing range.</li>
+<li><code>peerDependenciesMeta</code> entries are merged by name and then by key, so you can add <code>optional: true</code> without dropping other metadata. Every <code>peerDependenciesMeta</code> entry must correspond to a <code>peerDependencies</code> entry.</li>
+</ul>
+<p>Deletion is not supported; a <code>null</code>, <code>false</code>, or <code>"-"</code> value is an error.</p>
+<p><code>packageExtensions</code> does not rewrite the installed package's <code>package.json</code> on disk and does not modify <code>bundleDependencies</code>. Affected packages are recorded in <code>package-lock.json</code> and surfaced by <a href="../commands/npm-explain.html"><code>npm explain</code></a> and <a href="../commands/npm-ls.html"><code>npm ls</code></a>, so each repair is easy to audit and to remove once upstream is fixed.</p>
<h3 id="engines">engines</h3>
<p>You can specify the version of node that your stuff works on:</p>
<pre><code class="language-json">{
diff --git a/deps/npm/docs/output/configuring-npm/package-lock-json.html b/deps/npm/docs/output/configuring-npm/package-lock-json.html
index 9a4f1631b33..487bc1eef8f 100644
--- a/deps/npm/docs/output/configuring-npm/package-lock-json.html
+++ b/deps/npm/docs/output/configuring-npm/package-lock-json.html
@@ -186,16 +186,16 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----package-lockjson----11191">
+<h1 id="----package-lockjson----1210">
<span>package-lock.json</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">A manifestation of the manifest</span>
</header>
<section id="table_of_contents">
<h2 id="table-of-contents">Table of contents</h2>
-<div id="_table_of_contents"><ul><li><a href="#description">Description</a></li><li><a href="#package-lockjson-vs-npm-shrinkwrapjson"><code>package-lock.json</code> vs <code>npm-shrinkwrap.json</code></a></li><li><a href="#hidden-lockfiles">Hidden Lockfiles</a></li><li><a href="#handling-old-lockfiles">Handling Old Lockfiles</a></li><li><a href="#file-format">File Format</a></li><ul><li><a href="#name"><code>name</code></a></li><li><a href="#version"><code>version</code></a></li><li><a href="#lockfileversion"><code>lockfileVersion</code></a></li><li><a href="#packages"><code>packages</code></a></li><li><a href="#dependencies">dependencies</a></li></ul><li><a href="#see-also">See also</a></li></ul></div>
+<div id="_table_of_contents"><ul><li><a href="#description">Description</a></li><li><a href="#npm-shrinkwrapjson"><code>npm-shrinkwrap.json</code></a></li><li><a href="#hidden-lockfiles">Hidden Lockfiles</a></li><li><a href="#handling-old-lockfiles">Handling Old Lockfiles</a></li><li><a href="#file-format">File Format</a></li><ul><li><a href="#name"><code>name</code></a></li><li><a href="#version"><code>version</code></a></li><li><a href="#lockfileversion"><code>lockfileVersion</code></a></li><li><a href="#packages"><code>packages</code></a></li><li><a href="#dependencies">dependencies</a></li></ul><li><a href="#see-also">See also</a></li></ul></div>
</section>
<div id="_content"><h3 id="description">Description</h3>
@@ -220,12 +220,15 @@ It describes the exact tree that was generated, such that subsequent installs ar
</li>
</ul>
<p>When <code>npm</code> creates or updates <code>package-lock.json</code>, it will infer line endings and indentation from <code>package.json</code> so that the formatting of both files matches.</p>
-<h3 id="package-lockjson-vs-npm-shrinkwrapjson"><code>package-lock.json</code> vs <code>npm-shrinkwrap.json</code></h3>
-<p>Both of these files have the same format, and perform similar functions in the root of a project.</p>
-<p>The difference is that <code>package-lock.json</code> cannot be published, and it will be ignored if found in any place other than the root project.</p>
-<p>In contrast, <a href="../configuring-npm/npm-shrinkwrap-json.html">npm-shrinkwrap.json</a> allows publication, and defines the dependency tree from the point encountered.
-This is not recommended unless deploying a CLI tool or otherwise using the publication process for producing production packages.</p>
-<p>If both <code>package-lock.json</code> and <code>npm-shrinkwrap.json</code> are present in the root of a project, <code>npm-shrinkwrap.json</code> will take precedence and <code>package-lock.json</code> will be ignored.</p>
+<h3 id="npm-shrinkwrapjson"><code>npm-shrinkwrap.json</code></h3>
+<p>As of npm v12, <code>npm-shrinkwrap.json</code> is no longer read or written by
+npm. Projects that previously committed <code>npm-shrinkwrap.json</code> should
+rename it to <code>package-lock.json</code>; the file format is identical. When
+npm v12 encounters a dependency that ships an <code>npm-shrinkwrap.json</code>
+inside its tarball, the file is ignored — publishers who need to ship
+a locked tree should use
+<a href="../configuring-npm/package-json#bundledependencies.html"><code>bundleDependencies</code></a>
+instead.</p>
<h3 id="hidden-lockfiles">Hidden Lockfiles</h3>
<p>In order to avoid processing the <code>node_modules</code> folder repeatedly, npm as of v7 uses a "hidden" lockfile present in <code>node_modules/.package-lock.json</code>.
This contains information about the tree, and is used in lieu of reading the entire <code>node_modules</code> hierarchy provided that the following conditions are met:</p>
@@ -255,7 +258,7 @@ This will match what's in <code>package.json</code>.</p>
<p>Note that the file format changed significantly in npm v7 to track information that would have otherwise required looking in <code>node_modules</code> or the npm registry.
Lockfiles generated by npm v7 will contain <code>lockfileVersion: 2</code>.</p>
<ul>
-<li>No version provided: an "ancient" shrinkwrap file from a version of npm prior to npm v5.</li>
+<li>No version provided: an "ancient" lockfile from a version of npm prior to npm v5.</li>
<li><code>1</code>: The lockfile version used by npm v5 and v6.</li>
<li><code>2</code>: The lockfile version used by npm v7 and v8. Backwards compatible to v1 lockfiles.</li>
<li><code>3</code>: The lockfile version used by npm v9 and above.
@@ -298,9 +301,6 @@ If it is both a <code>dev</code> dependency <em>and</em> an <code>optional</code
<p>hasInstallScript: A flag to indicate that the package has a <code>preinstall</code>, <code>install</code>, or <code>postinstall</code> script.</p>
</li>
<li>
-<p>hasShrinkwrap: A flag to indicate that the package has an <code>npm-shrinkwrap.json</code> file.</p>
-</li>
-<li>
<p>bin, license, engines, dependencies, optionalDependencies: fields from <code>package.json</code></p>
</li>
<li>
@@ -370,8 +370,6 @@ The version should match via normal matching rules a dependency either in our <c
</ul>
<h3 id="see-also">See also</h3>
<ul>
-<li><a href="../commands/npm-shrinkwrap.html">npm shrinkwrap</a></li>
-<li><a href="../configuring-npm/npm-shrinkwrap-json.html">npm-shrinkwrap.json</a></li>
<li><a href="../configuring-npm/package-json.html">package.json</a></li>
<li><a href="../commands/npm-install.html">npm install</a></li>
</ul></div>
diff --git a/deps/npm/docs/output/using-npm/config.html b/deps/npm/docs/output/using-npm/config.html
index ac5829fba75..d95fa275dff 100644
--- a/deps/npm/docs/output/using-npm/config.html
+++ b/deps/npm/docs/output/using-npm/config.html
@@ -186,16 +186,16 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----config----11191">
+<h1 id="----config----1210">
<span>Config</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">About npm configuration</span>
</header>
<section id="table_of_contents">
<h2 id="table-of-contents">Table of contents</h2>
-<div id="_table_of_contents"><ul><li><a href="#description">Description</a></li><ul><li><a href="#command-line-flags">Command Line Flags</a></li><li><a href="#environment-variables">Environment Variables</a></li><li><a href="#npmrc-files">npmrc Files</a></li><li><a href="#default-configs">Default Configs</a></li></ul><li><a href="#shorthands-and-other-cli-niceties">Shorthands and Other CLI Niceties</a></li><li><a href="#config-settings">Config Settings</a></li><ul><li><a href="#auth"><code>_auth</code></a></li><li><a href="#access"><code>access</code></a></li><li><a href="#all"><code>all</code></a></li><li><a href="#allow-directory"><code>allow-directory</code></a></li><li><a href="#allow-file"><code>allow-file</code></a></li><li><a href="#allow-git"><code>allow-git</code></a></li><li><a href="#allow-remote"><code>allow-remote</code></a></li><li><a href="#allow-same-version"><code>allow-same-version</code></a></li><li><a href="#allow-scripts"><code>allow-scripts</code></a></li><li><a href="#allow-scripts-pending"><code>allow-scripts-pending</code></a></li><li><a href="#allow-scripts-pin"><code>allow-scripts-pin</code></a></li><li><a href="#audit"><code>audit</code></a></li><li><a href="#audit-level"><code>audit-level</code></a></li><li><a href="#auth-type"><code>auth-type</code></a></li><li><a href="#before"><code>before</code></a></li><li><a href="#bin-links"><code>bin-links</code></a></li><li><a href="#browser"><code>browser</code></a></li><li><a href="#bypass-2fa"><code>bypass-2fa</code></a></li><li><a href="#ca"><code>ca</code></a></li><li><a href="#cache"><code>cache</code></a></li><li><a href="#cafile"><code>cafile</code></a></li><li><a href="#call"><code>call</code></a></li><li><a href="#cidr"><code>cidr</code></a></li><li><a href="#color"><code>color</code></a></li><li><a href="#commit-hooks"><code>commit-hooks</code></a></li><li><a href="#cpu"><code>cpu</code></a></li><li><a href="#dangerously-allow-all-scripts"><code>dangerously-allow-all-scripts</code></a></li><li><a href="#depth"><code>depth</code></a></li><li><a href="#description2"><code>description</code></a></li><li><a href="#diff"><code>diff</code></a></li><li><a href="#diff-dst-prefix"><code>diff-dst-prefix</code></a></li><li><a href="#diff-ignore-all-space"><code>diff-ignore-all-space</code></a></li><li><a href="#diff-name-only"><code>diff-name-only</code></a></li><li><a href="#diff-no-prefix"><code>diff-no-prefix</code></a></li><li><a href="#diff-src-prefix"><code>diff-src-prefix</code></a></li><li><a href="#diff-text"><code>diff-text</code></a></li><li><a href="#diff-unified"><code>diff-unified</code></a></li><li><a href="#dry-run"><code>dry-run</code></a></li><li><a href="#editor"><code>editor</code></a></li><li><a href="#engine-strict"><code>engine-strict</code></a></li><li><a href="#expect-result-count"><code>expect-result-count</code></a></li><li><a href="#expect-results"><code>expect-results</code></a></li><li><a href="#expires"><code>expires</code></a></li><li><a href="#fetch-retries"><code>fetch-retries</code></a></li><li><a href="#fetch-retry-factor"><code>fetch-retry-factor</code></a></li><li><a href="#fetch-retry-maxtimeout"><code>fetch-retry-maxtimeout</code></a></li><li><a href="#fetch-retry-mintimeout"><code>fetch-retry-mintimeout</code></a></li><li><a href="#fetch-timeout"><code>fetch-timeout</code></a></li><li><a href="#force"><code>force</code></a></li><li><a href="#foreground-scripts"><code>foreground-scripts</code></a></li><li><a href="#format-package-lock"><code>format-package-lock</code></a></li><li><a href="#fund"><code>fund</code></a></li><li><a href="#git"><code>git</code></a></li><li><a href="#git-tag-version"><code>git-tag-version</code></a></li><li><a href="#global"><code>global</code></a></li><li><a href="#globalconfig"><code>globalconfig</code></a></li><li><a href="#heading"><code>heading</code></a></li><li><a href="#https-proxy"><code>https-proxy</code></a></li><li><a href="#if-present"><code>if-present</code></a></li><li><a href="#ignore-scripts"><code>ignore-scripts</code></a></li><li><a href="#include"><code>include</code></a></li><li><a href="#include-attestations"><code>include-attestations</code></a></li><li><a href="#include-staged"><code>include-staged</code></a></li><li><a href="#include-workspace-root"><code>include-workspace-root</code></a></li><li><a href="#init-author-email"><code>init-author-email</code></a></li><li><a href="#init-author-name"><code>init-author-name</code></a></li><li><a href="#init-author-url"><code>init-author-url</code></a></li><li><a href="#init-license"><code>init-license</code></a></li><li><a href="#init-module"><code>init-module</code></a></li><li><a href="#init-private"><code>init-private</code></a></li><li><a href="#init-type"><code>init-type</code></a></li><li><a href="#init-version"><code>init-version</code></a></li><li><a href="#install-links"><code>install-links</code></a></li><li><a href="#install-strategy"><code>install-strategy</code></a></li><li><a href="#json"><code>json</code></a></li><li><a href="#legacy-peer-deps"><code>legacy-peer-deps</code></a></li><li><a href="#libc"><code>libc</code></a></li><li><a href="#link"><code>link</code></a></li><li><a href="#local-address"><code>local-address</code></a></li><li><a href="#location"><code>location</code></a></li><li><a href="#lockfile-version"><code>lockfile-version</code></a></li><li><a href="#loglevel"><code>loglevel</code></a></li><li><a href="#logs-dir"><code>logs-dir</code></a></li><li><a href="#logs-max"><code>logs-max</code></a></li><li><a href="#long"><code>long</code></a></li><li><a href="#maxsockets"><code>maxsockets</code></a></li><li><a href="#message"><code>message</code></a></li><li><a href="#min-release-age"><code>min-release-age</code></a></li><li><a href="#min-release-age-exclude"><code>min-release-age-exclude</code></a></li><li><a href="#name"><code>name</code></a></li><li><a href="#node-gyp"><code>node-gyp</code></a></li><li><a href="#node-options"><code>node-options</code></a></li><li><a href="#noproxy"><code>noproxy</code></a></li><li><a href="#offline"><code>offline</code></a></li><li><a href="#omit"><code>omit</code></a></li><li><a href="#omit-lockfile-registry-resolved"><code>omit-lockfile-registry-resolved</code></a></li><li><a href="#orgs"><code>orgs</code></a></li><li><a href="#orgs-permission"><code>orgs-permission</code></a></li><li><a href="#os"><code>os</code></a></li><li><a href="#otp"><code>otp</code></a></li><li><a href="#pack-destination"><code>pack-destination</code></a></li><li><a href="#package"><code>package</code></a></li><li><a href="#package-lock"><code>package-lock</code></a></li><li><a href="#package-lock-only"><code>package-lock-only</code></a></li><li><a href="#packages"><code>packages</code></a></li><li><a href="#packages-all"><code>packages-all</code></a></li><li><a href="#packages-and-scopes-permission"><code>packages-and-scopes-permission</code></a></li><li><a href="#parseable"><code>parseable</code></a></li><li><a href="#password"><code>password</code></a></li><li><a href="#prefer-dedupe"><code>prefer-dedupe</code></a></li><li><a href="#prefer-offline"><code>prefer-offline</code></a></li><li><a href="#prefer-online"><code>prefer-online</code></a></li><li><a href="#prefix"><code>prefix</code></a></li><li><a href="#preid"><code>preid</code></a></li><li><a href="#progress"><code>progress</code></a></li><li><a href="#provenance"><code>provenance</code></a></li><li><a href="#provenance-file"><code>provenance-file</code></a></li><li><a href="#proxy"><code>proxy</code></a></li><li><a href="#read-only"><code>read-only</code></a></li><li><a href="#rebuild-bundle"><code>rebuild-bundle</code></a></li><li><a href="#registry"><code>registry</code></a></li><li><a href="#replace-registry-host"><code>replace-registry-host</code></a></li><li><a href="#save"><code>save</code></a></li><li><a href="#save-bundle"><code>save-bundle</code></a></li><li><a href="#save-dev"><code>save-dev</code></a></li><li><a href="#save-exact"><code>save-exact</code></a></li><li><a href="#save-optional"><code>save-optional</code></a></li><li><a href="#save-peer"><code>save-peer</code></a></li><li><a href="#save-prefix"><code>save-prefix</code></a></li><li><a href="#save-prod"><code>save-prod</code></a></li><li><a href="#sbom-format"><code>sbom-format</code></a></li><li><a href="#sbom-type"><code>sbom-type</code></a></li><li><a href="#scope"><code>scope</code></a></li><li><a href="#scopes"><code>scopes</code></a></li><li><a href="#script-shell"><code>script-shell</code></a></li><li><a href="#searchexclude"><code>searchexclude</code></a></li><li><a href="#searchlimit"><code>searchlimit</code></a></li><li><a href="#searchopts"><code>searchopts</code></a></li><li><a href="#searchstaleness"><code>searchstaleness</code></a></li><li><a href="#shell"><code>shell</code></a></li><li><a href="#sign-git-commit"><code>sign-git-commit</code></a></li><li><a href="#sign-git-tag"><code>sign-git-tag</code></a></li><li><a href="#strict-allow-scripts"><code>strict-allow-scripts</code></a></li><li><a href="#strict-peer-deps"><code>strict-peer-deps</code></a></li><li><a href="#strict-ssl"><code>strict-ssl</code></a></li><li><a href="#tag"><code>tag</code></a></li><li><a href="#tag-version-prefix"><code>tag-version-prefix</code></a></li><li><a href="#timing"><code>timing</code></a></li><li><a href="#token-description"><code>token-description</code></a></li><li><a href="#umask"><code>umask</code></a></li><li><a href="#unicode"><code>unicode</code></a></li><li><a href="#update-notifier"><code>update-notifier</code></a></li><li><a href="#usage"><code>usage</code></a></li><li><a href="#user-agent"><code>user-agent</code></a></li><li><a href="#userconfig"><code>userconfig</code></a></li><li><a href="#version"><code>version</code></a></li><li><a href="#versions"><code>versions</code></a></li><li><a href="#viewer"><code>viewer</code></a></li><li><a href="#which"><code>which</code></a></li><li><a href="#workspace"><code>workspace</code></a></li><li><a href="#workspaces"><code>workspaces</code></a></li><li><a href="#workspaces-update"><code>workspaces-update</code></a></li><li><a href="#yes"><code>yes</code></a></li><li><a href="#also"><code>also</code></a></li><li><a href="#cache-max"><code>cache-max</code></a></li><li><a href="#cache-min"><code>cache-min</code></a></li><li><a href="#cert"><code>cert</code></a></li><li><a href="#dev"><code>dev</code></a></li><li><a href="#global-style"><code>global-style</code></a></li><li><a href="#initauthoremail"><code>init.author.email</code></a></li><li><a href="#initauthorname"><code>init.author.name</code></a></li><li><a href="#initauthorurl"><code>init.author.url</code></a></li><li><a href="#initlicense"><code>init.license</code></a></li><li><a href="#initmodule"><code>init.module</code></a></li><li><a href="#initversion"><code>init.version</code></a></li><li><a href="#key"><code>key</code></a></li><li><a href="#legacy-bundling"><code>legacy-bundling</code></a></li><li><a href="#only"><code>only</code></a></li><li><a href="#optional"><code>optional</code></a></li><li><a href="#production"><code>production</code></a></li><li><a href="#shrinkwrap"><code>shrinkwrap</code></a></li></ul><li><a href="#see-also">See also</a></li></ul></div>
+<div id="_table_of_contents"><ul><li><a href="#description">Description</a></li><ul><li><a href="#command-line-flags">Command Line Flags</a></li><li><a href="#environment-variables">Environment Variables</a></li><li><a href="#npmrc-files">npmrc Files</a></li><li><a href="#default-configs">Default Configs</a></li></ul><li><a href="#shorthands-and-other-cli-niceties">Shorthands and Other CLI Niceties</a></li><li><a href="#config-settings">Config Settings</a></li><ul><li><a href="#auth"><code>_auth</code></a></li><li><a href="#access"><code>access</code></a></li><li><a href="#all"><code>all</code></a></li><li><a href="#allow-directory"><code>allow-directory</code></a></li><li><a href="#allow-file"><code>allow-file</code></a></li><li><a href="#allow-git"><code>allow-git</code></a></li><li><a href="#allow-remote"><code>allow-remote</code></a></li><li><a href="#allow-same-version"><code>allow-same-version</code></a></li><li><a href="#allow-scripts"><code>allow-scripts</code></a></li><li><a href="#allow-scripts-pending"><code>allow-scripts-pending</code></a></li><li><a href="#allow-scripts-pin"><code>allow-scripts-pin</code></a></li><li><a href="#allow-unused-patches"><code>allow-unused-patches</code></a></li><li><a href="#audit"><code>audit</code></a></li><li><a href="#audit-level"><code>audit-level</code></a></li><li><a href="#auth-type"><code>auth-type</code></a></li><li><a href="#before"><code>before</code></a></li><li><a href="#bin-links"><code>bin-links</code></a></li><li><a href="#browser"><code>browser</code></a></li><li><a href="#bypass-2fa"><code>bypass-2fa</code></a></li><li><a href="#ca"><code>ca</code></a></li><li><a href="#cache"><code>cache</code></a></li><li><a href="#cafile"><code>cafile</code></a></li><li><a href="#call"><code>call</code></a></li><li><a href="#cidr"><code>cidr</code></a></li><li><a href="#color"><code>color</code></a></li><li><a href="#commit-hooks"><code>commit-hooks</code></a></li><li><a href="#cpu"><code>cpu</code></a></li><li><a href="#dangerously-allow-all-scripts"><code>dangerously-allow-all-scripts</code></a></li><li><a href="#depth"><code>depth</code></a></li><li><a href="#description2"><code>description</code></a></li><li><a href="#diff"><code>diff</code></a></li><li><a href="#diff-dst-prefix"><code>diff-dst-prefix</code></a></li><li><a href="#diff-ignore-all-space"><code>diff-ignore-all-space</code></a></li><li><a href="#diff-name-only"><code>diff-name-only</code></a></li><li><a href="#diff-no-prefix"><code>diff-no-prefix</code></a></li><li><a href="#diff-src-prefix"><code>diff-src-prefix</code></a></li><li><a href="#diff-text"><code>diff-text</code></a></li><li><a href="#diff-unified"><code>diff-unified</code></a></li><li><a href="#dry-run"><code>dry-run</code></a></li><li><a href="#edit-dir"><code>edit-dir</code></a></li><li><a href="#editor"><code>editor</code></a></li><li><a href="#engine-strict"><code>engine-strict</code></a></li><li><a href="#expect-result-count"><code>expect-result-count</code></a></li><li><a href="#expect-results"><code>expect-results</code></a></li><li><a href="#expires"><code>expires</code></a></li><li><a href="#extension-file"><code>extension-file</code></a></li><li><a href="#fetch-retries"><code>fetch-retries</code></a></li><li><a href="#fetch-retry-factor"><code>fetch-retry-factor</code></a></li><li><a href="#fetch-retry-maxtimeout"><code>fetch-retry-maxtimeout</code></a></li><li><a href="#fetch-retry-mintimeout"><code>fetch-retry-mintimeout</code></a></li><li><a href="#fetch-timeout"><code>fetch-timeout</code></a></li><li><a href="#force"><code>force</code></a></li><li><a href="#foreground-scripts"><code>foreground-scripts</code></a></li><li><a href="#format-package-lock"><code>format-package-lock</code></a></li><li><a href="#fund"><code>fund</code></a></li><li><a href="#git"><code>git</code></a></li><li><a href="#git-tag-version"><code>git-tag-version</code></a></li><li><a href="#global"><code>global</code></a></li><li><a href="#global-ignore-file"><code>global-ignore-file</code></a></li><li><a href="#globalconfig"><code>globalconfig</code></a></li><li><a href="#heading"><code>heading</code></a></li><li><a href="#https-proxy"><code>https-proxy</code></a></li><li><a href="#if-present"><code>if-present</code></a></li><li><a href="#ignore-existing"><code>ignore-existing</code></a></li><li><a href="#ignore-extension"><code>ignore-extension</code></a></li><li><a href="#ignore-patch-failures"><code>ignore-patch-failures</code></a></li><li><a href="#ignore-scripts"><code>ignore-scripts</code></a></li><li><a href="#include"><code>include</code></a></li><li><a href="#include-attestations"><code>include-attestations</code></a></li><li><a href="#include-staged"><code>include-staged</code></a></li><li><a href="#include-workspace-root"><code>include-workspace-root</code></a></li><li><a href="#init-author-email"><code>init-author-email</code></a></li><li><a href="#init-author-name"><code>init-author-name</code></a></li><li><a href="#init-author-url"><code>init-author-url</code></a></li><li><a href="#init-license"><code>init-license</code></a></li><li><a href="#init-module"><code>init-module</code></a></li><li><a href="#init-private"><code>init-private</code></a></li><li><a href="#init-type"><code>init-type</code></a></li><li><a href="#init-version"><code>init-version</code></a></li><li><a href="#install-links"><code>install-links</code></a></li><li><a href="#install-strategy"><code>install-strategy</code></a></li><li><a href="#json"><code>json</code></a></li><li><a href="#keep-edit-dir"><code>keep-edit-dir</code></a></li><li><a href="#legacy-peer-deps"><code>legacy-peer-deps</code></a></li><li><a href="#libc"><code>libc</code></a></li><li><a href="#link"><code>link</code></a></li><li><a href="#local-address"><code>local-address</code></a></li><li><a href="#location"><code>location</code></a></li><li><a href="#lockfile-version"><code>lockfile-version</code></a></li><li><a href="#loglevel"><code>loglevel</code></a></li><li><a href="#logs-dir"><code>logs-dir</code></a></li><li><a href="#logs-max"><code>logs-max</code></a></li><li><a href="#long"><code>long</code></a></li><li><a href="#maxsockets"><code>maxsockets</code></a></li><li><a href="#message"><code>message</code></a></li><li><a href="#min-release-age"><code>min-release-age</code></a></li><li><a href="#min-release-age-exclude"><code>min-release-age-exclude</code></a></li><li><a href="#name"><code>name</code></a></li><li><a href="#node-gyp"><code>node-gyp</code></a></li><li><a href="#node-options"><code>node-options</code></a></li><li><a href="#noproxy"><code>noproxy</code></a></li><li><a href="#offline"><code>offline</code></a></li><li><a href="#omit"><code>omit</code></a></li><li><a href="#omit-lockfile-registry-resolved"><code>omit-lockfile-registry-resolved</code></a></li><li><a href="#orgs"><code>orgs</code></a></li><li><a href="#orgs-permission"><code>orgs-permission</code></a></li><li><a href="#os"><code>os</code></a></li><li><a href="#otp"><code>otp</code></a></li><li><a href="#pack-destination"><code>pack-destination</code></a></li><li><a href="#package"><code>package</code></a></li><li><a href="#package-lock"><code>package-lock</code></a></li><li><a href="#package-lock-only"><code>package-lock-only</code></a></li><li><a href="#packages"><code>packages</code></a></li><li><a href="#packages-all"><code>packages-all</code></a></li><li><a href="#packages-and-scopes-permission"><code>packages-and-scopes-permission</code></a></li><li><a href="#parseable"><code>parseable</code></a></li><li><a href="#password"><code>password</code></a></li><li><a href="#patches-dir"><code>patches-dir</code></a></li><li><a href="#prefer-dedupe"><code>prefer-dedupe</code></a></li><li><a href="#prefer-offline"><code>prefer-offline</code></a></li><li><a href="#prefer-online"><code>prefer-online</code></a></li><li><a href="#prefix"><code>prefix</code></a></li><li><a href="#preid"><code>preid</code></a></li><li><a href="#progress"><code>progress</code></a></li><li><a href="#provenance"><code>provenance</code></a></li><li><a href="#provenance-file"><code>provenance-file</code></a></li><li><a href="#proxy"><code>proxy</code></a></li><li><a href="#read-only"><code>read-only</code></a></li><li><a href="#rebuild-bundle"><code>rebuild-bundle</code></a></li><li><a href="#registry"><code>registry</code></a></li><li><a href="#replace-registry-host"><code>replace-registry-host</code></a></li><li><a href="#save"><code>save</code></a></li><li><a href="#save-bundle"><code>save-bundle</code></a></li><li><a href="#save-dev"><code>save-dev</code></a></li><li><a href="#save-exact"><code>save-exact</code></a></li><li><a href="#save-optional"><code>save-optional</code></a></li><li><a href="#save-peer"><code>save-peer</code></a></li><li><a href="#save-prefix"><code>save-prefix</code></a></li><li><a href="#save-prod"><code>save-prod</code></a></li><li><a href="#sbom-format"><code>sbom-format</code></a></li><li><a href="#sbom-type"><code>sbom-type</code></a></li><li><a href="#scope"><code>scope</code></a></li><li><a href="#scopes"><code>scopes</code></a></li><li><a href="#script-shell"><code>script-shell</code></a></li><li><a href="#searchexclude"><code>searchexclude</code></a></li><li><a href="#searchlimit"><code>searchlimit</code></a></li><li><a href="#searchopts"><code>searchopts</code></a></li><li><a href="#searchstaleness"><code>searchstaleness</code></a></li><li><a href="#shell"><code>shell</code></a></li><li><a href="#sign-git-commit"><code>sign-git-commit</code></a></li><li><a href="#sign-git-tag"><code>sign-git-tag</code></a></li><li><a href="#strict-allow-scripts"><code>strict-allow-scripts</code></a></li><li><a href="#strict-npmrc"><code>strict-npmrc</code></a></li><li><a href="#strict-peer-deps"><code>strict-peer-deps</code></a></li><li><a href="#strict-ssl"><code>strict-ssl</code></a></li><li><a href="#tag"><code>tag</code></a></li><li><a href="#tag-version-prefix"><code>tag-version-prefix</code></a></li><li><a href="#timing"><code>timing</code></a></li><li><a href="#to"><code>to</code></a></li><li><a href="#token-description"><code>token-description</code></a></li><li><a href="#umask"><code>umask</code></a></li><li><a href="#unicode"><code>unicode</code></a></li><li><a href="#update-notifier"><code>update-notifier</code></a></li><li><a href="#usage"><code>usage</code></a></li><li><a href="#user-agent"><code>user-agent</code></a></li><li><a href="#userconfig"><code>userconfig</code></a></li><li><a href="#version"><code>version</code></a></li><li><a href="#versions"><code>versions</code></a></li><li><a href="#viewer"><code>viewer</code></a></li><li><a href="#which"><code>which</code></a></li><li><a href="#workspace"><code>workspace</code></a></li><li><a href="#workspaces"><code>workspaces</code></a></li><li><a href="#workspaces-update"><code>workspaces-update</code></a></li><li><a href="#yes"><code>yes</code></a></li><li><a href="#also"><code>also</code></a></li><li><a href="#cache-max"><code>cache-max</code></a></li><li><a href="#cache-min"><code>cache-min</code></a></li><li><a href="#cert"><code>cert</code></a></li><li><a href="#dev"><code>dev</code></a></li><li><a href="#global-style"><code>global-style</code></a></li><li><a href="#initauthoremail"><code>init.author.email</code></a></li><li><a href="#initauthorname"><code>init.author.name</code></a></li><li><a href="#initauthorurl"><code>init.author.url</code></a></li><li><a href="#initlicense"><code>init.license</code></a></li><li><a href="#initmodule"><code>init.module</code></a></li><li><a href="#initversion"><code>init.version</code></a></li><li><a href="#key"><code>key</code></a></li><li><a href="#legacy-bundling"><code>legacy-bundling</code></a></li><li><a href="#only"><code>only</code></a></li><li><a href="#optional"><code>optional</code></a></li><li><a href="#production"><code>production</code></a></li></ul><li><a href="#see-also">See also</a></li></ul></div>
</section>
<div id="_content"><h3 id="description">Description</h3>
@@ -355,7 +355,7 @@ project's package.json to be installed. Also allows tarball file
dependencies to be used for other commands like <code>npm view</code></p>
<h4 id="allow-git"><code>allow-git</code></h4>
<ul>
-<li>Default: "all"</li>
+<li>Default: "none"</li>
<li>Type: "all", "none", or "root"</li>
</ul>
<p>Limits the ability for npm to fetch dependencies from git references. That
@@ -363,6 +363,10 @@ is, dependencies that point to a git repo instead of a version or semver
range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.</p>
+<p>As of npm 12 the default is <code>none</code>. Git dependencies run <code>git</code> against a
+remote repo and may install configuration the project does not control. Opt
+in explicitly per project (in <code>.npmrc</code>) or per command (on the CLI) when you
+need git deps.</p>
<p><code>all</code> allows any git dependencies to be fetched and installed. <code>none</code>
prevents any git dependencies from being fetched and installed. <code>root</code> only
allows git dependencies defined in your project's package.json to be fetched
@@ -370,7 +374,7 @@ and installed. Also allows git dependencies to be fetched for other commands
like <code>npm view</code></p>
<h4 id="allow-remote"><code>allow-remote</code></h4>
<ul>
-<li>Default: "all"</li>
+<li>Default: "none"</li>
<li>Type: "all", "none", or "root"</li>
</ul>
<p>Limits the ability for npm to fetch dependencies from urls. That is,
@@ -378,6 +382,12 @@ dependencies that point to a tarball url instead of a version or semver
range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.</p>
+<p>As of npm 12 the default is <code>none</code>. Tarballs that share a hostname with the
+configured registry (the typical case for the npm registry, GitHub Packages,
+and most private registries) are still installed normally. If your registry
+serves tarballs from a different host, set <code>replace-registry-host</code> or
+override this setting. Opt in explicitly per project (in <code>.npmrc</code>) or per
+command (on the CLI) when you intentionally install from a URL.</p>
<p><code>all</code> allows any url to be installed. <code>none</code> prevents any url from being
installed. <code>root</code> only allows urls defined in your project's package.json to
be installed. Also allows url dependencies to be used for other commands
@@ -406,6 +416,7 @@ project-scoped <code>npm install</code>, <code>ci</code>, <code>update</code>, o
<p>Each name is matched against a dependency's resolved identity, not against
the package's self-reported name. <code>--ignore-scripts</code> and
<code>--dangerously-allow-all-scripts</code> both override this setting.</p>
+<p>This value is not exported to the environment for child processes.</p>
<h4 id="allow-scripts-pending"><code>allow-scripts-pending</code></h4>
<ul>
<li>Default: false</li>
@@ -423,6 +434,15 @@ the package's self-reported name. <code>--ignore-scripts</code> and
<code>false</code> to write name-only entries that allow any version. Has no effect on
<code>npm deny-scripts</code>, which always writes name-only entries regardless of this
setting.</p>
+<h4 id="allow-unused-patches"><code>allow-unused-patches</code></h4>
+<ul>
+<li>Default: false</li>
+<li>Type: Boolean</li>
+</ul>
+<p>Install even when a registered patch in <code>patchedDependencies</code> matches no
+installed package. Does not silence patch apply failures.</p>
+<p>This flag is only honored when passed on the command line; it is ignored in
+<code>.npmrc</code> and environment variables, and rejected by <code>npm ci</code>.</p>
<h4 id="audit"><code>audit</code></h4>
<ul>
<li>Default: true</li>
@@ -647,6 +667,13 @@ commands that modify your local installation, eg, <code>install</code>, <code>up
<code>dedupe</code>, <code>uninstall</code>, as well as <code>pack</code> and <code>publish</code>.</p>
<p>Note: This is NOT honored by other network related commands, eg <code>dist-tags</code>,
<code>owner</code>, etc.</p>
+<h4 id="edit-dir"><code>edit-dir</code></h4>
+<ul>
+<li>Default: null</li>
+<li>Type: null or Path</li>
+</ul>
+<p>Override the temporary directory used by <code>npm patch add</code> to prepare a
+package for editing.</p>
<h4 id="editor"><code>editor</code></h4>
<ul>
<li>Default: The EDITOR or VISUAL environment variables, or
@@ -686,6 +713,16 @@ true (expect some results) or false (expect no results).</p>
<p>When creating a Granular Access Token with <code>npm token create</code>, this sets the
expiration in days. If not specified, the server will determine the default
expiration.</p>
+<h4 id="extension-file"><code>extension-file</code></h4>
+<ul>
+<li>Default: null</li>
+<li>Type: null or Path</li>
+</ul>
+<p>Path to a project-local npm extension file to load instead of discovering
+<code>.npm-extension.mjs</code> / <code>.npm-extension.cjs</code> at the project root. Must
+resolve inside the project root and use a <code>.mjs</code> or <code>.cjs</code> extension. Only
+honored from project config or the command line, never from user, global, or
+builtin config.</p>
<h4 id="fetch-retries"><code>fetch-retries</code></h4>
<ul>
<li>Default: 2</li>
@@ -762,8 +799,7 @@ but can be useful for debugging.</p>
<li>Default: true</li>
<li>Type: Boolean</li>
</ul>
-<p>Format <code>package-lock.json</code> or <code>npm-shrinkwrap.json</code> as a human readable
-file.</p>
+<p>Format <code>package-lock.json</code> as a human readable file.</p>
<h4 id="fund"><code>fund</code></h4>
<ul>
<li>Default: true</li>
@@ -799,6 +835,21 @@ of the current working directory.</li>
<li>bin files are linked to <code>{prefix}/bin</code></li>
<li>man pages are linked to <code>{prefix}/share/man</code></li>
</ul>
+<h4 id="global-ignore-file"><code>global-ignore-file</code></h4>
+<ul>
+<li>Default: The global --prefix setting plus 'etc/npmignore'. For example,
+'/usr/local/etc/npmignore'</li>
+<li>Type: Path</li>
+</ul>
+<p>An additional ignore file applied during <code>npm pack</code> and <code>npm publish</code>, owned
+by the current user rather than the package. Patterns follow the same syntax
+as a package's local <code>.npmignore</code> file. Useful for keeping editor metadata
+(such as <code>.idea/</code> or <code>*.iml</code>) and scratch directories out of every package
+you publish, without adding them to each package's own ignore rules.</p>
+<p>The global rules apply in addition to a package's local <code>.npmignore</code>. When a
+package uses a <code>files</code> field in its <code>package.json</code>, an entry in <code>files</code> that
+contradicts a global rule (i.e., explicitly includes a path the global rule
+would exclude) still wins.</p>
<h4 id="globalconfig"><code>globalconfig</code></h4>
<ul>
<li>Default: The global --prefix setting plus 'etc/npmrc'. For example,
@@ -833,6 +884,31 @@ present and fail if the script fails. This is useful, for example, when
running scripts that may only apply for some builds in an otherwise generic
CI setup.</p>
<p>This value is not exported to the environment for child processes.</p>
+<h4 id="ignore-existing"><code>ignore-existing</code></h4>
+<ul>
+<li>Default: false</li>
+<li>Type: Boolean</li>
+</ul>
+<p>With <code>npm patch add</code>, discard a previous unfinished edit directory and start
+fresh.</p>
+<h4 id="ignore-extension"><code>ignore-extension</code></h4>
+<ul>
+<li>Default: false</li>
+<li>Type: Boolean</li>
+</ul>
+<p>If true, npm does not import or execute a root <code>.npm-extension.mjs</code> /
+<code>.npm-extension.cjs</code> file (or one selected via <code>extension-file</code>).
+<code>ignore-scripts</code> implies <code>ignore-extension</code>, since both disable root-owned
+install-time code.</p>
+<h4 id="ignore-patch-failures"><code>ignore-patch-failures</code></h4>
+<ul>
+<li>Default: false</li>
+<li>Type: Boolean</li>
+</ul>
+<p>Install even when a registered patch fails to apply, with a warning per
+failure. Intended for incident response only.</p>
+<p>This flag is only honored when passed on the command line; it is ignored in
+<code>.npmrc</code> and environment variables, and rejected by <code>npm ci</code>.</p>
<h4 id="ignore-scripts"><code>ignore-scripts</code></h4>
<ul>
<li>Default: false</li>
@@ -843,6 +919,8 @@ CI setup.</p>
<code>npm start</code>, <code>npm stop</code>, <code>npm restart</code>, <code>npm test</code>, and <code>npm run</code> will still
run their intended script if <code>ignore-scripts</code> is set, but they will <em>not</em>
run any pre- or post-scripts.</p>
+<p>Setting <code>ignore-scripts</code> also disables <code>.npm-extension</code> execution, as if
+<code>ignore-extension</code> were set.</p>
<h4 id="include"><code>include</code></h4>
<ul>
<li>Default:</li>
@@ -900,10 +978,11 @@ the specified workspaces, and not on the root project.</p>
homepage.</p>
<h4 id="init-license"><code>init-license</code></h4>
<ul>
-<li>Default: "ISC"</li>
+<li>Default: ""</li>
<li>Type: String</li>
</ul>
-<p>The value <code>npm init</code> should use by default for the package license.</p>
+<p>The value <code>npm init</code> should use by default for the package license. If not
+set, the license field will be omitted from new packages.</p>
<h4 id="init-module"><code>init-module</code></h4>
<ul>
<li>Default: "~/.npm-init.js"</li>
@@ -970,6 +1049,13 @@ dependencies</a>.</p>
saving them to your <code>package.json</code>.</li>
</ul>
<p>Not supported by all npm commands.</p>
+<h4 id="keep-edit-dir"><code>keep-edit-dir</code></h4>
+<ul>
+<li>Default: false</li>
+<li>Type: Boolean</li>
+</ul>
+<p>With <code>npm patch commit</code>, do not remove the edit directory after committing
+the patch.</p>
<h4 id="legacy-peer-deps"><code>legacy-peer-deps</code></h4>
<ul>
<li>Default: false</li>
@@ -1026,8 +1112,8 @@ of the current working directory.</li>
otherwise, maintain current lockfile version.</li>
<li>Type: null, 1, 2, 3, "1", "2", or "3"</li>
</ul>
-<p>Set the lockfile format version to be used in package-lock.json and
-npm-shrinkwrap-json files. Possible options are:</p>
+<p>Set the lockfile format version to be used in package-lock.json files.
+Possible options are:</p>
<p>1: The lockfile version used by npm versions 5 and 6. Lacks some data that
is used during the install, resulting in slower and possibly less
deterministic installs. Prevents lockfile churn when interoperating with
@@ -1173,8 +1259,7 @@ allow the CLI to fill in missing cache data, see <code>--prefer-offline</code>.<
</ul>
<p>Dependency types to omit from the installation tree on disk.</p>
<p>Note that these dependencies <em>are</em> still resolved and added to the
-<code>package-lock.json</code> or <code>npm-shrinkwrap.json</code> file. They are just not
-physically installed on disk.</p>
+<code>package-lock.json</code> file. They are just not physically installed on disk.</p>
<p>If a package type appears in both the <code>--include</code> and <code>--omit</code> lists, then
it will be included.</p>
<p>If the resulting omit list includes <code>'dev'</code>, then the <code>NODE_ENV</code> environment
@@ -1266,11 +1351,14 @@ token access to all packages instead of limiting to specific packages.</p>
<h4 id="packages-and-scopes-permission"><code>packages-and-scopes-permission</code></h4>
<ul>
<li>Default: null</li>
-<li>Type: null, "read-only", "read-write", or "no-access"</li>
+<li>Type: null, "read-only", "read-write", "read-write-stage-only", or
+"no-access"</li>
</ul>
<p>When creating a Granular Access Token with <code>npm token create</code>, sets the
permission level for packages and scopes. Options are "read-only",
-"read-write", or "no-access".</p>
+"read-write", "read-write-stage-only", or "no-access".
+"read-write-stage-only" grants publish access that stages releases instead
+of publishing them directly.</p>
<h4 id="parseable"><code>parseable</code></h4>
<ul>
<li>Default: false</li>
@@ -1285,6 +1373,13 @@ permission level for packages and scopes. Options are "read-only",
</ul>
<p>Password for authentication. Can be provided via command line when creating
tokens, though it's generally safer to be prompted for it.</p>
+<h4 id="patches-dir"><code>patches-dir</code></h4>
+<ul>
+<li>Default: "patches"</li>
+<li>Type: String</li>
+</ul>
+<p>The directory, relative to the project root, where <code>npm patch commit</code> writes
+patch files for <code>patchedDependencies</code>.</p>
<h4 id="prefer-dedupe"><code>prefer-dedupe</code></h4>
<ul>
<li>Default: false</li>
@@ -1339,6 +1434,8 @@ operations, if <code>process.stderr</code> and <code>process.stdout</code> are a
</ul>
<p>When publishing from a supported cloud CI/CD system, the package will be
publicly linked to where it was built and published from.</p>
+<p>When the <code>provenance-file</code> config is set, it takes precedence and automatic
+provenance generation (including via trusted publishing/OIDC) is skipped.</p>
<p>This config cannot be used with: <code>provenance-file</code></p>
<h4 id="provenance-file"><code>provenance-file</code></h4>
<ul>
@@ -1346,6 +1443,8 @@ publicly linked to where it was built and published from.</p>
<li>Type: Path</li>
</ul>
<p>When publishing, the provenance bundle at the given path will be used.</p>
+<p>This takes precedence over automatic provenance generation in trusted
+publishing flows.</p>
<p>This config cannot be used with: <code>provenance</code></p>
<h4 id="proxy"><code>proxy</code></h4>
<ul>
@@ -1565,15 +1664,25 @@ this to work properly.</p>
<li>Type: Boolean</li>
</ul>
<p>If <code>true</code>, turn the install-script policy from a warning into a hard error:
-any dependency with install scripts not covered by <code>allowScripts</code> will fail
-the install instead of running with a notice.</p>
+any dependency with install scripts that is not covered by <code>allowScripts</code>
+will fail the install instead of being blocked with a warning.</p>
<p>Dependencies explicitly denied with <code>false</code> in <code>allowScripts</code> are always
-silently skipped; this setting only affects unreviewed entries.
+silently skipped; this setting only affects unreviewed entries (packages
+with install scripts that are neither approved nor denied).
<code>--ignore-scripts</code> and <code>--dangerously-allow-all-scripts</code> both override this
setting.</p>
<p>Optional dependencies that cannot be installed on the current platform or
engine (a non-matching <code>os</code>, <code>cpu</code>, or <code>libc</code>) are not flagged, because
their install scripts never run.</p>
+<h4 id="strict-npmrc"><code>strict-npmrc</code></h4>
+<ul>
+<li>Default: false</li>
+<li>Type: Boolean</li>
+</ul>
+<p>If set to <code>true</code>, unknown configuration keys found in <code>.npmrc</code> files are
+treated as a hard error instead of a warning.</p>
+<p>Unknown command line flags and abbreviated flags always error regardless of
+this setting.</p>
<h4 id="strict-peer-deps"><code>strict-peer-deps</code></h4>
<ul>
<li>Default: false</li>
@@ -1632,6 +1741,14 @@ cache or <code>logs-dir</code>. The file name ends with <code>-timing.json</code
<code>cat ~/.npm/_logs/*-timing.json | npm exec -- json -g</code>.</p>
<p>Timing information will also be reported in the terminal. To suppress this
while still writing the timing file, use <code>--silent</code>.</p>
+<h4 id="to"><code>to</code></h4>
+<ul>
+<li>Default: null</li>
+<li>Type: null or String</li>
+</ul>
+<p>Used by <code>npm patch update</code> to set the version to rebase a patch onto when it
+cannot be read from <code>package-lock.json</code> — for example an exact-version
+selector, or a version that has not been installed yet.</p>
<h4 id="token-description"><code>token-description</code></h4>
<ul>
<li>Default: null</li>
@@ -1857,7 +1974,7 @@ on deeper dependencies. Sets <code>--install-strategy=shallow</code>.</p>
<p>Alias for <code>--init-author-url</code></p>
<h4 id="initlicense"><code>init.license</code></h4>
<ul>
-<li>Default: "ISC"</li>
+<li>Default: ""</li>
<li>Type: String</li>
<li>DEPRECATED: Use <code>--init-license</code> instead.</li>
</ul>
@@ -1925,13 +2042,6 @@ de-duplicating. Sets <code>--install-strategy=nested</code>.</p>
<li>DEPRECATED: Use <code>--omit=dev</code> instead.</li>
</ul>
<p>Alias for <code>--omit=dev</code></p>
-<h4 id="shrinkwrap"><code>shrinkwrap</code></h4>
-<ul>
-<li>Default: true</li>
-<li>Type: Boolean</li>
-<li>DEPRECATED: Use the --package-lock setting instead.</li>
-</ul>
-<p>Alias for --package-lock</p>
<h3 id="see-also">See also</h3>
<ul>
<li><a href="../commands/npm-config.html">npm config</a></li>
diff --git a/deps/npm/docs/output/using-npm/dependency-selectors.html b/deps/npm/docs/output/using-npm/dependency-selectors.html
index c56b5e6c402..fd33213840f 100644
--- a/deps/npm/docs/output/using-npm/dependency-selectors.html
+++ b/deps/npm/docs/output/using-npm/dependency-selectors.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----dependency-selectors----11191">
+<h1 id="----dependency-selectors----1210">
<span>Dependency Selectors</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Dependency Selector Syntax & Querying</span>
</header>
diff --git a/deps/npm/docs/output/using-npm/developers.html b/deps/npm/docs/output/using-npm/developers.html
index 984f28bfe7b..3c262b7d975 100644
--- a/deps/npm/docs/output/using-npm/developers.html
+++ b/deps/npm/docs/output/using-npm/developers.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----developers----11191">
+<h1 id="----developers----1210">
<span>Developers</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Developer guide</span>
</header>
@@ -346,12 +346,7 @@ A dependency that's still satisfied at your build by a <code>devDependency</code
So treat it as one check, not a guarantee, alongside auditing the dependencies your published package actually uses.</p>
</blockquote>
<h3 id="create-a-user-account">Create a User Account</h3>
-<p>Create a user with the adduser command.
-It works like this:</p>
-<pre><code class="language-bash">npm adduser
-</code></pre>
-<p>and then follow the prompts.</p>
-<p>This is documented better in <a href="../commands/npm-adduser.html">npm adduser</a>.</p>
+<p>Create a user account on the <a href="https://www.npmjs.com/signup">npm website</a>.</p>
<h3 id="publish-your-package">Publish your Package</h3>
<p>This part's easy.
In the root of your folder, do this:</p>
@@ -370,7 +365,7 @@ So, if you have secret stuff in there, use a <code>.npmignore</code> file to lis
<li><a href="../configuring-npm/package-json.html">package.json</a></li>
<li><a href="../using-npm/scripts.html">npm scripts</a></li>
<li><a href="../commands/npm-publish.html">npm publish</a></li>
-<li><a href="../commands/npm-adduser.html">npm adduser</a></li>
+<li><a href="../commands/npm-login.html">npm login</a></li>
<li><a href="../using-npm/registry.html">npm registry</a></li>
</ul></div>
diff --git a/deps/npm/docs/output/using-npm/logging.html b/deps/npm/docs/output/using-npm/logging.html
index f6f6dd742f1..29a4b046477 100644
--- a/deps/npm/docs/output/using-npm/logging.html
+++ b/deps/npm/docs/output/using-npm/logging.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----logging----11191">
+<h1 id="----logging----1210">
<span>Logging</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Why, What & How we Log</span>
</header>
diff --git a/deps/npm/docs/output/using-npm/orgs.html b/deps/npm/docs/output/using-npm/orgs.html
index f579fcbbac1..ac10041d0e7 100644
--- a/deps/npm/docs/output/using-npm/orgs.html
+++ b/deps/npm/docs/output/using-npm/orgs.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----organizations----11191">
+<h1 id="----organizations----1210">
<span>Organizations</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Working with teams & organizations</span>
</header>
diff --git a/deps/npm/docs/output/using-npm/package-spec.html b/deps/npm/docs/output/using-npm/package-spec.html
index 620f470d109..6b414770b89 100644
--- a/deps/npm/docs/output/using-npm/package-spec.html
+++ b/deps/npm/docs/output/using-npm/package-spec.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----package-spec----11191">
+<h1 id="----package-spec----1210">
<span>Package spec</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Package name specifier</span>
</header>
diff --git a/deps/npm/docs/output/using-npm/registry.html b/deps/npm/docs/output/using-npm/registry.html
index e61715c22e4..11050d44bf8 100644
--- a/deps/npm/docs/output/using-npm/registry.html
+++ b/deps/npm/docs/output/using-npm/registry.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----registry----11191">
+<h1 id="----registry----1210">
<span>Registry</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">The JavaScript Package Registry</span>
</header>
@@ -211,7 +211,7 @@ If no scope is specified, the default registry is used, which is supplied by the
See <a href="../commands/npm-config.html"><code>npm config</code></a>, <a href="../configuring-npm/npmrc.html"><code>npmrc</code></a>, and <a href="../using-npm/config.html"><code>config</code></a> for more on managing npm's configuration.
Authentication configuration such as auth tokens and certificates are configured specifically scoped to an individual registry.
See <a href="../configuring-npm/npmrc#auth-related-configuration.html">Auth Related Configuration</a></p>
-<p>When the default registry is used in a package-lock or shrinkwrap it has the special meaning of "the currently configured registry". If you create a lock file while using the default registry you can switch to another registry and npm will install packages from the new registry, but if you create a lock file while using a custom registry packages will be installed from that registry even after you change to another registry.</p>
+<p>When the default registry is used in a package-lock it has the special meaning of "the currently configured registry". If you create a lock file while using the default registry you can switch to another registry and npm will install packages from the new registry, but if you create a lock file while using a custom registry packages will be installed from that registry even after you change to another registry.</p>
<h3 id="does-npm-send-any-information-about-me-back-to-the-registry">Does npm send any information about me back to the registry?</h3>
<p>Yes.</p>
<p>When making requests of the registry npm adds two headers with information about your environment:</p>
diff --git a/deps/npm/docs/output/using-npm/removal.html b/deps/npm/docs/output/using-npm/removal.html
index 07ee6c06bc4..3f26061b997 100644
--- a/deps/npm/docs/output/using-npm/removal.html
+++ b/deps/npm/docs/output/using-npm/removal.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----removal----11191">
+<h1 id="----removal----1210">
<span>Removal</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Cleaning the slate</span>
</header>
diff --git a/deps/npm/docs/output/using-npm/scope.html b/deps/npm/docs/output/using-npm/scope.html
index a08571ebfda..548495818de 100644
--- a/deps/npm/docs/output/using-npm/scope.html
+++ b/deps/npm/docs/output/using-npm/scope.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----scope----11191">
+<h1 id="----scope----1210">
<span>Scope</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Scoped packages</span>
</header>
diff --git a/deps/npm/docs/output/using-npm/scripts.html b/deps/npm/docs/output/using-npm/scripts.html
index 4e852304a11..f0a3b967dc3 100644
--- a/deps/npm/docs/output/using-npm/scripts.html
+++ b/deps/npm/docs/output/using-npm/scripts.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----scripts----11191">
+<h1 id="----scripts----1210">
<span>Scripts</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">How npm handles the "scripts" field</span>
</header>
@@ -306,7 +306,7 @@ It is run AFTER the changes have been applied and the <code>package.json</code>
</ul>
<h4 id="npm-ci"><a href="../commands/npm-ci.html"><code>npm ci</code></a></h4>
<ul>
-<li><code>preinstall</code></li>
+<li><code>preinstall</code> (before dependencies are installed)</li>
<li><code>install</code></li>
<li><code>postinstall</code></li>
<li><code>prepublish</code></li>
@@ -314,16 +314,16 @@ It is run AFTER the changes have been applied and the <code>package.json</code>
<li><code>prepare</code></li>
<li><code>postprepare</code></li>
</ul>
-<p>These all run after the actual installation of modules into
-<code>node_modules</code>, in order, with no internal actions happening in between</p>
+<p><code>preinstall</code> runs before any dependencies are fetched or unpacked into <code>node_modules</code>, so scripts can prepare the environment (for example, setting up authentication for a private registry) before tarballs are fetched. For <code>npm ci</code>, <code>preinstall</code> fires <em>after</em> the lockfile has been validated against <code>package.json</code>, so it cannot influence dependency resolution — that remains locked to <code>package-lock.json</code>. The remaining scripts run after the installation of modules into <code>node_modules</code>, in order, with no internal actions happening in between.</p>
+<p>Because <code>preinstall</code> runs before reify, scripts cannot rely on packages from <code>node_modules</code>. <code>npm ci</code> wipes <code>node_modules</code> before <code>preinstall</code> fires, so <code>require()</code> of a dependency will always fail. Use <code>install</code> or <code>postinstall</code> for setup that depends on installed packages.</p>
<h4 id="npm-diff"><a href="../commands/npm-diff.html"><code>npm diff</code></a></h4>
<ul>
<li><code>prepare</code></li>
</ul>
<h4 id="npm-install"><a href="../commands/npm-install.html"><code>npm install</code></a></h4>
-<p>These also run when you run <code>npm install -g <pkg-name></code></p>
+<p>These run on a bare <code>npm install</code> in a local project (no package arguments).</p>
<ul>
-<li><code>preinstall</code></li>
+<li><code>preinstall</code> (before dependencies are installed)</li>
<li><code>install</code></li>
<li><code>postinstall</code></li>
<li><code>prepublish</code></li>
@@ -331,6 +331,8 @@ It is run AFTER the changes have been applied and the <code>package.json</code>
<li><code>prepare</code></li>
<li><code>postprepare</code></li>
</ul>
+<p><code>preinstall</code> runs before any dependencies are fetched or unpacked into <code>node_modules</code>, so scripts can prepare the environment (for example, setting up authentication for a private registry) before resolution begins. The remaining scripts run after installation has completed.</p>
+<p>Because <code>preinstall</code> runs before reify, scripts cannot rely on packages from <code>node_modules</code>. On a fresh checkout, <code>require()</code> of a dependency will fail. On a repeat <code>npm install</code> against an existing <code>node_modules/</code>, it may incidentally succeed because the previously-installed tree is still on disk, but the version available is whatever was previously installed and may be removed or replaced by the upcoming install. Use <code>install</code> or <code>postinstall</code> for setup that depends on installed packages.</p>
<p>If there is a <code>binding.gyp</code> file in the root of your package and you haven't defined your own <code>install</code> or <code>preinstall</code> scripts, npm will default the <code>install</code> command to compile using node-gyp via <code>node-gyp rebuild</code></p>
<p>These are run from the scripts of <code><pkg-name></code></p>
<h4 id="npm-pack"><a href="../commands/npm-pack.html"><code>npm pack</code></a></h4>
diff --git a/deps/npm/docs/output/using-npm/workspaces.html b/deps/npm/docs/output/using-npm/workspaces.html
index ec3d3abed05..048ee835c87 100644
--- a/deps/npm/docs/output/using-npm/workspaces.html
+++ b/deps/npm/docs/output/using-npm/workspaces.html
@@ -186,9 +186,9 @@ npm command-line interface
<section id="content">
<header class="title">
-<h1 id="----workspaces----11191">
+<h1 id="----workspaces----1210">
<span>Workspaces</span>
- <span class="version">@11.19.1</span>
+ <span class="version">@12.1.0</span>
</h1>
<span class="description">Working with workspaces</span>
</header>
diff --git a/deps/npm/lib/base-cmd.js b/deps/npm/lib/base-cmd.js
index 85b1f5ac8f3..d8500b5206a 100644
--- a/deps/npm/lib/base-cmd.js
+++ b/deps/npm/lib/base-cmd.js
@@ -1,5 +1,5 @@
const { log } = require('proc-log')
-const { definitions, shorthands } = require('@npmcli/config/lib/definitions')
+const { definitions } = require('@npmcli/config/lib/definitions')
const nopt = require('nopt')
class BaseCommand {
@@ -325,10 +325,9 @@ class BaseCommand {
delete parsed.argv
}
- // Validate flags - only if command has definitions (new system)
- if (this.constructor.definitions && this.constructor.definitions.length > 0) {
- this.#validateFlags(parsed, commandDefinitions, remains)
- }
+ // Validate unknown CLI flags/configs and unexpected positionals.
+ // Runs for every command; command-specific flags are allow-listed here so they don't trip the global unknown-config collection from Config.loadCLI().
+ this.validateCli(commandDefinitions, remains)
// Check for conflicts between main flags and their aliases
// Also map aliases back to their main keys
@@ -365,64 +364,89 @@ class BaseCommand {
return [{ ...defaults, ...filtered }, remains]
}
- // Validate flags and throw errors for unknown flags or unexpected positionals
- #validateFlags (parsed, commandDefinitions, remains) {
- // Build a set of all valid flag names (global + command-specific + shorthands)
- const validFlags = new Set([
- ...Object.keys(definitions),
+ // Unified CLI validation — runs for every command (definitions-based and legacy).
+ // Reads collected unknown configs from Config (they were collected, not thrown, during Config.load()), subtracts any command-specific definitions, and throws a single aggregated error.
+ // Also enforces extra-positional errors for commands that set a finite `static positionals`.
+ // Shellout commands (run/exec/lifecycle) leave `static positionals = null` and are unaffected.
+ // Commands that set `static skipConfigValidation = true` (config, help, doctor, completion, version) bypass both unknown-config checks so they can operate against a broken .npmrc.
+ validateCli (commandDefinitions = this.constructor.definitions || [], remains = null) {
+ const allowlist = new Set([
...commandDefinitions.map(d => d.key),
- ...Object.keys(shorthands), // Add global shorthands like 'verbose', 'dd', etc.
+ ...commandDefinitions.flatMap(d => Array.isArray(d.alias) ? d.alias : []),
])
- // Add aliases to valid flags
- for (const def of commandDefinitions) {
- if (def.alias && Array.isArray(def.alias)) {
- for (const alias of def.alias) {
- validFlags.add(alias)
- }
- }
- }
+ if (!this.constructor.skipConfigValidation) {
+ const cliUnknowns = this.npm.config.getUnknownConfigs('cli')
+ .filter(u => !allowlist.has(u.key) && !allowlist.has(u.baseKey))
- // Check parsed flags against valid flags
- const unknownFlags = []
- for (const key of Object.keys(parsed)) {
- if (!validFlags.has(key)) {
- unknownFlags.push(key)
+ const fileUnknowns = []
+ for (const where of ['builtin', 'project', 'user', 'global']) {
+ fileUnknowns.push(...this.npm.config.getUnknownConfigs(where))
}
- }
- // Throw error if unknown flags were found
- if (unknownFlags.length > 0) {
- const flagList = unknownFlags.map(f => `--${f}`).join(', ')
- throw this.usageError(`Unknown flag${unknownFlags.length > 1 ? 's' : ''}: ${flagList}`)
- }
+ // Unknown cli configs/flags/abbreviations always error. Unknown .npmrc
+ // (file) configs warn by default, matching pre-npm-12 behavior, but error
+ // when `strict-npmrc` is set.
+ const strictNpmrc = this.npm.config.get('strict-npmrc')
+ if (!strictNpmrc) {
+ for (const u of fileUnknowns) {
+ const display = u.baseKey ? `"${u.baseKey}" (${u.key})` : `"${u.key}"`
+ log.warn(
+ `Unknown ${u.where} config ${display}. This will stop working in the ` +
+ 'next major version of npm. See `npm help npmrc` for supported config options.')
+ }
+ }
- // Remove warnings for command-specific definitions that npm's global config doesn't know about (these were queued as "unknown" during config.load())
- for (const def of commandDefinitions) {
- this.npm.config.removeWarning(def.key)
- if (def.alias && Array.isArray(def.alias)) {
- for (const alias of def.alias) {
- this.npm.config.removeWarning(alias)
+ const errorFileUnknowns = strictNpmrc ? fileUnknowns : []
+ if (cliUnknowns.length > 0 || errorFileUnknowns.length > 0) {
+ const sections = []
+ if (cliUnknowns.length > 0) {
+ const lines = cliUnknowns.map(u =>
+ u.baseKey ? ` - --${u.baseKey} (${u.key})` : ` - --${u.key}`
+ )
+ sections.push(
+ `Unknown cli flag${cliUnknowns.length > 1 ? 's' : ''}:`,
+ ...lines,
+ 'Run `npm help config` for supported options.'
+ )
}
+ if (errorFileUnknowns.length > 0) {
+ if (sections.length > 0) {
+ sections.push('')
+ }
+ const lines = errorFileUnknowns.map(u => {
+ const display = u.baseKey ? `"${u.baseKey}" (${u.key})` : `"${u.key}"`
+ return ` - ${u.where} config ${display} from ${u.source}`
+ })
+ sections.push(
+ `Unknown npm configuration key${errorFileUnknowns.length > 1 ? 's' : ''}:`,
+ ...lines,
+ 'See `npm help npmrc` for supported config options.'
+ )
+ }
+ throw Object.assign(new Error(sections.join('\n')), {
+ code: 'EUNKNOWNCONFIG',
+ unknownConfigs: [...cliUnknowns, ...errorFileUnknowns],
+ })
}
}
- // Remove warnings for unknown positionals that were actually consumed as flag values by command-specific definitions (e.g., --id <value> where --id is command-specific)
- const remainsSet = new Set(remains)
- for (const unknownPos of this.npm.config.getUnknownPositionals()) {
- if (!remainsSet.has(unknownPos)) {
- // This value was consumed as a flag value, not truly a positional
- this.npm.config.removeUnknownPositional(unknownPos)
+ // Positionals consumed as flag values by command-specific definitions were queued as "unknown positional" warnings by Config.unknownHandler; drop those since they're actually flag arguments.
+ if (Array.isArray(remains)) {
+ const remainsSet = new Set(remains)
+ for (const unknownPos of this.npm.config.getUnknownPositionals()) {
+ if (!remainsSet.has(unknownPos)) {
+ this.npm.config.removeUnknownPositional(unknownPos)
+ }
}
}
- // Warn about extra positional arguments beyond what the command expects
- const expectedPositionals = this.constructor.positionals
- if (expectedPositionals !== null && remains.length > expectedPositionals) {
- const extraPositionals = remains.slice(expectedPositionals)
- for (const extra of extraPositionals) {
- throw new Error(`Unknown positional argument: ${extra}`)
- }
+ const expected = this.constructor.positionals
+ if (expected !== null && remains !== null && remains.length > expected) {
+ const extra = remains.slice(expected)
+ throw this.usageError(
+ `Unknown positional argument${extra.length > 1 ? 's' : ''}: ${extra.join(', ')}`
+ )
}
this.npm.config.logWarnings()
diff --git a/deps/npm/lib/commands/adduser.js b/deps/npm/lib/commands/adduser.js
deleted file mode 100644
index cf64e7a7e74..00000000000
--- a/deps/npm/lib/commands/adduser.js
+++ /dev/null
@@ -1,50 +0,0 @@
-const { log, output } = require('proc-log')
-const { redactLog: replaceInfo } = require('@npmcli/redact')
-const auth = require('../utils/auth.js')
-const BaseCommand = require('../base-cmd.js')
-
-class AddUser extends BaseCommand {
- static description = 'Add a registry user account'
- static name = 'adduser'
- static params = [
- 'registry',
- 'scope',
- 'auth-type',
- ]
-
- async exec () {
- const scope = this.npm.config.get('scope')
- let registry = this.npm.config.get('registry')
-
- if (scope) {
- const scopedRegistry = this.npm.config.get(`${scope}:registry`)
- const cliRegistry = this.npm.config.get('registry', 'cli')
- if (scopedRegistry && !cliRegistry) {
- registry = scopedRegistry
- }
- }
-
- const creds = this.npm.config.getCredentialsByURI(registry)
-
- log.notice('', `Log in on ${replaceInfo(registry)}`)
-
- const { message, newCreds } = await auth.adduser(this.npm, {
- ...this.npm.flatOptions,
- creds,
- registry,
- })
-
- this.npm.config.delete('_token', 'user') // prevent legacy pollution
- this.npm.config.setCredentialsByURI(registry, newCreds)
-
- if (scope) {
- this.npm.config.set(scope + ':registry', registry, 'user')
- }
-
- await this.npm.config.save('user')
-
- output.standard(message)
- }
-}
-
-module.exports = AddUser
diff --git a/deps/npm/lib/commands/audit.js b/deps/npm/lib/commands/audit.js
index 6a55af43135..bc2480c520f 100644
--- a/deps/npm/lib/commands/audit.js
+++ b/deps/npm/lib/commands/audit.js
@@ -4,6 +4,7 @@ const auditError = require('../utils/audit-error.js')
const { log, output } = require('proc-log')
const reifyFinish = require('../utils/reify-finish.js')
const resolveAllowScripts = require('../utils/resolve-allow-scripts.js')
+const { patchRelaxOpts } = require('../utils/cli-only-flag.js')
const VerifySignatures = require('../utils/verify-signatures.js')
class Audit extends ArboristWorkspaceCmd {
@@ -62,6 +63,8 @@ class Audit extends ArboristWorkspaceCmd {
const { policy: allowScriptsPolicy } = await resolveAllowScripts(this.npm)
const opts = {
...this.npm.flatOptions,
+ // audit fix reifies, so honor the cli-only patch relax flags
+ ...patchRelaxOpts(this.npm.config),
audit: true,
path: this.npm.prefix,
reporter,
diff --git a/deps/npm/lib/commands/ci.js b/deps/npm/lib/commands/ci.js
index e8243854329..17307badede 100644
--- a/deps/npm/lib/commands/ci.js
+++ b/deps/npm/lib/commands/ci.js
@@ -6,6 +6,7 @@ const fs = require('node:fs/promises')
const path = require('node:path')
const { log, time } = require('proc-log')
const validateLockfile = require('../utils/validate-lockfile.js')
+const { validatePackageExtensions, validateNpmExtension } = require('../utils/validate-lockfile.js')
const ArboristWorkspaceCmd = require('../arborist-cmd.js')
const getWorkspaces = require('../utils/get-workspaces.js')
@@ -44,6 +45,15 @@ class CI extends ArboristWorkspaceCmd {
})
}
+ // npm ci is always strict about patches; the relax flags are not accepted
+ for (const flag of ['allow-unused-patches', 'ignore-patch-failures']) {
+ if (this.npm.config.find(flag) === 'cli') {
+ throw Object.assign(new Error(`The --${flag} flag is not allowed with \`npm ci\`.`), {
+ code: 'ECIPATCHFLAG',
+ })
+ }
+ }
+
const dryRun = this.npm.config.get('dry-run')
const ignoreScripts = this.npm.config.get('ignore-scripts')
const where = this.npm.prefix
@@ -56,6 +66,9 @@ class CI extends ArboristWorkspaceCmd {
save: false, // npm ci should never modify the lockfile or package.json
workspaces: this.workspaceNames,
allowScripts: allowScriptsPolicy,
+ // npm ci reifies the locked graph, which already carries extension-influenced edges, so it must never import or execute .npm-extension.
+ // The extension file hash is still validated below, independent of execution.
+ ignoreExtension: true,
}
// generate an inventory from the virtual tree in the lockfile
@@ -65,24 +78,36 @@ class CI extends ArboristWorkspaceCmd {
} catch (err) {
log.verbose('loadVirtual', err.stack)
const msg =
- 'The `npm ci` command can only install with an existing package-lock.json or\n' +
- 'npm-shrinkwrap.json with lockfileVersion >= 1. Run an install with npm@5 or\n' +
- 'later to generate a package-lock.json file, then try again.'
+ 'The `npm ci` command can only install with an existing\n' +
+ 'package-lock.json with lockfileVersion >= 1. Run an install with npm@5\n' +
+ 'or later to generate a package-lock.json file, then try again.'
throw this.usageError(msg)
}
const virtualInventory = new Map(virtualArb.virtualTree.inventory)
// Now we make our real Arborist.
- // We need a new one because the virtual tree fromt the lockfile can have extraneous dependencies in it that won't install on this platform
+ // We need a new one because the virtual tree from the lockfile can have extraneous dependencies in it that won't install on this platform
const arb = new Arborist(opts)
await arb.buildIdealTree()
await strictAllowScriptsPreflight({ arb, npm: this.npm, idealTreeOpts: opts })
// Verifies that the packages from the ideal tree will match the same versions that are present in the virtual tree (lock file).
const errors = validateLockfile(virtualInventory, arb.idealTree.inventory)
+ // Verifies that the root packageExtensions state matches the lockfile and is still consistent with the locked tree.
+ errors.push(...validatePackageExtensions(virtualArb.virtualTree, arb.idealTree))
+ // Verifies that the root .npm-extension file matches the lockfile hash.
+ // The hash comes from discovering the file (no import or execution), so this holds even under ignore-extension/ignore-scripts.
+ const { NpmExtension } = require('@npmcli/arborist')
+ let fileHash = null
+ try {
+ fileHash = new NpmExtension({ root: where, extensionFile: opts.extensionFile }).hash
+ } catch (err) {
+ errors.push(`Invalid: ${err.message}`)
+ }
+ errors.push(...validateNpmExtension(virtualArb.virtualTree, fileHash))
if (errors.length) {
throw this.usageError(
- '`npm ci` can only install packages when your package.json and package-lock.json or npm-shrinkwrap.json are in sync. ' +
+ '`npm ci` can only install packages when your package.json and package-lock.json are in sync. ' +
'Please update your lock file with `npm install` before continuing.\n\n' +
errors.join('\n')
)
@@ -107,12 +132,24 @@ class CI extends ArboristWorkspaceCmd {
})
}
+ // Root lifecycle scripts for `npm ci` mirror those run by `npm install`. `preinstall` runs *before* reify so that scripts can bootstrap the environment (e.g. private-registry auth) before any dependency is fetched or unpacked. The remaining scripts run after reify as they did before.
+ const scriptShell = this.npm.config.get('script-shell') || undefined
+ const runRootScript = (event) => runScript({
+ path: where,
+ args: [],
+ scriptShell,
+ stdio: 'inherit',
+ event,
+ })
+
+ if (!ignoreScripts) {
+ await runRootScript('preinstall')
+ }
+
await arb.reify(opts)
- // run the same set of scripts that `npm install` runs.
if (!ignoreScripts) {
- const scripts = [
- 'preinstall',
+ const postReifyScripts = [
'install',
'postinstall',
'prepublish', // XXX should we remove this finally??
@@ -120,15 +157,8 @@ class CI extends ArboristWorkspaceCmd {
'prepare',
'postprepare',
]
- const scriptShell = this.npm.config.get('script-shell') || undefined
- for (const event of scripts) {
- await runScript({
- path: where,
- args: [],
- scriptShell,
- stdio: 'inherit',
- event,
- })
+ for (const event of postReifyScripts) {
+ await runRootScript(event)
}
}
await reifyFinish(this.npm, arb)
diff --git a/deps/npm/lib/commands/completion.js b/deps/npm/lib/commands/completion.js
index 499afcb5c68..712cf735883 100644
--- a/deps/npm/lib/commands/completion.js
+++ b/deps/npm/lib/commands/completion.js
@@ -37,6 +37,7 @@ class Completion extends BaseCommand {
static name = 'completion'
// Completion command uses args differently - they represent the command line being completed, not actual arguments to this command, so we use an empty definitions object to prevent flag validation
static definitions = []
+ static skipConfigValidation = true
// completion for the completion command
static async completion (opts) {
diff --git a/deps/npm/lib/commands/dedupe.js b/deps/npm/lib/commands/dedupe.js
index e703e9fb374..0b3fee45bf2 100644
--- a/deps/npm/lib/commands/dedupe.js
+++ b/deps/npm/lib/commands/dedupe.js
@@ -1,5 +1,6 @@
const reifyFinish = require('../utils/reify-finish.js')
const resolveAllowScripts = require('../utils/resolve-allow-scripts.js')
+const { patchRelaxOpts } = require('../utils/cli-only-flag.js')
const ArboristWorkspaceCmd = require('../arborist-cmd.js')
// dedupe duplicated packages, or find them in the tree
@@ -47,6 +48,7 @@ class Dedupe extends ArboristWorkspaceCmd {
save: false,
workspaces: this.workspaceNames,
allowScripts: allowScriptsPolicy,
+ ...patchRelaxOpts(this.npm.config),
}
const arb = new Arborist(opts)
await arb.dedupe(opts)
diff --git a/deps/npm/lib/commands/doctor.js b/deps/npm/lib/commands/doctor.js
index f01b05bead2..203f6d156c5 100644
--- a/deps/npm/lib/commands/doctor.js
+++ b/deps/npm/lib/commands/doctor.js
@@ -99,6 +99,7 @@ class Doctor extends BaseCommand {
static name = 'doctor'
static params = ['registry']
static ignoreImplicitWorkspace = false
+ static skipConfigValidation = true
static usage = [`[${checks.flatMap(s => s.groups)
.filter((value, index, self) => self.indexOf(value) === index && value !== 'ping')
.join('] [')}]`]
diff --git a/deps/npm/lib/commands/help.js b/deps/npm/lib/commands/help.js
index a684667e324..d520dd1cceb 100644
--- a/deps/npm/lib/commands/help.js
+++ b/deps/npm/lib/commands/help.js
@@ -25,6 +25,7 @@ class Help extends BaseCommand {
static name = 'help'
static usage = ['<term> [<terms..>]']
static params = ['viewer']
+ static skipConfigValidation = true
static async completion (opts, npm) {
if (opts.conf.argv.remain.length > 2) {
diff --git a/deps/npm/lib/commands/install.js b/deps/npm/lib/commands/install.js
index 11bdb1b76c2..2fd9bc8d5cd 100644
--- a/deps/npm/lib/commands/install.js
+++ b/deps/npm/lib/commands/install.js
@@ -7,6 +7,7 @@ const checks = require('npm-install-checks')
const reifyFinish = require('../utils/reify-finish.js')
const resolveAllowScripts = require('../utils/resolve-allow-scripts.js')
const strictAllowScriptsPreflight = require('../utils/strict-allow-scripts-preflight.js')
+const { patchRelaxOpts } = require('../utils/cli-only-flag.js')
const ArboristWorkspaceCmd = require('../arborist-cmd.js')
class Install extends ArboristWorkspaceCmd {
@@ -152,14 +153,30 @@ class Install extends ArboristWorkspaceCmd {
add: args,
workspaces: this.workspaceNames,
allowScripts: allowScriptsPolicy,
+ // patch relax flags are honored only when passed on the command line
+ ...patchRelaxOpts(this.npm.config),
}
+
+ // Root lifecycle scripts only run for a bare `npm install` in a local project. `preinstall` runs *before* Arborist touches the filesystem so that scripts can bootstrap the environment (e.g. set up private-registry auth, generate files consumed during resolution) before dependencies are fetched or unpacked. The remaining scripts run after reify as they did before.
+ const runRootLifecycle = !args.length && !isGlobalInstall && !ignoreScripts
+ const runRootScript = (event) => runScript({
+ path: where,
+ args: [],
+ scriptShell,
+ stdio: 'inherit',
+ event,
+ })
+
+ if (runRootLifecycle) {
+ await runRootScript('preinstall')
+ }
+
const arb = new Arborist(opts)
await strictAllowScriptsPreflight({ arb, npm: this.npm, idealTreeOpts: opts })
await arb.reify(opts)
- if (!args.length && !isGlobalInstall && !ignoreScripts) {
- const scripts = [
- 'preinstall',
+ if (runRootLifecycle) {
+ const postReifyScripts = [
'install',
'postinstall',
'prepublish', // XXX(npm9) should we remove this finally??
@@ -167,14 +184,8 @@ class Install extends ArboristWorkspaceCmd {
'prepare',
'postprepare',
]
- for (const event of scripts) {
- await runScript({
- path: where,
- args: [],
- scriptShell,
- stdio: 'inherit',
- event,
- })
+ for (const event of postReifyScripts) {
+ await runRootScript(event)
}
}
await reifyFinish(this.npm, arb)
diff --git a/deps/npm/lib/commands/link.js b/deps/npm/lib/commands/link.js
index cad499b2df8..cd6782a1f98 100644
--- a/deps/npm/lib/commands/link.js
+++ b/deps/npm/lib/commands/link.js
@@ -6,6 +6,7 @@ const semver = require('semver')
const reifyFinish = require('../utils/reify-finish.js')
const resolveAllowScripts = require('../utils/resolve-allow-scripts.js')
const strictAllowScriptsPreflight = require('../utils/strict-allow-scripts-preflight.js')
+const { patchRelaxOpts } = require('../utils/cli-only-flag.js')
const ArboristWorkspaceCmd = require('../arborist-cmd.js')
class Link extends ArboristWorkspaceCmd {
@@ -74,6 +75,7 @@ class Link extends ArboristWorkspaceCmd {
const { policy: allowScriptsPolicy } = await resolveAllowScripts(this.npm)
const globalOpts = {
...this.npm.flatOptions,
+ ...patchRelaxOpts(this.npm.config),
Arborist,
path: globalTop,
global: true,
@@ -130,6 +132,7 @@ class Link extends ArboristWorkspaceCmd {
// reify all the pending names as symlinks there
const localArb = new Arborist({
...this.npm.flatOptions,
+ ...patchRelaxOpts(this.npm.config),
prune: false,
path: this.npm.prefix,
save,
@@ -158,6 +161,7 @@ class Link extends ArboristWorkspaceCmd {
const Arborist = require('@npmcli/arborist')
const arb = new Arborist({
...this.npm.flatOptions,
+ ...patchRelaxOpts(this.npm.config),
Arborist,
path: globalTop,
global: true,
diff --git a/deps/npm/lib/commands/ls.js b/deps/npm/lib/commands/ls.js
index 8b9b4f3f5d2..ac0f4817efe 100644
--- a/deps/npm/lib/commands/ls.js
+++ b/deps/npm/lib/commands/ls.js
@@ -278,6 +278,21 @@ const augmentItemWithIncludeMetadata = (node, item) => {
return item
}
+// Render a manifest-extension provenance object as a short "field.name" list, empty when none.
+const formatExtensionApplied = (applied) => {
+ if (!applied) {
+ return ''
+ }
+ const fields = ['dependencies', 'optionalDependencies', 'peerDependencies', 'peerDependenciesMeta']
+ const parts = []
+ for (const field of fields) {
+ for (const name of applied[field] || []) {
+ parts.push(`${field}.${name}`)
+ }
+ }
+ return parts.join(', ')
+}
+
const getHumanOutputItem = (node, { args, chalk, global, long }) => {
const { pkgid, path } = node
const workspacePkgId = chalk.blueBright(pkgid)
@@ -333,6 +348,21 @@ const getHumanOutputItem = (node, { args, chalk, global, long }) => {
? ' ' + chalk.dim('overridden')
: ''
) +
+ (
+ node.patched
+ ? ' ' + chalk.cyan(`[patched: ${node.patched.path}]`)
+ : ''
+ ) +
+ (
+ formatExtensionApplied(node.packageExtensionsApplied)
+ ? ' ' + chalk.dim(`packageExtensions: ${formatExtensionApplied(node.packageExtensionsApplied)}`)
+ : ''
+ ) +
+ (
+ formatExtensionApplied(node.npmExtensionApplied)
+ ? ' ' + chalk.dim(`.npm-extension: ${formatExtensionApplied(node.npmExtensionApplied)}`)
+ : ''
+ ) +
(isGitNode(node) ? ` (${node.resolved})` : '') +
(node.isLink ? ` -> ${relativePrefix}${targetLocation}` : '') +
(long ? `\n${node.package.description || ''}` : '')
@@ -357,6 +387,14 @@ const getJsonOutputItem = (node, { global, long }) => {
item.overridden = node.overridden
}
+ if (node.packageExtensionsApplied) {
+ item.packageExtensionsApplied = node.packageExtensionsApplied
+ }
+
+ if (node.npmExtensionApplied) {
+ item.npmExtensionApplied = node.npmExtensionApplied
+ }
+
item[_name] = node.name
// special formatting for top-level package name
@@ -389,6 +427,10 @@ const getJsonOutputItem = (node, { global, long }) => {
item.invalid = node[_invalid]
}
+ if (node.patched) {
+ item.patched = node.patched.path
+ }
+
if (node[_missing] && !isOptional(node)) {
item.required = node[_required]
item.missing = true
@@ -404,7 +446,6 @@ const getJsonOutputItem = (node, { global, long }) => {
// Undeclared workspaces no longer need filtering here: loadActual synthesizes their root links so their edges resolve instead of reporting missing.
const filterLinkedStrategyEdges = ({ currentDepth }) => (edge) => {
// Skip dev edges for non-root packages (store packages)
- /* istanbul ignore next: store packages no longer carry dev edges, so this guard is not exercised by tests */
if (currentDepth > 0 && edge.dev) {
return false
}
diff --git a/deps/npm/lib/commands/pack.js b/deps/npm/lib/commands/pack.js
index 9c4b59657f4..3918c77f8f5 100644
--- a/deps/npm/lib/commands/pack.js
+++ b/deps/npm/lib/commands/pack.js
@@ -71,10 +71,8 @@ class Pack extends BaseCommand {
tarballs.push(await getContents(manifest, tarballData))
}
- for (const [index, tar] of Object.entries(tarballs)) {
- // XXX(BREAKING_CHANGE): publish outputs a json object with package names as keys.
- // Pack should do the same here instead of an array
- logTar(tar, { unicode, json, key: index })
+ for (const tar of tarballs) {
+ logTar(tar, { unicode, json, key: tar.name })
if (!json) {
output.standard(tar.filename.replace(/^@/, '').replace(/\//, '-'))
}
diff --git a/deps/npm/lib/commands/patch.js b/deps/npm/lib/commands/patch.js
new file mode 100644
index 00000000000..67b8bc45555
--- /dev/null
+++ b/deps/npm/lib/commands/patch.js
@@ -0,0 +1,740 @@
+const { resolve, relative, join, dirname, basename, isAbsolute, sep } = require('node:path')
+const { tmpdir } = require('node:os')
+const { cp, mkdir, mkdtemp, readFile, rm, writeFile } = require('node:fs/promises')
+const pacote = require('pacote')
+const npa = require('npm-package-arg')
+const semver = require('semver')
+const git = require('@npmcli/git')
+const PackageJson = require('@npmcli/package-json')
+const { log, output } = require('proc-log')
+const { matchSelector, parseSelector } = require('@npmcli/arborist/lib/patched-dependencies.js')
+const { applyPatchToDir } = require('@npmcli/arborist/lib/patch.js')
+const { patchRelaxOpts } = require('../utils/cli-only-flag.js')
+const BaseCommand = require('../base-cmd.js')
+const { diffDirs } = require('../utils/patch-diff.js')
+const reifyFinish = require('../utils/reify-finish.js')
+
+const SUBCOMMANDS = ['add', 'commit', 'update', 'ls', 'rm']
+
+// Marker left in a conflicted update edit dir so the finalizing commit drops the old exact selector.
+const UPDATE_MARKER = '.npm-patch-update.json'
+
+// fs.cp filter that skips a git working directory.
+const notGitDir = src => !src.split(sep).includes('.git')
+
+// Build the selector key stored in patchedDependencies, e.g. lodash@4.17.21.
+const selectorKey = (name, version) => `${name}@${version}`
+
+// Posix-relative path to a patch file inside patches-dir for name@version.
+const patchFilePath = (patchesDir, name, version) =>
+ `${patchesDir}/${name}@${version}.patch`.split('\\').join('/')
+
+// Recover the exact version a patch file was authored against from its name.
+// commit always writes <name>@<version>.patch, so the baseline is encoded there.
+const patchFileVersion = patchPath => {
+ const { spec } = parseSelector(basename(patchPath).replace(/\.patch$/, ''))
+ return semver.valid(spec)
+}
+
+const patchErr = (message, code, extra = {}) =>
+ Object.assign(new Error(message), { code, ...extra })
+
+// The project-root-relative posix path for abs, or null if abs escapes the root.
+const containedRelative = (root, abs) => {
+ const rel = relative(root, abs).split('\\').join('/')
+ return (!rel || rel.startsWith('..') || isAbsolute(rel)) ? null : rel
+}
+
+class Patch extends BaseCommand {
+ static description = 'Apply local patches to installed dependencies'
+ static name = 'patch'
+ static params = [
+ 'patches-dir',
+ 'allow-unused-patches',
+ 'ignore-patch-failures',
+ 'edit-dir',
+ 'ignore-existing',
+ 'keep-edit-dir',
+ 'to',
+ 'registry',
+ ]
+
+ static usage = [
+ '<pkg>[@<version>]',
+ 'add <pkg>[@<version>] [--edit-dir <path>] [--ignore-existing]',
+ 'commit <edit-dir> [--patches-dir <dir>] [--keep-edit-dir]',
+ 'update <pkg>[@<old-version>] [--to <new-version>] [--patches-dir <dir>]',
+ 'ls',
+ 'rm <pkg>[@<version>]',
+ ]
+
+ static async completion (opts) {
+ if (opts.conf.argv.remain.length === 2) {
+ return SUBCOMMANDS
+ }
+ return []
+ }
+
+ async exec (args) {
+ const [sub, ...rest] = args
+ if (!sub) {
+ throw this.usageError()
+ }
+ // explicit subcommand, else treat the bare arg as `patch add <pkg>`
+ if (SUBCOMMANDS.includes(sub)) {
+ return this[sub](rest)
+ }
+ return this.add(args)
+ }
+
+ get #root () {
+ return this.npm.localPrefix
+ }
+
+ #newArborist (opts = {}) {
+ const Arborist = require('@npmcli/arborist')
+ return new Arborist({
+ ...this.npm.flatOptions,
+ ...patchRelaxOpts(this.npm.config),
+ path: this.#root,
+ ...opts,
+ })
+ }
+
+ async #loadActual () {
+ return this.#newArborist().loadActual()
+ }
+
+ // Resolve a user spec to a concrete registry name@version to patch.
+ async #resolveTarget (spec) {
+ const parsed = npa(spec)
+ if (parsed.type && !parsed.registry) {
+ throw this.#nonRegistryError(spec)
+ }
+
+ const { name } = parsed
+ const tree = await this.#loadActual()
+ // group every installed node by version so mixed-source duplicates are seen
+ const installed = new Map()
+ for (const node of tree.inventory.values()) {
+ if (node.name === name && !node.isProjectRoot && node.version) {
+ const nodes = installed.get(node.version) || []
+ nodes.push(node)
+ installed.set(node.version, nodes)
+ }
+ }
+
+ // a version cannot be patched if a consumer depends on it through a non-registry spec (file:, git:, http(s)); npm: aliases stay registry.
+ // checking the edges (not isRegistryDependency) avoids rejecting edgeless store nodes and linked symlinks, which are registry deps.
+ const ensureRegistry = version => {
+ const nodes = installed.get(version) || []
+ if (nodes.some(n => [...n.edgesIn].some(e => e.spec && !npa(e.spec).registry))) {
+ throw this.#nonRegistryError(`${name}@${version}`)
+ }
+ }
+
+ // an explicit version/range is honored even when not present in the tree
+ if (parsed.rawSpec && parsed.rawSpec !== '*' && parsed.rawSpec !== 'latest') {
+ const exact = semver.valid(parsed.fetchSpec)
+ if (exact) {
+ ensureRegistry(exact)
+ return { name, version: exact }
+ }
+ const matches = [...installed.keys()].filter(v => semver.satisfies(v, parsed.fetchSpec))
+ if (matches.length > 1) {
+ throw this.#ambiguousError(name, matches, installed)
+ }
+ if (matches.length === 1) {
+ ensureRegistry(matches[0])
+ return { name, version: matches[0] }
+ }
+ // resolve the range against the registry
+ const mani = await pacote.manifest(spec, this.npm.flatOptions)
+ return { name: mani.name, version: mani.version }
+ }
+
+ if (installed.size === 0) {
+ throw Object.assign(
+ new Error(`No installed version of "${name}" found. ` +
+ `Run "npm install" first, or pass an explicit version.`),
+ { code: 'EPATCHNOTINSTALLED' }
+ )
+ }
+ if (installed.size > 1) {
+ throw this.#ambiguousError(name, [...installed.keys()], installed)
+ }
+ const [version] = [...installed.keys()]
+ ensureRegistry(version)
+ return { name, version }
+ }
+
+ #nonRegistryError (label) {
+ return Object.assign(
+ new Error(`Cannot patch non-registry dependency "${label}". ` +
+ `Only registry dependencies can be patched; edit the source directly.`),
+ { code: 'EPATCHNONREGISTRY' }
+ )
+ }
+
+ #ambiguousError (name, versions, installed) {
+ const lines = versions.map(version => {
+ const node = installed.get(version)[0]
+ const dependant = [...node.edgesIn][0]?.from?.location || '(root)'
+ return ` ${selectorKey(name, version)} (via ${dependant})`
+ })
+ return Object.assign(
+ new Error(`Multiple versions of "${name}" are installed:\n${lines.join('\n')}\n` +
+ `Re-run with an exact selector, e.g. "npm patch add ${selectorKey(name, versions[0])}".`),
+ { code: 'EPATCHAMBIGUOUS' }
+ )
+ }
+
+ // Create (or reuse, with --edit-dir) the directory a package is extracted into for editing.
+ async #makeEditDir (name, version) {
+ let editDir = this.npm.config.get('edit-dir')
+ if (!editDir) {
+ const base = join(tmpdir(), 'npm-patch')
+ await mkdir(base, { recursive: true })
+ return mkdtemp(join(base, `${name.replace(/\//g, '+')}@${version}-`))
+ }
+ editDir = resolve(editDir)
+ if (this.npm.config.get('ignore-existing')) {
+ await rm(editDir, { recursive: true, force: true })
+ }
+ await mkdir(editDir, { recursive: true })
+ return editDir
+ }
+
+ async add (args) {
+ if (args.length !== 1) {
+ throw this.usageError()
+ }
+ const { name, version } = await this.#resolveTarget(args[0])
+ const editDir = await this.#makeEditDir(name, version)
+
+ await pacote.extract(selectorKey(name, version), editDir, this.npm.flatOptions)
+
+ output.standard(`You can now edit the following directory: ${editDir}`)
+ output.standard(`When done, run: npm patch commit ${editDir}`)
+ }
+
+ async commit (args) {
+ if (args.length !== 1) {
+ throw this.usageError()
+ }
+ const editDir = resolve(args[0])
+ const { content: edited } = await PackageJson.normalize(editDir).catch(() => {
+ throw Object.assign(
+ new Error(`No package.json found in edit directory: ${editDir}`),
+ { code: 'EPATCHNOEDITDIR' }
+ )
+ })
+ const { name, version } = edited
+ if (!name || !version) {
+ throw new Error(`Edit directory package.json is missing name or version: ${editDir}`)
+ }
+
+ // a conflicted `patch update` leaves a marker so this commit drops the renamed-from selector
+ // it is kept on disk (and excluded from the diff) so a re-run after a no-op resolution still finalizes the update
+ const markerPath = join(editDir, UPDATE_MARKER)
+ const markerRaw = await readFile(markerPath, 'utf8').catch(() => null)
+ let marker = null
+ if (markerRaw !== null) {
+ try {
+ marker = JSON.parse(markerRaw)
+ } catch {
+ throw patchErr(`invalid update marker in ${editDir}`, 'EPATCHBADMARKER')
+ }
+ }
+
+ // extract a clean baseline to diff against
+ const base = await mkdtemp(join(tmpdir(), 'npm-patch-base-'))
+ let diff, packageJsonChanged
+ try {
+ await pacote.extract(selectorKey(name, version), base, this.npm.flatOptions)
+ ;({ diff, packageJsonChanged } = await diffDirs(base, editDir, new Set([UPDATE_MARKER])))
+ } finally {
+ await rm(base, { recursive: true, force: true })
+ }
+
+ if (!diff) {
+ // package.json is excluded from patches, so an edit limited to it captures nothing
+ const reason = packageJsonChanged
+ ? `only package.json changed in ${editDir}, which is not patchable; nothing to commit`
+ : `no changes detected in ${editDir}; nothing to commit`
+ log.warn('patch', reason)
+ return
+ }
+ if (packageJsonChanged) {
+ log.warn('patch', 'changes to package.json are not included in patches and were ignored')
+ }
+
+ const patchesDir = this.npm.config.get('patches-dir')
+ const absPatch = resolve(this.#root, patchFilePath(patchesDir, name, version))
+ // refuse to write outside the project so the patch set stays in the repo
+ const relPatch = containedRelative(this.#root, absPatch)
+ if (!relPatch) {
+ throw Object.assign(
+ new Error(`patches-dir "${patchesDir}" resolves outside the project root.`),
+ { code: 'EPATCHUNSAFE' }
+ )
+ }
+ await mkdir(dirname(absPatch), { recursive: true })
+ await writeFile(absPatch, diff)
+
+ const pkgJson = await PackageJson.load(this.#root)
+ const patchedDependencies = { ...pkgJson.content.patchedDependencies }
+ const newKey = selectorKey(name, version)
+ patchedDependencies[newKey] = relPatch
+ // a marker left by a conflicted `patch update` for this package means a metadata-only finalize.
+ // its name is checked so a stray or forged marker can never hijack a normal commit.
+ const updateFinalize = !!marker && marker.name === name
+ let orphan = null
+ // an exact rename drops the renamed-from selector; a fork carries removeKey null and keeps the old entry.
+ // removeKey must be a real, same-package selector string, so a malformed marker can neither crash nor drop the wrong entry.
+ if (updateFinalize && typeof marker.removeKey === 'string' && marker.removeKey !== newKey &&
+ patchedDependencies[marker.removeKey] !== undefined &&
+ parseSelector(marker.removeKey).name === name) {
+ orphan = this.#dropSelector(patchedDependencies, marker.removeKey)
+ }
+ pkgJson.update({ patchedDependencies })
+ await pkgJson.save()
+
+ // finishing a conflicted update is metadata-only (like update itself): the new version may not be installed yet
+ const arb = updateFinalize
+ ? this.#newArborist({ packageLockOnly: true, allowUnusedPatches: true, audit: false })
+ : this.#newArborist()
+ await arb.reify(arb.options)
+ await reifyFinish(this.npm, arb)
+
+ // remove the renamed-from patch file only after the lockfile is durable
+ await this.#removePatchFile(orphan)
+
+ if (!this.npm.config.get('keep-edit-dir')) {
+ await rm(editDir, { recursive: true, force: true })
+ }
+
+ output.standard(`Patched ${newKey} -> ${relPatch}`)
+ }
+
+ // Remove a selector from the map; return its patch file path if nothing else references it.
+ #dropSelector (patched, key) {
+ const patchPath = patched[key]
+ delete patched[key]
+ /* istanbul ignore next - the shared-file branch only fires when two selectors point at one patch */
+ return (patchPath && !Object.values(patched).includes(patchPath)) ? patchPath : null
+ }
+
+ // Delete an orphaned patch file, but never one that escapes the project root.
+ async #removePatchFile (patchPath) {
+ if (!patchPath) {
+ return
+ }
+ const abs = resolve(this.#root, patchPath)
+ /* istanbul ignore else - defensive: orphaned paths come from the manifest and stay in-project */
+ if (containedRelative(this.#root, abs)) {
+ await rm(abs, { force: true })
+ }
+ }
+
+ async update (args) {
+ if (args.length !== 1) {
+ throw this.usageError()
+ }
+
+ const pkgJson = await PackageJson.load(this.#root)
+ const patched = { ...pkgJson.content.patchedDependencies }
+ const entry = this.#resolveUpdateEntry(args[0], patched)
+
+ const baseVersion = patchFileVersion(entry.patchPath)
+ if (!baseVersion) {
+ throw patchErr(
+ `cannot determine the version "${entry.patchPath}" was authored against; rebase by hand`,
+ 'EPATCHBASE'
+ )
+ }
+
+ const installedVersions = await this.#installedVersions(entry.name)
+ const newVersion = this.#resolveNewVersion(entry, installedVersions)
+ if (newVersion === baseVersion) {
+ throw patchErr(`nothing to update: the patch already targets ${selectorKey(entry.name, newVersion)}`, 'EPATCHNOOP')
+ }
+ const newKey = selectorKey(entry.name, newVersion)
+ if (patched[newKey] && newKey !== entry.key) {
+ throw patchErr(
+ `an entry already exists for ${newKey}; use "npm patch rm" first or rebase manually`,
+ 'EPATCHEXISTS'
+ )
+ }
+
+ const rebase = await this.#rebasePatch({
+ name: entry.name,
+ baseVersion,
+ newVersion,
+ patchAbs: resolve(this.#root, entry.patchPath),
+ })
+ try {
+ if (rebase.conflicted) {
+ const editDir = await this.#makeEditDir(entry.name, newVersion)
+ try {
+ await cp(rebase.repo, editDir, { recursive: true, filter: notGitDir })
+ // mark the conflict so the finalizing commit knows this is an update finalize.
+ // an exact selector is a rename (drop the old key); a range/name-only is a fork (keep it).
+ const removeKey = entry.spec && semver.valid(entry.spec) ? entry.key : null
+ await writeFile(join(editDir, UPDATE_MARKER), JSON.stringify({ name: entry.name, removeKey }) + '\n')
+ } catch (er) {
+ // discard a temp edit dir we created if the copy or marker write fails; never a user-supplied --edit-dir
+ /* istanbul ignore next - a failing copy/marker write is not deterministically reproducible */
+ if (!this.npm.config.get('edit-dir')) {
+ await rm(editDir, { recursive: true, force: true })
+ }
+ /* istanbul ignore next */
+ throw er
+ }
+ output.standard(`Patch did not apply cleanly to ${newKey}.`)
+ output.standard(`Resolve the conflicts in: ${editDir}`)
+ output.standard(`When done, run: npm patch commit ${editDir}`)
+ return
+ }
+
+ const { diff } = await diffDirs(rebase.newDir, rebase.repo)
+ if (!diff) {
+ throw patchErr(
+ `the patch no longer changes ${newKey}; remove it with "npm patch rm" instead`,
+ 'EPATCHEMPTY'
+ )
+ }
+ await this.#finalizeUpdate({
+ pkgJson, patched, entry, name: entry.name, newVersion, newKey, diff, installedVersions,
+ })
+ } finally {
+ await rm(rebase.work, { recursive: true, force: true })
+ }
+ }
+
+ // Identify the single patchedDependencies entry the update targets.
+ #resolveUpdateEntry (spec, patched) {
+ const target = npa(spec)
+ const name = target.name
+ const oldSpec = target.rawSpec && target.rawSpec !== '*' ? target.fetchSpec : null
+ const keys = Object.keys(patched)
+
+ if (oldSpec) {
+ const key = selectorKey(name, oldSpec)
+ if (!patched[key]) {
+ throw patchErr(`no patch registered for ${key}`, 'EPATCHNOTFOUND')
+ }
+ return { key, name, spec: oldSpec, patchPath: patched[key] }
+ }
+
+ const matches = keys.filter(k => parseSelector(k).name === name)
+ if (!matches.length) {
+ throw patchErr(`no patch to update for "${name}"`, 'EPATCHNOTFOUND')
+ }
+ if (matches.length > 1) {
+ throw patchErr(
+ `multiple patches match "${name}":\n${matches.map(k => ` ${k}`).join('\n')}\n` +
+ `Re-run with an explicit selector, e.g. "npm patch update ${matches[0]}".`,
+ 'EPATCHAMBIGUOUS'
+ )
+ }
+ const key = matches[0]
+ return { key, name, spec: parseSelector(key).spec, patchPath: patched[key] }
+ }
+
+ // Determine the version to rebase onto: --to, else the installed version matching the selector.
+ #resolveNewVersion (entry, installedVersions) {
+ const to = this.npm.config.get('to')
+ if (to) {
+ const valid = semver.valid(to)
+ if (!valid) {
+ throw patchErr(`--to "${to}" is not a valid version`, 'EPATCHBADTO')
+ }
+ // update finalizes with allowUnusedPatches, so a --to absent from the tree records an unused patch silently.
+ // The next plain install then rejects with EPATCHUNUSED, so warn now to surface the mismatch early.
+ if (installedVersions !== null && !installedVersions.includes(valid)) {
+ log.warn('patch',
+ `${selectorKey(entry.name, valid)} is not installed; ` +
+ `bump the dependency and reinstall, or the next "npm install" will fail with EPATCHUNUSED.`)
+ }
+ return valid
+ }
+
+ if (installedVersions === null) {
+ throw patchErr(
+ `could not read the lockfile for "${entry.name}"; ` +
+ `run "npm install" first or pass --to <new-version>`,
+ 'EPATCHSTALE'
+ )
+ }
+ const { spec } = entry
+ let matching
+ if (spec && semver.valid(spec)) {
+ matching = installedVersions.filter(v => semver.eq(v, spec))
+ } else if (spec) {
+ matching = installedVersions.filter(v => semver.satisfies(v, spec))
+ } else {
+ matching = installedVersions
+ }
+ if (!matching.length) {
+ throw patchErr(
+ `no installed version matches the patch selector "${entry.key}"; ` +
+ `pass --to <new-version> to rebase onto a specific version`,
+ 'EPATCHSTALE'
+ )
+ }
+ return matching.sort(semver.rcompare)[0]
+ }
+
+ // Distinct registry-installed versions of a package from the lockfile, or null when it cannot be loaded.
+ // Uses loadVirtual so the lockfile's own validity gates staleness and links/workspaces are excluded.
+ async #installedVersions (name) {
+ let tree
+ try {
+ tree = await this.#newArborist().loadVirtual()
+ } catch {
+ return null
+ }
+ const versions = new Set()
+ for (const node of tree.inventory.values()) {
+ if (node.isProjectRoot || node.isWorkspace || node.isLink || !node.version) {
+ continue
+ }
+ /* istanbul ignore else - other-named nodes are skipped; only exercised with multi-package trees */
+ if (node.name === name) {
+ versions.add(node.version)
+ }
+ }
+ return [...versions]
+ }
+
+ // 3-way merge the existing patch onto the new version via a throwaway git repo.
+ // Returns { work, repo, newDir, conflicted }; the caller removes work on success.
+ async #rebasePatch ({ name, baseVersion, newVersion, patchAbs }) {
+ const work = await mkdtemp(join(tmpdir(), 'npm-patch-rebase-'))
+ try {
+ const baseDir = join(work, 'base')
+ const newDir = join(work, 'new')
+ const repo = join(work, 'repo')
+ await pacote.extract(selectorKey(name, baseVersion), baseDir, this.npm.flatOptions)
+ await pacote.extract(selectorKey(name, newVersion), newDir, this.npm.flatOptions)
+ await mkdir(repo, { recursive: true })
+
+ const id = ['-c', 'user.name=npm', '-c', 'user.email=npm@npmjs.com', '-c', 'commit.gpgsign=false']
+ await this.#git(['init', '-q', '-b', 'base'], repo)
+ // base = the version the patch was authored against
+ await cp(baseDir, repo, { recursive: true })
+ await this.#git(['add', '-Af'], repo)
+ await this.#git([...id, 'commit', '-qm', 'base', '--allow-empty'], repo)
+ // theirs = base + the existing patch, applied with the same jsdiff helper installs use
+ await this.#git(['checkout', '-q', '-b', 'theirs'], repo)
+ try {
+ await applyPatchToDir({ patch: await readFile(patchAbs), cwd: repo })
+ } catch (er) {
+ throw patchErr(
+ `the existing patch no longer applies to its baseline ${selectorKey(name, baseVersion)}; rebase by hand`,
+ 'EPATCHBASE',
+ { cause: er }
+ )
+ }
+ await this.#git(['add', '-Af'], repo)
+ await this.#git([...id, 'commit', '-qm', 'theirs', '--allow-empty'], repo)
+ // ours = the new version, branched from base
+ await this.#git(['checkout', '-q', '-b', 'ours', 'base'], repo)
+ await this.#git(['rm', '-rqf', '.'], repo)
+ await cp(newDir, repo, { recursive: true })
+ await this.#git(['add', '-Af'], repo)
+ await this.#git([...id, 'commit', '-qm', 'ours', '--allow-empty'], repo)
+ // replay the patch's intent onto the new version
+ let conflicted = false
+ try {
+ await this.#git([...id, 'merge', '--no-edit', 'theirs'], repo)
+ } catch (er) {
+ // a genuine conflict leaves unmerged paths; any other non-zero exit is a real git failure
+ const unmerged = await this.#git(['ls-files', '--unmerged'], repo)
+ /* istanbul ignore else - a non-conflict merge failure is a git/environment fault */
+ if (String(unmerged.stdout).trim()) {
+ conflicted = true
+ } else {
+ throw er
+ }
+ }
+ return { work, repo, newDir, conflicted }
+ } catch (er) {
+ await rm(work, { recursive: true, force: true })
+ throw er
+ }
+ }
+
+ #git (args, cwd) {
+ return git.spawn(args, {
+ cwd,
+ env: { ...process.env, GIT_CONFIG_GLOBAL: '/dev/null', GIT_CONFIG_SYSTEM: '/dev/null' },
+ })
+ }
+
+ // Apply the selector rules, write the new patch, and sync the lockfile without touching node_modules.
+ async #finalizeUpdate (opts) {
+ const { pkgJson, patched, entry, name, newVersion, newKey, diff, installedVersions } = opts
+ const patchesDir = this.npm.config.get('patches-dir')
+ const absPatch = resolve(this.#root, patchFilePath(patchesDir, name, newVersion))
+ const relPatch = containedRelative(this.#root, absPatch)
+ if (!relPatch) {
+ throw patchErr(`patches-dir "${patchesDir}" resolves outside the project root.`, 'EPATCHUNSAFE')
+ }
+ // write the new patch first so no selector points at a missing file
+ await mkdir(dirname(absPatch), { recursive: true })
+ await writeFile(absPatch, diff)
+
+ patched[newKey] = relPatch
+ // drop the old selector only when it no longer wins any installed node, so a still-needed range survives
+ let orphan = null
+ if (entry.key !== newKey && this.#selectorUnused(patched, entry.key, name, installedVersions)) {
+ orphan = this.#dropSelector(patched, entry.key)
+ }
+
+ pkgJson.update({ patchedDependencies: patched })
+ await pkgJson.save()
+
+ // record the new patch integrity in the lockfile only; update never touches node_modules
+ const arb = this.#newArborist({ packageLockOnly: true, allowUnusedPatches: true, audit: false })
+ await arb.reify(arb.options)
+ await reifyFinish(this.npm, arb)
+
+ // remove the now-orphaned old patch file only after the lockfile is durable
+ await this.#removePatchFile(orphan)
+
+ output.standard(`Updated ${entry.key} -> ${newKey} (${relPatch})`)
+ }
+
+ // Whether `key` should be dropped once the new selector is added.
+ // An exact selector is a straight rename. A range/name-only selector is dropped only when it no longer
+ // wins any installed node under the installer's exact > range > name-only precedence, so a kept one is still used.
+ #selectorUnused (patched, key, name, installedVersions) {
+ const { spec } = parseSelector(key)
+ if (spec && semver.valid(spec)) {
+ return true
+ }
+ if (installedVersions === null) {
+ return false
+ }
+ const selectors = Object.keys(patched)
+ .filter(k => parseSelector(k).name === name)
+ .map(k => ({ ...parseSelector(k), key: k }))
+ for (const version of installedVersions) {
+ let winner
+ try {
+ winner = matchSelector(selectors, { name, version })
+ } catch {
+ /* istanbul ignore next - ambiguous overlapping ranges: keep the selector to be safe */
+ return false
+ }
+ /* istanbul ignore if - a still-winning selector is kept; only exercised with multiple installed versions */
+ if (winner?.key === key) {
+ return false
+ }
+ }
+ return true
+ }
+
+ async ls () {
+ const pkgJson = await PackageJson.normalize(this.#root).catch(() => ({ content: {} }))
+ const patched = pkgJson.content.patchedDependencies || {}
+ const keys = Object.keys(patched)
+ if (!keys.length) {
+ return
+ }
+
+ // count nodes per patch using the same precedence Arborist applies at install
+ const tree = await this.#loadActual()
+ const selectors = keys.map(key => ({ ...parseSelector(key), key, patchPath: patched[key] }))
+ const counts = new Map(keys.map(key => [key, 0]))
+ // only the overlapping range selectors that actually conflict on a node
+ const ambiguous = new Set()
+ for (const node of tree.inventory.values()) {
+ if (node.isProjectRoot || node.isLink || !node.version) {
+ continue
+ }
+ let winner = null
+ try {
+ winner = matchSelector(selectors, node)
+ } catch {
+ for (const s of selectors) {
+ if (s.name === node.name && s.spec && !semver.valid(s.spec) &&
+ semver.satisfies(node.version, s.spec)) {
+ ambiguous.add(s.key)
+ }
+ }
+ continue
+ }
+ if (winner) {
+ counts.set(winner.key, counts.get(winner.key) + 1)
+ }
+ }
+ for (const key of keys) {
+ if (ambiguous.has(key)) {
+ output.standard(`${patched[key]}\t${key}\t(error: ambiguous selectors)`)
+ continue
+ }
+ const n = counts.get(key)
+ output.standard(`${patched[key]}\t${key}\t(${n} node${n === 1 ? '' : 's'})`)
+ }
+ }
+
+ async rm (args) {
+ if (args.length !== 1) {
+ throw this.usageError()
+ }
+ const target = npa(args[0])
+ const targetName = target.name
+ const targetVersion = target.rawSpec && target.rawSpec !== '*' ? target.fetchSpec : null
+
+ const pkgJson = await PackageJson.load(this.#root)
+ const patched = { ...pkgJson.content.patchedDependencies }
+ const removed = []
+ for (const key of Object.keys(patched)) {
+ const { name, spec } = parseSelector(key)
+ if (name === targetName && (!targetVersion || spec === targetVersion)) {
+ removed.push(key)
+ }
+ }
+ if (!removed.length) {
+ throw Object.assign(
+ new Error(`No registered patch found for "${args[0]}".`),
+ { code: 'EPATCHNOTFOUND' }
+ )
+ }
+
+ for (const key of removed) {
+ const patchPath = patched[key]
+ delete patched[key]
+ // only delete the file when no remaining selector references it
+ if (!Object.values(patched).includes(patchPath)) {
+ const abs = resolve(this.#root, patchPath)
+ // never delete a path that escapes the project root
+ if (!containedRelative(this.#root, abs)) {
+ throw Object.assign(
+ new Error(`Refusing to delete patch outside the project root: ${patchPath}`),
+ { code: 'EPATCHUNSAFE' }
+ )
+ }
+ await rm(abs, { force: true })
+ }
+ }
+
+ if (Object.keys(patched).length) {
+ pkgJson.update({ patchedDependencies: patched })
+ } else {
+ delete pkgJson.content.patchedDependencies
+ }
+ await pkgJson.save()
+
+ const arb = this.#newArborist()
+ await arb.reify(arb.options)
+ await reifyFinish(this.npm, arb)
+
+ output.standard(`Removed patch${removed.length === 1 ? '' : 'es'}: ${removed.join(', ')}`)
+ }
+}
+
+module.exports = Patch
diff --git a/deps/npm/lib/commands/pkg.js b/deps/npm/lib/commands/pkg.js
index 3eccb24769e..a47c7695c3d 100644
--- a/deps/npm/lib/commands/pkg.js
+++ b/deps/npm/lib/commands/pkg.js
@@ -1,3 +1,4 @@
+const { inspect } = require('node:util')
const { output } = require('proc-log')
const PackageJson = require('@npmcli/package-json')
const BaseCommand = require('../base-cmd.js')
@@ -56,25 +57,40 @@ class Pkg extends BaseCommand {
}
async get (args, { path, workspace }) {
- this.npm.config.set('json', true)
const pkgJson = await PackageJson.load(path)
+ const json = this.npm.config.get('json')
- let result = pkgJson.content
+ // filter out the newline/indent symbols from the package-json object
+ let result = JSON.parse(JSON.stringify(pkgJson.content))
if (args.length) {
- result = new Queryable(result).query(args)
- // in case there's only a single argument and a single result from the query just prints that one element to stdout.
- // TODO(BREAKING_CHANGE): much like other places where we unwrap single item arrays this should go away.
- // it makes the behavior unknown for users who don't already know the shape of the data.
- if (Object.keys(result).length === 1 && args.length === 1) {
- result = result[args]
+ result = new Queryable(result).query(args, { unwrapSingleItemArrays: false })
+ if (args.length === 1 && !json && args[0] in result) {
+ if (workspace) {
+ return output.standard(`${workspace} ${result[args[0]]}`)
+ }
+ return output.standard(result[args[0]])
}
}
- // The display layer is responsible for calling JSON.stringify on the result
- // TODO: https://github.com/npm/cli/issues/5508 a raw mode has been requested similar to jq -r.
- // If that was added then this method should no longer set `json:true` all the time
- output.buffer(workspace ? { [workspace]: result } : result)
+ if (json) {
+ output.buffer(workspace ? { [workspace]: result } : result)
+ } else {
+ for (let [f, d] of Object.entries(result)) {
+ d = inspect(d, {
+ showHidden: false,
+ depth: 5,
+ colors: this.npm.color,
+ maxArrayLength: null,
+ })
+
+ if (workspace) {
+ output.standard(`${workspace} ${f} = ${d}`)
+ } else {
+ output.standard(`${f} = ${d}`)
+ }
+ }
+ }
}
async set (args, { path }) {
diff --git a/deps/npm/lib/commands/profile.js b/deps/npm/lib/commands/profile.js
index 926eb02f49c..9417989cf31 100644
--- a/deps/npm/lib/commands/profile.js
+++ b/deps/npm/lib/commands/profile.js
@@ -16,8 +16,6 @@ const knownProfileKeys = [
'two-factor auth',
'fullname',
'homepage',
- 'freenode',
- 'twitter',
'github',
'created',
'updated',
@@ -28,8 +26,6 @@ const writableProfileKeys = [
'password',
'fullname',
'homepage',
- 'freenode',
- 'twitter',
'github',
]
diff --git a/deps/npm/lib/commands/prune.js b/deps/npm/lib/commands/prune.js
index bc88a4e20de..e1790e40947 100644
--- a/deps/npm/lib/commands/prune.js
+++ b/deps/npm/lib/commands/prune.js
@@ -1,5 +1,6 @@
const reifyFinish = require('../utils/reify-finish.js')
const resolveAllowScripts = require('../utils/resolve-allow-scripts.js')
+const { patchRelaxOpts } = require('../utils/cli-only-flag.js')
const ArboristWorkspaceCmd = require('../arborist-cmd.js')
class Prune extends ArboristWorkspaceCmd {
@@ -26,6 +27,7 @@ class Prune extends ArboristWorkspaceCmd {
path: where,
workspaces: this.workspaceNames,
allowScripts: allowScriptsPolicy,
+ ...patchRelaxOpts(this.npm.config),
}
const arb = new Arborist(opts)
await arb.prune(opts)
diff --git a/deps/npm/lib/commands/publish.js b/deps/npm/lib/commands/publish.js
index aea01cc10e7..f13bc026f32 100644
--- a/deps/npm/lib/commands/publish.js
+++ b/deps/npm/lib/commands/publish.js
@@ -96,6 +96,9 @@ class Publish extends BaseCommand {
const spec = npa(args[0])
let manifest = await this.#getManifest(spec, opts)
+ // packageExtensions is root-only project policy and must never be published; fail fast so dry-run reports it too
+ this.#assertNoPackageExtensions(manifest)
+
// only run scripts for directory type publishes
if (spec.type === 'directory' && !ignoreScripts) {
await runScript({
@@ -118,10 +121,12 @@ class Publish extends BaseCommand {
workspaces: this.workspacePaths,
})
const pkgContents = await getContents(manifest, tarballData)
- const logPkg = () => logTar(pkgContents, { unicode, json, key: workspace })
+ const logPkg = () => logTar(pkgContents, { unicode, json, key: pkgContents.name })
// The purpose of re-reading the manifest is in case it changed, so that we send the latest and greatest thing to the registry note that publishConfig might have changed as well!
manifest = await this.#getManifest(spec, opts, true)
+ // re-check the authoritative manifest in case a lifecycle script introduced packageExtensions
+ this.#assertNoPackageExtensions(manifest)
const force = this.npm.config.get('force')
const isDefaultTag = this.npm.config.isDefault('tag') && !manifest.publishConfig?.tag
@@ -273,6 +278,16 @@ class Publish extends BaseCommand {
}
}
+ // packageExtensions is root-only project policy and must never reach the registry; private packages may keep it for local use
+ #assertNoPackageExtensions (manifest) {
+ if (!manifest.private && manifest.packageExtensions !== undefined) {
+ throw Object.assign(
+ new Error('packageExtensions is only honored at the project root and must not be published.'),
+ { code: 'EPACKAGEEXTENSIONS' }
+ )
+ }
+ }
+
// if it's a directory, read it from the file system
// otherwise, get the full metadata from whatever it is
// XXX can't pacote read the manifest from a directory?
diff --git a/deps/npm/lib/commands/query.js b/deps/npm/lib/commands/query.js
index f826cdc5265..f4282653c55 100644
--- a/deps/npm/lib/commands/query.js
+++ b/deps/npm/lib/commands/query.js
@@ -87,7 +87,7 @@ class Query extends BaseCommand {
} catch (err) {
log.verbose('loadVirtual', err.stack)
throw this.usageError(
- 'A package lock or shrinkwrap file is required in package-lock-only mode'
+ 'A package-lock.json file is required in package-lock-only mode'
)
}
} else {
@@ -113,7 +113,7 @@ class Query extends BaseCommand {
} catch (err) {
log.verbose('loadVirtual', err.stack)
throw this.usageError(
- 'A package lock or shrinkwrap file is required in package-lock-only mode'
+ 'A package-lock.json file is required in package-lock-only mode'
)
}
} else {
diff --git a/deps/npm/lib/commands/rebuild.js b/deps/npm/lib/commands/rebuild.js
index 17595aa4eb7..0f98b41e8c1 100644
--- a/deps/npm/lib/commands/rebuild.js
+++ b/deps/npm/lib/commands/rebuild.js
@@ -68,13 +68,12 @@ class Rebuild extends ArboristWorkspaceCmd {
await arb.rebuild()
}
- // Phase 1 advisory: list any packages whose install scripts ran (or
- // would have run) and are not yet covered by allowScripts. Rebuild
- // doesn't go through reifyFinish, so the walker is invoked here.
+ // Rebuild skips reifyFinish, so run the walker here to list any
+ // packages whose install scripts were blocked.
const unreviewed = await checkAllowScripts({ arb, npm: this.npm })
if (unreviewed.length > 0) {
const count = unreviewed.length
- const noun = count === 1 ? 'package has' : 'packages have'
+ const noun = count === 1 ? 'package had' : 'packages had'
// `npm install-scripts` writes to a project package.json, which doesn't
// exist for global rebuilds. Point global users at `npm config set`,
// which writes the `allow-scripts` setting to their user .npmrc.
@@ -84,7 +83,7 @@ class Rebuild extends ArboristWorkspaceCmd {
: 'Run `npm install-scripts ls` to review.'
log.warn(
'rebuild',
- `${count} ${noun} install scripts not yet covered by allowScripts. ` +
+ `${count} ${noun} install scripts blocked because they are not covered by allowScripts. ` +
remediation
)
}
diff --git a/deps/npm/lib/commands/run.js b/deps/npm/lib/commands/run.js
index 4547679754e..ada203f2793 100644
--- a/deps/npm/lib/commands/run.js
+++ b/deps/npm/lib/commands/run.js
@@ -101,8 +101,7 @@ class RunScript extends BaseCommand {
pkg.scripts = scripts
if (
- !Object.prototype.hasOwnProperty.call(scripts, event) &&
- !(event === 'start' && (await runScript.isServerPackage(path)))
+ !Object.prototype.hasOwnProperty.call(scripts, event)
) {
if (this.npm.config.get('if-present')) {
return
diff --git a/deps/npm/lib/commands/sbom.js b/deps/npm/lib/commands/sbom.js
index fb3d81bb2d3..38fb383834e 100644
--- a/deps/npm/lib/commands/sbom.js
+++ b/deps/npm/lib/commands/sbom.js
@@ -39,7 +39,7 @@ class SBOM extends BaseCommand {
const arb = new Arborist(opts)
const tree = packageLockOnly ? await arb.loadVirtual(opts).catch(() => {
- throw this.usageError('A package lock or shrinkwrap file is required in package-lock-only mode')
+ throw this.usageError('A package-lock.json file is required in package-lock-only mode')
}) : await arb.loadActual(opts)
// Collect the list of selected workspaces in the project
diff --git a/deps/npm/lib/commands/shrinkwrap.js b/deps/npm/lib/commands/shrinkwrap.js
deleted file mode 100644
index e8d3a256f19..00000000000
--- a/deps/npm/lib/commands/shrinkwrap.js
+++ /dev/null
@@ -1,70 +0,0 @@
-const { resolve, basename } = require('node:path')
-const { unlink } = require('node:fs/promises')
-const { log } = require('proc-log')
-const BaseCommand = require('../base-cmd.js')
-
-class Shrinkwrap extends BaseCommand {
- static description = 'Lock down dependency versions for publication'
- static name = 'shrinkwrap'
- static ignoreImplicitWorkspace = false
-
- async exec () {
- // if has a npm-shrinkwrap.json, nothing to do
- // if has a package-lock.json, rename to npm-shrinkwrap.json
- // if has neither, load the actual tree and save that as npm-shrinkwrap.json
- //
- // loadVirtual, fall back to loadActual
- // rename shrinkwrap file type, and tree.meta.save()
- if (this.npm.global) {
- const er = new Error('`npm shrinkwrap` does not work for global packages')
- er.code = 'ESHRINKWRAPGLOBAL'
- throw er
- }
-
- const Arborist = require('@npmcli/arborist')
- const path = this.npm.prefix
- const sw = resolve(path, 'npm-shrinkwrap.json')
- const arb = new Arborist({ ...this.npm.flatOptions, path })
- const tree = await arb.loadVirtual().catch(() => arb.loadActual())
- const { meta } = tree
- const newFile = meta.hiddenLockfile || !meta.loadedFromDisk
- const oldFilename = meta.filename
- const notSW = !newFile && basename(oldFilename) !== 'npm-shrinkwrap.json'
-
- // The computed lockfile version of a hidden lockfile is always 3 even if the actual value of the property is a different.
- // When shrinkwrap is run with only a hidden lockfile we want to set the shrinkwrap lockfile version as whatever was explicitly requested with a fallback to the actual value from the hidden
- // lockfile.
- if (meta.hiddenLockfile) {
- meta.lockfileVersion = arb.options.lockfileVersion ||
- meta.originalLockfileVersion
- }
- meta.hiddenLockfile = false
- meta.filename = sw
- await meta.save()
-
- const updatedVersion = meta.originalLockfileVersion !== meta.lockfileVersion
- ? meta.lockfileVersion
- : null
-
- if (newFile) {
- let message = 'created a lockfile as npm-shrinkwrap.json'
- if (updatedVersion) {
- message += ` with version ${updatedVersion}`
- }
- log.notice('', message)
- } else if (notSW) {
- await unlink(oldFilename)
- let message = 'package-lock.json has been renamed to npm-shrinkwrap.json'
- if (updatedVersion) {
- message += ` and updated to version ${updatedVersion}`
- }
- log.notice('', message)
- } else if (updatedVersion) {
- log.notice('', `npm-shrinkwrap.json updated to version ${updatedVersion}`)
- } else {
- log.notice('', 'npm-shrinkwrap.json up to date')
- }
- }
-}
-
-module.exports = Shrinkwrap
diff --git a/deps/npm/lib/commands/star.js b/deps/npm/lib/commands/star.js
deleted file mode 100644
index 7d1be1d3897..00000000000
--- a/deps/npm/lib/commands/star.js
+++ /dev/null
@@ -1,72 +0,0 @@
-const npmFetch = require('npm-registry-fetch')
-const npa = require('npm-package-arg')
-const { log, output } = require('proc-log')
-const getIdentity = require('../utils/get-identity')
-const BaseCommand = require('../base-cmd.js')
-
-class Star extends BaseCommand {
- static description = 'Mark your favorite packages'
- static name = 'star'
- static usage = ['[<package-spec>...]']
- static params = [
- 'registry',
- 'unicode',
- 'otp',
- ]
-
- static ignoreImplicitWorkspace = false
-
- async exec (args) {
- if (!args.length) {
- throw this.usageError()
- }
-
- // if we're unstarring, then show an empty star image
- // otherwise, show the full star image
- const unicode = this.npm.config.get('unicode')
- const full = unicode ? '\u2605 ' : '(*)'
- const empty = unicode ? '\u2606 ' : '( )'
- const show = this.name === 'star' ? full : empty
-
- const pkgs = args.map(npa)
- const username = await getIdentity(this.npm, this.npm.flatOptions)
-
- for (const pkg of pkgs) {
- const fullData = await npmFetch.json(pkg.escapedName, {
- ...this.npm.flatOptions,
- spec: pkg,
- query: { write: true },
- preferOnline: true,
- })
-
- const body = {
- _id: fullData._id,
- _rev: fullData._rev,
- users: fullData.users || {},
- }
-
- if (this.name === 'star') {
- log.info('star', 'starring', body._id)
- body.users[username] = true
- log.verbose('star', 'starring', body)
- } else {
- delete body.users[username]
- log.info('unstar', 'unstarring', body._id)
- log.verbose('unstar', 'unstarring', body)
- }
-
- const data = await npmFetch.json(pkg.escapedName, {
- ...this.npm.flatOptions,
- spec: pkg,
- method: 'PUT',
- body,
- })
-
- output.standard(show + ' ' + pkg.name)
- log.verbose('star', data)
- return data
- }
- }
-}
-
-module.exports = Star
diff --git a/deps/npm/lib/commands/stars.js b/deps/npm/lib/commands/stars.js
deleted file mode 100644
index d059d012509..00000000000
--- a/deps/npm/lib/commands/stars.js
+++ /dev/null
@@ -1,39 +0,0 @@
-const npmFetch = require('npm-registry-fetch')
-const { log, output } = require('proc-log')
-const getIdentity = require('../utils/get-identity.js')
-const BaseCommand = require('../base-cmd.js')
-
-class Stars extends BaseCommand {
- static description = 'View packages marked as favorites'
- static name = 'stars'
- static usage = ['[<user>]']
- static params = ['registry']
- static ignoreImplicitWorkspace = false
-
- async exec ([user]) {
- try {
- if (!user) {
- user = await getIdentity(this.npm, this.npm.flatOptions)
- }
-
- const { rows } = await npmFetch.json('/-/_view/starredByUser', {
- ...this.npm.flatOptions,
- query: { key: `"${user}"` },
- })
- if (rows.length === 0) {
- log.warn('stars', 'user has not starred any packages')
- }
-
- for (const row of rows) {
- output.standard(row.value)
- }
- } catch (err) {
- if (err.code === 'ENEEDAUTH') {
- log.warn('stars', 'auth is required to look up your username')
- }
- throw err
- }
- }
-}
-
-module.exports = Stars
diff --git a/deps/npm/lib/commands/token.js b/deps/npm/lib/commands/token.js
index 8f54e9d8725..f3fce31af8d 100644
--- a/deps/npm/lib/commands/token.js
+++ b/deps/npm/lib/commands/token.js
@@ -171,6 +171,25 @@ class Token extends BaseCommand {
const validCIDR = await this.validateCIDRList(cidr)
+ // Warn when creating a token that can publish directly to the registry.
+ // Only 'read-write' package/scope permission grants direct-publish; stage-only
+ // tokens ('read-write-stage-only') stage releases instead, and non-publishing
+ // permissions (read-only/no-access) can't publish at all, so both stay silent.
+ // bypass-2fa is orthogonal — it removes the 2FA requirement but grants no
+ // publish capability on its own — so it is not part of this trigger.
+ if (packagesAndScopesPermission === 'read-write') {
+ // Deprecation notice for direct-publish tokens; see github/npm#15609.
+ log.warn(
+ 'token',
+ 'Creating a token that can publish directly to the registry. ' +
+ 'Consider `--packages-and-scopes-permission=read-write-stage-only` ' +
+ 'instead — with a stage-only token, your releases go to a staging ' +
+ 'queue for you to approve before they go public. Bypass-2FA tokens ' +
+ 'with direct-publish access will stop working in January 2027. ' +
+ 'See https://gh.io/bypass-2fa-tokens-no-longer-publish.'
+ )
+ }
+
/* istanbul ignore if - skip testing read input */
if (!password) {
password = await readUserInfo.password()
diff --git a/deps/npm/lib/commands/uninstall.js b/deps/npm/lib/commands/uninstall.js
index 60c5eb8e791..eb595c26a45 100644
--- a/deps/npm/lib/commands/uninstall.js
+++ b/deps/npm/lib/commands/uninstall.js
@@ -3,6 +3,7 @@ const pkgJson = require('@npmcli/package-json')
const reifyFinish = require('../utils/reify-finish.js')
const resolveAllowScripts = require('../utils/resolve-allow-scripts.js')
const completion = require('../utils/installed-shallow.js')
+const { patchRelaxOpts } = require('../utils/cli-only-flag.js')
const ArboristWorkspaceCmd = require('../arborist-cmd.js')
class Uninstall extends ArboristWorkspaceCmd {
@@ -47,6 +48,7 @@ class Uninstall extends ArboristWorkspaceCmd {
rm: args,
workspaces: this.workspaceNames,
allowScripts: allowScriptsPolicy,
+ ...patchRelaxOpts(this.npm.config),
}
const arb = new Arborist(opts)
await arb.reify(opts)
diff --git a/deps/npm/lib/commands/unstar.js b/deps/npm/lib/commands/unstar.js
deleted file mode 100644
index c7296686666..00000000000
--- a/deps/npm/lib/commands/unstar.js
+++ /dev/null
@@ -1,8 +0,0 @@
-const Star = require('./star.js')
-
-class Unstar extends Star {
- static description = 'Remove an item from your favorite packages'
- static name = 'unstar'
-}
-
-module.exports = Unstar
diff --git a/deps/npm/lib/commands/update.js b/deps/npm/lib/commands/update.js
index 38f87c4a3e2..64c2c5128bb 100644
--- a/deps/npm/lib/commands/update.js
+++ b/deps/npm/lib/commands/update.js
@@ -3,6 +3,7 @@ const { log } = require('proc-log')
const reifyFinish = require('../utils/reify-finish.js')
const resolveAllowScripts = require('../utils/resolve-allow-scripts.js')
const strictAllowScriptsPreflight = require('../utils/strict-allow-scripts-preflight.js')
+const { patchRelaxOpts } = require('../utils/cli-only-flag.js')
const ArboristWorkspaceCmd = require('../arborist-cmd.js')
class Update extends ArboristWorkspaceCmd {
@@ -64,6 +65,7 @@ class Update extends ArboristWorkspaceCmd {
save,
workspaces: this.workspaceNames,
allowScripts: allowScriptsPolicy,
+ ...patchRelaxOpts(this.npm.config),
}
const arb = new Arborist(opts)
diff --git a/deps/npm/lib/commands/version.js b/deps/npm/lib/commands/version.js
index fe70322fd7c..67b17cfbf39 100644
--- a/deps/npm/lib/commands/version.js
+++ b/deps/npm/lib/commands/version.js
@@ -23,6 +23,7 @@ class Version extends BaseCommand {
static workspaces = true
static ignoreImplicitWorkspace = false
+ static skipConfigValidation = true
static usage = ['[<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease | from-git]']
diff --git a/deps/npm/lib/commands/view.js b/deps/npm/lib/commands/view.js
index 28393c823d6..747f1d4ffaf 100644
--- a/deps/npm/lib/commands/view.js
+++ b/deps/npm/lib/commands/view.js
@@ -204,6 +204,7 @@ class View extends BaseCommand {
const includeVersions = versions.length > 1
let includeFields
+ // TODO if we ask for two fields but only one existed we treat it as if we only asked for one field, this needs to be fixed
const res = versions.flatMap((v) => {
const fields = Object.entries(data[v])
@@ -239,16 +240,13 @@ class View extends BaseCommand {
})
if (json) {
- // TODO(BREAKING_CHANGE): all unwrapping should be removed.
- // Users should know based on their arguments if they can expect an array or an object.
- // And this unwrapping can break that assumption.
- // e.g. `npm view abbrev@^2` should always return an array, but currently since there is only one version matching `^2` this will return a single object instead.
const first = Object.keys(res[0] || {})
const jsonRes = first.length === 1 ? res.map(m => m[first[0]]) : res
if (jsonRes.length === 0) {
return
}
- if (jsonRes.length === 1) {
+ // Avoid wrapping a single array-valued result in another array.
+ if (jsonRes.length === 1 && Array.isArray(jsonRes[0])) {
return jsonRes[0]
}
return jsonRes
diff --git a/deps/npm/lib/npm.js b/deps/npm/lib/npm.js
index 340d872a176..5c42dbe57f1 100644
--- a/deps/npm/lib/npm.js
+++ b/deps/npm/lib/npm.js
@@ -1,6 +1,5 @@
const { resolve, dirname, join } = require('node:path')
const Config = require('@npmcli/config')
-const which = require('which')
const fs = require('node:fs/promises')
const { definitions, flatten, nerfDarts, shorthands } = require('@npmcli/config/lib/definitions')
const usage = require('./utils/npm-usage.js')
@@ -82,16 +81,6 @@ class Npm {
}
async #load () {
- await time.start('npm:load:whichnode', async () => {
- // TODO should we throw here?
- const node = await which(process.argv[0]).catch(() => {})
- if (node && node.toUpperCase() !== process.execPath.toUpperCase()) {
- log.verbose('node symlink', node)
- process.execPath = node
- this.config.execPath = node
- }
- })
-
await time.start('npm:load:configload', () => this.config.load())
// npm --versions
@@ -111,7 +100,6 @@ class Npm {
const command = deref(commandArg)
await this.#display.load({
- command,
loglevel: this.config.get('loglevel'),
stdoutColor: this.color,
stderrColor: this.logColor,
@@ -130,6 +118,19 @@ class Npm {
return { exec: false }
}
+ // extension-file selects root-owned install-time code, so it is only honored from project config or the command line.
+ // This is checked after #display.load() so the error is surfaced to the user instead of being swallowed during early config loading.
+ const extensionFile = this.config.get('extension-file')
+ if (extensionFile != null) {
+ const where = this.config.find('extension-file')
+ if (!['cli', 'project', 'default'].includes(where)) {
+ throw Object.assign(
+ new Error(`\`extension-file\` may only be set in project config or on the command line, not from ${where} config`),
+ { code: 'ENPMEXTENSIONCONFIG' }
+ )
+ }
+ }
+
// mkdir this separately since the logs dir can be set to a different location.
// if this fails, then we don't have a cache dir, but we don't want to fail immediately since the command might not need a cache dir (like `npm --version`)
await time.start('npm:load:mkdirpcache', () =>
@@ -303,8 +304,10 @@ class Npm {
? commandInstance.execWorkspaces(positionalArgs, flags)
: commandInstance.exec(positionalArgs, flags))
} else {
- // Legacy commands without definitions
- this.config.logWarnings()
+ // Legacy commands without definitions: still validate unknown CLI configs/flags and (when finite) extra positionals.
+ if (typeof commandInstance.validateCli === 'function') {
+ commandInstance.validateCli([], args)
+ }
return time.start(`command:${commandName}`, () =>
execWorkspaces ? commandInstance.execWorkspaces(args) : commandInstance.exec(args))
}
diff --git a/deps/npm/lib/trust-cmd.js b/deps/npm/lib/trust-cmd.js
index 7fabe3e421a..4371cc4488a 100644
--- a/deps/npm/lib/trust-cmd.js
+++ b/deps/npm/lib/trust-cmd.js
@@ -47,7 +47,7 @@ class TrustCommand extends BaseCommand {
// dialogue is non-log text that is different from our usual npm prefix logging
// it should always show to the user unless --json is specified
- // it's not controled by log levels
+ // it's not controlled by log levels
dialogue (strings, ...values) {
const json = this.config.get('json')
if (!json) {
diff --git a/deps/npm/lib/utils/allow-scripts-cmd.js b/deps/npm/lib/utils/allow-scripts-cmd.js
index 315b7b0b4fb..f07dc8d1dc5 100644
--- a/deps/npm/lib/utils/allow-scripts-cmd.js
+++ b/deps/npm/lib/utils/allow-scripts-cmd.js
@@ -142,7 +142,7 @@ class AllowScriptsCmd extends BaseCommand {
const has = count === 1 ? 'has' : 'have'
const pkg = count === 1 ? 'package' : 'packages'
output.standard(
- `${count} ${pkg} ${has} install scripts not yet covered by allowScripts:`
+ `${count} ${pkg} ${has} install scripts blocked because they are not covered by allowScripts:`
)
for (const { node, scripts } of unreviewed) {
const { name, version } = trustedDisplay(node)
diff --git a/deps/npm/lib/utils/allow-scripts-writer.js b/deps/npm/lib/utils/allow-scripts-writer.js
index 6964279f2f2..26d13b164e3 100644
--- a/deps/npm/lib/utils/allow-scripts-writer.js
+++ b/deps/npm/lib/utils/allow-scripts-writer.js
@@ -2,6 +2,7 @@ const npa = require('npm-package-arg')
const { log } = require('proc-log')
const {
getTrustedRegistryIdentity,
+ matchFileOrDir,
resolvedSourceSpecs,
} = require('@npmcli/arborist/lib/script-allowed.js')
@@ -150,7 +151,7 @@ const isNameOnlyKey = (key) => {
const keyTargetsNode = (key, node) => {
let parsed
try {
- parsed = npa(key)
+ parsed = npa(key, node?.root?.path)
} catch {
return false
}
@@ -179,6 +180,7 @@ const keyTargetsNode = (key, node) => {
}
case 'file':
case 'directory':
+ return matchFileOrDir(node, parsed)
case 'remote':
return resolvedSourceSpecs(node)
.some(resolved => resolved === parsed.saveSpec || resolved === parsed.fetchSpec)
diff --git a/deps/npm/lib/utils/auth.js b/deps/npm/lib/utils/auth.js
index f93e6a3b9c3..55e40d5c3c2 100644
--- a/deps/npm/lib/utils/auth.js
+++ b/deps/npm/lib/utils/auth.js
@@ -1,4 +1,4 @@
-const { webAuthOpener, adduserWeb, loginWeb, loginCouch, adduserCouch } = require('npm-profile')
+const { webAuthOpener, loginWeb, loginCouch } = require('npm-profile')
const { log } = require('proc-log')
const { createOpener } = require('../utils/open-url.js')
const read = require('../utils/read-user-info.js')
@@ -32,42 +32,6 @@ const otplease = async (npm, opts, fn) => {
}
}
-const adduser = async (npm, { creds, ...opts }) => {
- const authType = npm.config.get('auth-type')
- let res
- if (authType === 'web') {
- try {
- res = await adduserWeb(createOpener(npm, 'Create your account at'), opts)
- } catch (err) {
- if (err.code === 'ENYI') {
- log.verbose('web add user not supported, trying couch')
- } else {
- throw err
- }
- }
- }
-
- // auth type !== web or ENYI error w/ web adduser
- if (!res) {
- const username = await read.username('Username:', creds.username)
- const password = await read.password('Password:', creds.password)
- const email = await read.email('Email (this will be public):', creds.email)
- // npm registry quirk:
- // If you "add" an existing user with their current password, it's effectively a login, and if that account has otp you'll be prompted for it.
- res = await otplease(npm, opts, (reqOpts) => adduserCouch(username, email, password, reqOpts))
- }
-
- // We don't know the username if it was a web login, all we can reliably log is scope and registry
- const message = `Logged in${opts.scope ? ` to scope ${opts.scope}` : ''} on ${opts.registry}.`
-
- log.info('adduser', message)
-
- return {
- message,
- newCreds: { token: res.token },
- }
-}
-
const login = async (npm, { creds, ...opts }) => {
const authType = npm.config.get('auth-type')
let res
@@ -102,7 +66,6 @@ const login = async (npm, { creds, ...opts }) => {
}
module.exports = {
- adduser,
login,
otplease,
}
diff --git a/deps/npm/lib/utils/cli-only-flag.js b/deps/npm/lib/utils/cli-only-flag.js
new file mode 100644
index 00000000000..760c1eabaa9
--- /dev/null
+++ b/deps/npm/lib/utils/cli-only-flag.js
@@ -0,0 +1,13 @@
+// Read a config value only when it was passed on the command line.
+// Values from .npmrc, env, or defaults resolve to undefined, so the flag cannot be set as project policy.
+const cliOnlyFlag = (config, key) =>
+ config.find(key) === 'cli' ? config.get(key) : undefined
+
+// The patch relax flags, honored only from the command line, as Arborist options.
+const patchRelaxOpts = config => ({
+ allowUnusedPatches: cliOnlyFlag(config, 'allow-unused-patches'),
+ ignorePatchFailures: cliOnlyFlag(config, 'ignore-patch-failures'),
+})
+
+module.exports = cliOnlyFlag
+module.exports.patchRelaxOpts = patchRelaxOpts
diff --git a/deps/npm/lib/utils/cmd-list.js b/deps/npm/lib/utils/cmd-list.js
index 8816d829471..1654075197f 100644
--- a/deps/npm/lib/utils/cmd-list.js
+++ b/deps/npm/lib/utils/cmd-list.js
@@ -4,7 +4,6 @@ const abbrev = require('abbrev')
// Please keep this list sorted alphabetically
const commands = [
'access',
- 'adduser',
'approve-scripts',
'audit',
'bugs',
@@ -42,6 +41,7 @@ const commands = [
'outdated',
'owner',
'pack',
+ 'patch',
'ping',
'pkg',
'prefix',
@@ -57,10 +57,7 @@ const commands = [
'sbom',
'search',
'set',
- 'shrinkwrap',
'stage',
- 'star',
- 'stars',
'start',
'stop',
'team',
@@ -70,7 +67,6 @@ const commands = [
'undeprecate',
'uninstall',
'unpublish',
- 'unstar',
'update',
'version',
'view',
@@ -142,7 +138,7 @@ const aliases = {
sit: 'install-ci-test',
urn: 'run',
ogr: 'org',
- 'add-user': 'adduser',
+
}
const deref = (c) => {
diff --git a/deps/npm/lib/utils/display.js b/deps/npm/lib/utils/display.js
index 72e76bd3673..4030c8e32b9 100644
--- a/deps/npm/lib/utils/display.js
+++ b/deps/npm/lib/utils/display.js
@@ -91,6 +91,8 @@ const getArrayOrObject = (items) => {
return foundNonObject
}
// We use objects with 0,1,2,etc keys to merge array
+ // We don't currently use this but want to allow for it again
+ // istanbul ignore next
if (items.every((o, i) => Object.hasOwn(o, i))) {
return Object.assign([], ...items)
}
@@ -169,7 +171,6 @@ class Display {
#progress
// options
- #command
#levelIndex
#timing
#json
@@ -212,7 +213,6 @@ class Display {
}
async load ({
- command,
heading,
json,
loglevel,
@@ -235,7 +235,6 @@ class Display {
this.#stderrChalk = stderrColor ? new Chalk({ level }) : this.#noColorChalk
this.#logColors = COLOR_PALETTE({ chalk: this.#stderrChalk })
- this.#command = command
this.#levelIndex = LEVEL_OPTIONS[loglevel].index
this.#timing = timing
this.#json = json
@@ -313,17 +312,6 @@ class Display {
if (this.#outputState.buffering) {
this.#outputState.buffer.push([level, meta, ...args])
} else {
- // XXX: Check if the argument looks like a run-script banner. This should be replaced with proc-log.META in @npmcli/run-script
- if (typeof args[0] === 'string' && args[0].startsWith('\n> ') && args[0].endsWith('\n')) {
- if (this.#silent || ['exec', 'explore'].includes(this.#command)) {
- // Silent mode and some specific commands always hide run script banners
- break
- } else if (this.#json) {
- // In json mode, change output to stderr since we don't want to break json parsing on stdout if the user is piping to jq or something.
- // XXX: in a future (breaking?) change it might make sense for run-script to always output these banners with proc-log.output.error if we think they align closer with "logging" instead of "output".
- level = output.KEYS.error
- }
- }
this.#writeOutput(level, meta, ...args)
}
break
diff --git a/deps/npm/lib/utils/error-message.js b/deps/npm/lib/utils/error-message.js
index ab01ca621d1..41e35bd78ac 100644
--- a/deps/npm/lib/utils/error-message.js
+++ b/deps/npm/lib/utils/error-message.js
@@ -80,6 +80,7 @@ const errorMessage = (er, npm) => {
}
case 'EALLOWGIT':
+ case 'EALLOWREMOTE':
summary.push(['', er.message])
detail.push(['', `Refusing to fetch "${er.package}"`])
break
@@ -267,7 +268,7 @@ const errorMessage = (er, npm) => {
case 'ENEEDAUTH':
summary.push(['need auth', er.message])
- detail.push(['need auth', 'You need to authorize this machine using `npm adduser`'])
+ detail.push(['need auth', 'You need to authorize this machine using `npm login`'])
break
case 'ECONNRESET':
diff --git a/deps/npm/lib/utils/explain-dep.js b/deps/npm/lib/utils/explain-dep.js
index 6c84aa4ebbc..06722c627ec 100644
--- a/deps/npm/lib/utils/explain-dep.js
+++ b/deps/npm/lib/utils/explain-dep.js
@@ -76,7 +76,7 @@ const explainDependents = ({ dependents }, depth, chalk, seen) => {
}
const explainEdge = (
- { name, type, bundled, from, spec, rawSpec, overridden },
+ { name, type, bundled, from, spec, rawSpec, overridden, packageExtensions, npmExtension },
depth, chalk, seen = new Set()
) => {
let dep = type === 'workspace'
@@ -88,9 +88,19 @@ const explainEdge = (
const fromMsg = ` from ${explainFrom(from, depth, chalk, seen)}`
+ // note an edge created by a root packageExtensions repair
+ const extMsg = packageExtensions
+ ? chalk.dim(` (added by packageExtensions["${packageExtensions.selector}"].${packageExtensions.field}.${name})`)
+ : ''
+
+ // note an edge created or changed by a root .npm-extension repair
+ const npmExtMsg = npmExtension
+ ? chalk.dim(` (changed by .npm-extension ${npmExtension.extensionPoint} ${npmExtension.field}.${name})`)
+ : ''
+
return (type === 'prod' ? '' : `${colorType(type, chalk)} `) +
(bundled ? `${colorType('bundled', chalk)} ` : '') +
- `${dep}${fromMsg}`
+ `${dep}${fromMsg}${extMsg}${npmExtMsg}`
}
const explainFrom = (from, depth, chalk, seen) => {
diff --git a/deps/npm/lib/utils/key-values.js b/deps/npm/lib/utils/key-values.js
index cf54304da6b..ec9f4098931 100644
--- a/deps/npm/lib/utils/key-values.js
+++ b/deps/npm/lib/utils/key-values.js
@@ -26,11 +26,23 @@ function logObject (values, { chalk, json, predicate = defaultPredicate }) {
}
function logStageItem (item, { chalk }) {
- const { id, packageName, version, tag, createdAt, actor, actorType, shasum, ...rest } = item
+ const {
+ id,
+ packageName,
+ version,
+ tag,
+ createdAt,
+ actor,
+ actorType,
+ shasum,
+ status,
+ ...rest
+ } = item
logObject({
id,
'package name': packageName,
version,
+ status,
tag,
'date staged': createdAt,
'staged by': actorType ? `${actor} (${actorType})` : actor,
diff --git a/deps/npm/lib/utils/oidc.js b/deps/npm/lib/utils/oidc.js
index 00f32c64262..203aaf3143a 100644
--- a/deps/npm/lib/utils/oidc.js
+++ b/deps/npm/lib/utils/oidc.js
@@ -143,8 +143,9 @@ async function oidc ({ packageName, registry, opts, config }) {
try {
const isDefaultProvenance = config.isDefault('provenance')
- // CircleCI doesn't support provenance yet, so skip the auto-enable logic
- if (isDefaultProvenance && !ciInfo.CIRCLE) {
+ // CircleCI doesn't support provenance yet, so skip the auto-enable logic.
+ // An explicitly provided provenance file always takes precedence over auto-generated provenance
+ if (isDefaultProvenance && !ciInfo.CIRCLE && !opts.provenanceFile) {
const [headerB64, payloadB64] = idToken.split('.')
if (headerB64 && payloadB64) {
const payloadJson = Buffer.from(payloadB64, 'base64').toString('utf8')
@@ -158,7 +159,6 @@ async function oidc ({ packageName, registry, opts, config }) {
if (visibility?.public) {
log.verbose('oidc', `Enabling provenance`)
opts.provenance = true
- config.set('provenance', true, 'user')
}
}
}
diff --git a/deps/npm/lib/utils/patch-diff.js b/deps/npm/lib/utils/patch-diff.js
new file mode 100644
index 00000000000..b0ab9a3aa0b
--- /dev/null
+++ b/deps/npm/lib/utils/patch-diff.js
@@ -0,0 +1,88 @@
+// Generate a git-compatible unified diff between two directories.
+// Used by `npm patch commit` to capture edits against a clean tarball.
+// The output is consumed by Arborist's apply step (jsdiff parsePatch).
+const { createTwoFilesPatch } = require('diff')
+const { readdir, readFile } = require('node:fs/promises')
+const { join, sep } = require('node:path')
+
+const IGNORE = new Set(['node_modules', '.git'])
+
+// Recursively list file paths under dir, relative and posix-separated.
+const listFiles = async dir => {
+ const out = []
+ const walk = async sub => {
+ const entries = await readdir(join(dir, sub), { withFileTypes: true })
+ for (const entry of entries) {
+ const rel = sub ? `${sub}/${entry.name}` : entry.name
+ if (entry.isDirectory()) {
+ if (!IGNORE.has(entry.name)) {
+ await walk(rel)
+ }
+ } else if (entry.isFile()) {
+ out.push(rel)
+ }
+ }
+ }
+ await walk('')
+ return out
+}
+
+const readMaybe = async file => {
+ try {
+ return await readFile(file, 'utf8')
+ } catch {
+ return null
+ }
+}
+
+// Diff originalDir against editedDir, returning { diff, packageJsonChanged }.
+// Added files use `--- /dev/null`, deleted files use `+++ /dev/null`.
+// The root package.json is excluded: Arborist resolves the pre-patch manifest, so a patched manifest would apply to disk without being honored.
+// ignore holds extra root-relative filenames the caller keeps out of the diff, e.g. the patch-update marker.
+const diffDirs = async (originalDir, editedDir, ignore = new Set()) => {
+ const [origFiles, editFiles] = await Promise.all([
+ listFiles(originalDir),
+ listFiles(editedDir),
+ ])
+ const all = [...new Set([...origFiles, ...editFiles])].sort()
+
+ let result = ''
+ let packageJsonChanged = false
+ for (const file of all) {
+ const native = file.split('/').join(sep)
+ const [a, b] = await Promise.all([
+ readMaybe(join(originalDir, native)),
+ readMaybe(join(editedDir, native)),
+ ])
+ if (a === b) {
+ continue
+ }
+
+ // the root package.json is never patchable; flag the change so commit can warn
+ if (file === 'package.json') {
+ packageJsonChanged = true
+ continue
+ }
+
+ // caller-owned control files (e.g. the patch-update marker) never belong in the diff
+ if (ignore.has(file)) {
+ continue
+ }
+
+ let patch = createTwoFilesPatch(
+ `a/${file}`, `b/${file}`, a || '', b || '', '', ''
+ ).replace('===================================================================\n', '')
+
+ // mark adds and deletes with /dev/null so the apply step creates/removes files
+ if (a === null) {
+ patch = patch.replace(`--- a/${file}\t`, '--- /dev/null\t')
+ }
+ if (b === null) {
+ patch = patch.replace(`+++ b/${file}\t`, '+++ /dev/null\t')
+ }
+ result += patch
+ }
+ return { diff: result, packageJsonChanged }
+}
+
+module.exports = { diffDirs }
diff --git a/deps/npm/lib/utils/reify-output.js b/deps/npm/lib/utils/reify-output.js
index fa229a318d2..75129abfb15 100644
--- a/deps/npm/lib/utils/reify-output.js
+++ b/deps/npm/lib/utils/reify-output.js
@@ -44,7 +44,8 @@ const reifyOutput = (npm, arb, extras = {}) => {
}
if (diff) {
- const showDiff = npm.config.get('dry-run') || npm.config.get('long')
+ const showDiff = !npm.flatOptions.json &&
+ (npm.config.get('dry-run') || npm.config.get('long'))
const chalk = npm.chalk
depth({
@@ -221,7 +222,7 @@ const packagesChangedMessage = (npm, { added, removed, changed, audited }) => {
}
const packagesFundingMessage = (npm, { funding }) => {
- if (!funding) {
+ if (!funding || npm.global) {
return
}
@@ -242,8 +243,9 @@ const unreviewedScriptsMessage = (npm, unreviewedScripts) => {
// stdout is reserved for things the user explicitly asked to see
// (npm ls, npm view).
const count = unreviewedScripts.length
- const pkg = count === 1 ? 'package has' : 'packages have'
- const header = `${count} ${pkg} install scripts not yet covered by allowScripts:`
+ const pkg = count === 1 ? 'package had' : 'packages had'
+ const header =
+ `${count} ${pkg} install scripts blocked because they are not covered by allowScripts:`
const names = []
const lines = unreviewedScripts.map(({ node, scripts }) => {
diff --git a/deps/npm/lib/utils/sbom-cyclonedx.js b/deps/npm/lib/utils/sbom-cyclonedx.js
index bd741718bef..5ff00e7eb9c 100644
--- a/deps/npm/lib/utils/sbom-cyclonedx.js
+++ b/deps/npm/lib/utils/sbom-cyclonedx.js
@@ -106,7 +106,7 @@ const toCyclonedxItem = (node, { packageType }) => {
const component = {
'bom-ref': toCyclonedxID(node),
type: packageType,
- name: node.name,
+ name: node.packageName,
version: node.version,
scope: (node.optional || node.devOptional) ? 'optional' : 'required',
author: (typeof node.package?.author === 'object')
diff --git a/deps/npm/lib/utils/tar.js b/deps/npm/lib/utils/tar.js
index 6b6870678c0..91e424ca127 100644
--- a/deps/npm/lib/utils/tar.js
+++ b/deps/npm/lib/utils/tar.js
@@ -10,7 +10,7 @@ const localeCompare = require('@isaacs/string-locale-compare')('en', {
const logTar = (tarball, { unicode = false, json, key, redact } = {}) => {
if (json) {
const meta = redact === false ? { [META]: true, redact: false } : undefined
- output.buffer(key == null ? tarball : { [key]: tarball }, meta)
+ output.buffer({ [key]: tarball }, meta)
return
}
log.notice('')
diff --git a/deps/npm/lib/utils/validate-lockfile.js b/deps/npm/lib/utils/validate-lockfile.js
index 29161ec55bb..9039a797c03 100644
--- a/deps/npm/lib/utils/validate-lockfile.js
+++ b/deps/npm/lib/utils/validate-lockfile.js
@@ -22,8 +22,109 @@ function validateLockfile (virtualTree, idealTree) {
errors.push(`Invalid: lock file's ${lock.name}@${lock.version} does ` +
`not satisfy ${entry.name}@${entry.version}`)
}
+
+ // a patch whose on-disk hash or path diverges from the lockfile is out of sync
+ if ((lock.patched?.integrity || null) !== (entry.patched?.integrity || null) ||
+ (lock.patched?.path || null) !== (entry.patched?.path || null)) {
+ if (entry.patched && !lock.patched) {
+ // package.json declares a patch the lockfile lacks: newly added, or skipped via --ignore-patch-failures
+ errors.push(`Invalid: package.json declares a patch for ${entry.name}@${entry.version} ` +
+ `that the lock file does not record (it may have been skipped with --ignore-patch-failures). ` +
+ `Fix the patch and reinstall, or remove its patchedDependencies entry`)
+ } else if (lock.patched && !entry.patched) {
+ // describe the lock file's own version, which can differ from the ideal tree's when the version also drifted
+ errors.push(`Invalid: lock file records a patch for ${lock.name}@${lock.version} ` +
+ `that package.json no longer declares`)
+ } else {
+ errors.push(`Invalid: patch for ${entry.name}@${entry.version} does not ` +
+ `match the patch recorded in the lock file`)
+ }
+ }
+ }
+ return errors
+}
+
+// validates that the root packageExtensions state matches what the lockfile recorded, and that the locked tree is still consistent with the rule set.
+// Returns an array of human-readable error strings, empty when valid.
+function validatePackageExtensions (virtualTree, idealTree) {
+ const errors = []
+ const lockHash = virtualTree.meta?.packageExtensionsHash || null
+ const idealHash = idealTree.meta?.packageExtensionsHash || null
+
+ if (idealHash !== lockHash) {
+ if (idealHash && !lockHash) {
+ errors.push('Missing: packageExtensions state from lock file')
+ } else if (!idealHash && lockHash) {
+ errors.push('Invalid: lock file records packageExtensions state but package.json has none')
+ } else {
+ errors.push('Invalid: packageExtensions in package.json do not match the lock file')
+ }
+ // once the canonical hashes diverge, the deeper per-node checks are moot
+ return errors
+ }
+
+ // the hashes match, so validate the locked tree's own consistency against the rules
+ const { PackageExtensions } = require('@npmcli/arborist')
+ const root = idealTree.target || idealTree
+ let pe
+ try {
+ pe = new PackageExtensions(root.package?.packageExtensions)
+ } catch (err) {
+ return [`Invalid: ${err.message}`]
+ }
+
+ for (const node of virtualTree.inventory.values()) {
+ if (node.isProjectRoot || node.isWorkspace) {
+ continue
+ }
+ // selectors match the underlying package identity, which is the alias target for aliased installs
+ const name = node.packageName || node.name
+ // a locked package identity must not match more than one selector
+ try {
+ pe.match(name, node.version)
+ } catch (err) {
+ errors.push(`Invalid: ${err.message}`)
+ }
+ // recorded provenance must still correspond to a selector that matches the node
+ const applied = node.packageExtensionsApplied
+ if (applied) {
+ const sel = pe.selectors.find(s => s.key === applied.selector)
+ if (!sel || !pe.wouldMatch(name, node.version)) {
+ errors.push(
+ `Invalid: stale packageExtensions provenance for ${node.name}@${node.version} (selector "${applied.selector}")`)
+ }
+ }
}
return errors
}
+// validates that the .npm-extension state recorded in the lockfile still matches the selected extension file.
+// Validation is hash-based: arbitrary code has no selector to re-check, so a matching hash is trusted and a mismatch fails.
+// fileHash is computed from the on-disk file (discovery only, no execution), so this holds even under ignore-extension/ignore-scripts.
+// The lockfile carries extension state if it records a root hash or any per-package npmExtensionApplied provenance.
+// Returns an array of human-readable error strings, empty when valid.
+function validateNpmExtension (virtualTree, fileHash) {
+ const lockHash = virtualTree?.meta?.npmExtensionHash || null
+ const hasProvenance = !!virtualTree &&
+ [...virtualTree.inventory.values()].some(node => node.npmExtensionApplied)
+ fileHash = fileHash || null
+
+ if (fileHash) {
+ if (!lockHash) {
+ return ['Missing: .npm-extension state from lock file']
+ }
+ if (lockHash !== fileHash) {
+ return ['Invalid: .npm-extension file does not match the lock file']
+ }
+ return []
+ }
+ // no extension file present
+ if (lockHash || hasProvenance) {
+ return ['Invalid: lock file records .npm-extension state but no .npm-extension file is present']
+ }
+ return []
+}
+
module.exports = validateLockfile
+module.exports.validatePackageExtensions = validatePackageExtensions
+module.exports.validateNpmExtension = validateNpmExtension
diff --git a/deps/npm/man/man1/npm-access.1 b/deps/npm/man/man1/npm-access.1
index 435819623db..ea2124af3a2 100644
--- a/deps/npm/man/man1/npm-access.1
+++ b/deps/npm/man/man1/npm-access.1
@@ -1,4 +1,4 @@
-.TH "NPM-ACCESS" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-ACCESS" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-access\fR - Set access level on published packages
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-adduser.1 b/deps/npm/man/man1/npm-adduser.1
deleted file mode 100644
index 5cc62878424..00000000000
--- a/deps/npm/man/man1/npm-adduser.1
+++ /dev/null
@@ -1,93 +0,0 @@
-.TH "NPM-ADDUSER" "1" "August 2026" "NPM@11.19.1" ""
-.SH "NAME"
-\fBnpm-adduser\fR - Add a registry user account
-.SS "Synopsis"
-.P
-.RS 2
-.nf
-npm adduser
-
-alias: add-user
-.fi
-.RE
-.P
-Note: This command is unaware of workspaces.
-.SS "Description"
-.P
-Create a new user in the specified registry, and save the credentials to the \fB.npmrc\fR file. If no registry is specified, the default registry will be used (see npm help registry).
-.P
-When you run \fBnpm adduser\fR, the CLI automatically generates a legacy token of \fBpublish\fR type. For more information, see \fBAbout legacy tokens\fR \fI\(la/about-access-tokens#about-legacy-tokens\(ra\fR.
-.P
-When using \fBlegacy\fR for your \fBauth-type\fR, the username, password, and email are read in from prompts.
-.SS "Configuration"
-.SS "\fBregistry\fR"
-.RS 0
-.IP \(bu 4
-Default: "https://registry.npmjs.org/"
-.IP \(bu 4
-Type: URL
-.RE 0
-
-.P
-The base URL of the npm registry.
-.SS "\fBscope\fR"
-.RS 0
-.IP \(bu 4
-Default: the scope of the current project, if any, or ""
-.IP \(bu 4
-Type: String
-.RE 0
-
-.P
-Associate an operation with a scope for a scoped registry.
-.P
-Useful when logging in to or out of a private registry:
-.P
-.RS 2
-.nf
-# log in, linking the scope to the custom registry
-npm login --scope=@mycorp --registry=https://registry.mycorp.com
-
-# log out, removing the link and the auth token
-npm logout --scope=@mycorp
-.fi
-.RE
-.P
-This will cause \fB@mycorp\fR to be mapped to the registry for future installation of packages specified according to the pattern \fB@mycorp/package\fR.
-.P
-This will also cause \fBnpm init\fR to create a scoped package.
-.P
-.RS 2
-.nf
-# accept all defaults, and create a package named "@foo/whatever",
-# instead of just named "whatever"
-npm init --scope=@foo --yes
-.fi
-.RE
-.SS "\fBauth-type\fR"
-.RS 0
-.IP \(bu 4
-Default: "web"
-.IP \(bu 4
-Type: "legacy" or "web"
-.RE 0
-
-.P
-What authentication strategy to use with \fBlogin\fR. Note that if an \fBotp\fR config is given, this value will always be set to \fBlegacy\fR.
-.SS "See Also"
-.RS 0
-.IP \(bu 4
-npm help registry
-.IP \(bu 4
-npm help config
-.IP \(bu 4
-npm help npmrc
-.IP \(bu 4
-npm help owner
-.IP \(bu 4
-npm help whoami
-.IP \(bu 4
-npm help token
-.IP \(bu 4
-npm help profile
-.RE 0
diff --git a/deps/npm/man/man1/npm-approve-scripts.1 b/deps/npm/man/man1/npm-approve-scripts.1
index f874e752ab9..21ab5382ca4 100644
--- a/deps/npm/man/man1/npm-approve-scripts.1
+++ b/deps/npm/man/man1/npm-approve-scripts.1
@@ -1,4 +1,4 @@
-.TH "NPM-APPROVE-SCRIPTS" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-APPROVE-SCRIPTS" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-approve-scripts\fR - Approve install scripts for specific dependencies
.SS "Synopsis"
@@ -16,7 +16,7 @@ Note: This command is unaware of workspaces.
.P
Manages the \fBallowScripts\fR field in your project's \fBpackage.json\fR, which records which of your dependencies are permitted to run install scripts (\fBpreinstall\fR, \fBinstall\fR, \fBpostinstall\fR, and \fBprepare\fR for non-registry sources). This command is the recommended way to maintain that field.
.P
-In the current release, this field is advisory: install scripts still run by default, but installs print a list of packages whose scripts have not been reviewed. A future release will block unreviewed install scripts.
+Dependency install scripts are blocked by default. Install commands silently skip lifecycle scripts for any dependency that does not have a matching entry in \fBallowScripts\fR, and end with a list of the packages whose scripts were skipped so you can review them with this command.
.P
This command only works inside a project that has a \fBpackage.json\fR. Running it with \fB--global\fR (\fB-g\fR) fails with an \fBEGLOBAL\fR error, since global installs (\fBnpm install -g\fR) and one-off executions (\fBnpm exec\fR / \fBnpx\fR) have no project \fBpackage.json\fR to write to. To allow install scripts in those contexts, use the \fB--allow-scripts\fR flag at install time (for example \fBnpm install -g --allow-scripts=canvas,sharp\fR) or persist the setting with \fBnpm config set allow-scripts=canvas,sharp --location=user\fR.
.P
diff --git a/deps/npm/man/man1/npm-audit.1 b/deps/npm/man/man1/npm-audit.1
index 8c9815292ae..d6751bf0d47 100644
--- a/deps/npm/man/man1/npm-audit.1
+++ b/deps/npm/man/man1/npm-audit.1
@@ -1,4 +1,4 @@
-.TH "NPM-AUDIT" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-AUDIT" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-audit\fR - Run a security audit
.SS "Synopsis"
@@ -19,7 +19,7 @@ Note that some vulnerabilities cannot be fixed automatically and will require ma
By default, the audit command will exit with a non-zero code if any vulnerability is found. It may be useful in CI environments to include the \fB--audit-level\fR parameter to specify the minimum vulnerability level that will cause the command to fail. This option does not filter the report output, it simply changes the command's failure threshold.
.SS "Package lock"
.P
-By default npm requires a package-lock or shrinkwrap in order to run the audit. You can bypass the package lock with \fB--no-package-lock\fR but be aware the results may be different with every run, since npm will re-build the dependency tree each time.
+By default npm requires a package-lock in order to run the audit. You can bypass the package lock with \fB--no-package-lock\fR but be aware the results may be different with every run, since npm will re-build the dependency tree each time.
.SS "Audit Signatures"
.P
To ensure the integrity of packages you download from the public npm registry, or any registry that supports signatures, you can verify the registry signatures of downloaded packages using the npm CLI.
@@ -336,7 +336,7 @@ Type: "dev", "optional", or "peer" (can be set multiple times)
.P
Dependency types to omit from the installation tree on disk.
.P
-Note that these dependencies \fIare\fR still resolved and added to the \fBpackage-lock.json\fR or \fBnpm-shrinkwrap.json\fR file. They are just not physically installed on disk.
+Note that these dependencies \fIare\fR still resolved and added to the \fBpackage-lock.json\fR file. They are just not physically installed on disk.
.P
If a package type appears in both the \fB--include\fR and \fB--omit\fR lists, then it will be included.
.P
@@ -379,6 +379,8 @@ Type: Boolean
If true, npm does not run scripts specified in package.json files.
.P
Note that commands explicitly intended to run a particular script, such as \fBnpm start\fR, \fBnpm stop\fR, \fBnpm restart\fR, \fBnpm test\fR, and \fBnpm run\fR will still run their intended script if \fBignore-scripts\fR is set, but they will \fInot\fR run any pre- or post-scripts.
+.P
+Setting \fBignore-scripts\fR also disables \fB.npm-extension\fR execution, as if \fBignore-extension\fR were set.
.SS "\fBinclude-attestations\fR"
.RS 0
.IP \(bu 4
diff --git a/deps/npm/man/man1/npm-bugs.1 b/deps/npm/man/man1/npm-bugs.1
index 0113cf310fd..28877e4200d 100644
--- a/deps/npm/man/man1/npm-bugs.1
+++ b/deps/npm/man/man1/npm-bugs.1
@@ -1,4 +1,4 @@
-.TH "NPM-BUGS" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-BUGS" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-bugs\fR - Report bugs for a package in a web browser
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-cache.1 b/deps/npm/man/man1/npm-cache.1
index 71eaeccf613..00837aa6e97 100644
--- a/deps/npm/man/man1/npm-cache.1
+++ b/deps/npm/man/man1/npm-cache.1
@@ -1,4 +1,4 @@
-.TH "NPM-CACHE" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-CACHE" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-cache\fR - Manipulates packages cache
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-ci.1 b/deps/npm/man/man1/npm-ci.1
index 2e544d6dfa8..86d0233e032 100644
--- a/deps/npm/man/man1/npm-ci.1
+++ b/deps/npm/man/man1/npm-ci.1
@@ -1,4 +1,4 @@
-.TH "NPM-CI" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-CI" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-ci\fR - Clean install a project
.SS "Synopsis"
@@ -17,7 +17,7 @@ This command is similar to npm help install, except it's meant to be used in aut
The main differences between using \fBnpm install\fR and \fBnpm ci\fR are:
.RS 0
.IP \(bu 4
-The project \fBmust\fR have an existing \fBpackage-lock.json\fR or \fBnpm-shrinkwrap.json\fR.
+The project \fBmust\fR have an existing \fBpackage-lock.json\fR.
.IP \(bu 4
If dependencies in the package lock do not match those in \fBpackage.json\fR, \fBnpm ci\fR will exit with an error, instead of updating the package lock.
.IP \(bu 4
@@ -25,7 +25,7 @@ If dependencies in the package lock do not match those in \fBpackage.json\fR, \f
.IP \(bu 4
If a \fBnode_modules\fR is already present, it will be automatically removed before \fBnpm ci\fR begins its install.
.IP \(bu 4
-It will never write to \fBpackage.json\fR or any of the package-locks: installs are essentially frozen.
+It will never write to \fBpackage.json\fR or \fBpackage-lock.json\fR: installs are essentially frozen.
.RE 0
.P
@@ -113,7 +113,7 @@ Type: "dev", "optional", or "peer" (can be set multiple times)
.P
Dependency types to omit from the installation tree on disk.
.P
-Note that these dependencies \fIare\fR still resolved and added to the \fBpackage-lock.json\fR or \fBnpm-shrinkwrap.json\fR file. They are just not physically installed on disk.
+Note that these dependencies \fIare\fR still resolved and added to the \fBpackage-lock.json\fR file. They are just not physically installed on disk.
.P
If a package type appears in both the \fB--include\fR and \fB--omit\fR lists, then it will be included.
.P
@@ -170,6 +170,8 @@ Type: Boolean
If true, npm does not run scripts specified in package.json files.
.P
Note that commands explicitly intended to run a particular script, such as \fBnpm start\fR, \fBnpm stop\fR, \fBnpm restart\fR, \fBnpm test\fR, and \fBnpm run\fR will still run their intended script if \fBignore-scripts\fR is set, but they will \fInot\fR run any pre- or post-scripts.
+.P
+Setting \fBignore-scripts\fR also disables \fB.npm-extension\fR execution, as if \fBignore-extension\fR were set.
.SS "\fBallow-directory\fR"
.RS 0
.IP \(bu 4
@@ -197,7 +199,7 @@ Limits the ability for npm to install dependencies from tarball files. That is,
.SS "\fBallow-git\fR"
.RS 0
.IP \(bu 4
-Default: "all"
+Default: "none"
.IP \(bu 4
Type: "all", "none", or "root"
.RE 0
@@ -205,11 +207,13 @@ Type: "all", "none", or "root"
.P
Limits the ability for npm to fetch dependencies from git references. That is, dependencies that point to a git repo instead of a version or semver range. Please note that this could leave your tree incomplete and some packages may not function as intended or designed. Changing this setting will not remove dependencies that are already installed.
.P
+As of npm 12 the default is \fBnone\fR. Git dependencies run \fBgit\fR against a remote repo and may install configuration the project does not control. Opt in explicitly per project (in \fB.npmrc\fR) or per command (on the CLI) when you need git deps.
+.P
\fBall\fR allows any git dependencies to be fetched and installed. \fBnone\fR prevents any git dependencies from being fetched and installed. \fBroot\fR only allows git dependencies defined in your project's package.json to be fetched and installed. Also allows git dependencies to be fetched for other commands like \fBnpm view\fR
.SS "\fBallow-remote\fR"
.RS 0
.IP \(bu 4
-Default: "all"
+Default: "none"
.IP \(bu 4
Type: "all", "none", or "root"
.RE 0
@@ -217,6 +221,8 @@ Type: "all", "none", or "root"
.P
Limits the ability for npm to fetch dependencies from urls. That is, dependencies that point to a tarball url instead of a version or semver range. Please note that this could leave your tree incomplete and some packages may not function as intended or designed. Changing this setting will not remove dependencies that are already installed.
.P
+As of npm 12 the default is \fBnone\fR. Tarballs that share a hostname with the configured registry (the typical case for the npm registry, GitHub Packages, and most private registries) are still installed normally. If your registry serves tarballs from a different host, set \fBreplace-registry-host\fR or override this setting. Opt in explicitly per project (in \fB.npmrc\fR) or per command (on the CLI) when you intentionally install from a URL.
+.P
\fBall\fR allows any url to be installed. \fBnone\fR prevents any url from being installed. \fBroot\fR only allows urls defined in your project's package.json to be installed. Also allows url dependencies to be used for other commands like \fBnpm view\fR
.SS "\fBallow-scripts\fR"
.RS 0
@@ -232,6 +238,8 @@ Comma-separated list of packages whose install-time lifecycle scripts (\fBpreins
This setting is intended for one-off and global contexts: \fBnpm exec\fR, \fBnpx\fR, and \fBnpm install -g\fR, where no project \fBpackage.json\fR is involved. For team-wide policy in a project, use the \fBallowScripts\fR field in \fBpackage.json\fR (which also supports explicit denials), or configure it in \fB.npmrc\fR. Passing \fB--allow-scripts\fR on the command line during a project-scoped \fBnpm install\fR, \fBci\fR, \fBupdate\fR, or \fBrebuild\fR is an error.
.P
Each name is matched against a dependency's resolved identity, not against the package's self-reported name. \fB--ignore-scripts\fR and \fB--dangerously-allow-all-scripts\fR both override this setting.
+.P
+This value is not exported to the environment for child processes.
.SS "\fBstrict-allow-scripts\fR"
.RS 0
.IP \(bu 4
@@ -241,9 +249,9 @@ Type: Boolean
.RE 0
.P
-If \fBtrue\fR, turn the install-script policy from a warning into a hard error: any dependency with install scripts not covered by \fBallowScripts\fR will fail the install instead of running with a notice.
+If \fBtrue\fR, turn the install-script policy from a warning into a hard error: any dependency with install scripts that is not covered by \fBallowScripts\fR will fail the install instead of being blocked with a warning.
.P
-Dependencies explicitly denied with \fBfalse\fR in \fBallowScripts\fR are always silently skipped; this setting only affects unreviewed entries. \fB--ignore-scripts\fR and \fB--dangerously-allow-all-scripts\fR both override this setting.
+Dependencies explicitly denied with \fBfalse\fR in \fBallowScripts\fR are always silently skipped; this setting only affects unreviewed entries (packages with install scripts that are neither approved nor denied). \fB--ignore-scripts\fR and \fB--dangerously-allow-all-scripts\fR both override this setting.
.P
Optional dependencies that cannot be installed on the current platform or engine (a non-matching \fBos\fR, \fBcpu\fR, or \fBlibc\fR) are not flagged, because their install scripts never run.
.SS "\fBdangerously-allow-all-scripts\fR"
diff --git a/deps/npm/man/man1/npm-completion.1 b/deps/npm/man/man1/npm-completion.1
index d5cefe61d0c..07114f3f03f 100644
--- a/deps/npm/man/man1/npm-completion.1
+++ b/deps/npm/man/man1/npm-completion.1
@@ -1,4 +1,4 @@
-.TH "NPM-COMPLETION" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-COMPLETION" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-completion\fR - Tab Completion for npm
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-config.1 b/deps/npm/man/man1/npm-config.1
index b0ef989fe72..d49fee95a85 100644
--- a/deps/npm/man/man1/npm-config.1
+++ b/deps/npm/man/man1/npm-config.1
@@ -1,4 +1,4 @@
-.TH "NPM-CONFIG" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-CONFIG" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-config\fR - Manage the npm configuration files
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-dedupe.1 b/deps/npm/man/man1/npm-dedupe.1
index 1fa8e34027f..1e80269a54b 100644
--- a/deps/npm/man/man1/npm-dedupe.1
+++ b/deps/npm/man/man1/npm-dedupe.1
@@ -1,4 +1,4 @@
-.TH "NPM-DEDUPE" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-DEDUPE" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-dedupe\fR - Reduce duplication in the package tree
.SS "Synopsis"
@@ -136,7 +136,7 @@ Type: "dev", "optional", or "peer" (can be set multiple times)
.P
Dependency types to omit from the installation tree on disk.
.P
-Note that these dependencies \fIare\fR still resolved and added to the \fBpackage-lock.json\fR or \fBnpm-shrinkwrap.json\fR file. They are just not physically installed on disk.
+Note that these dependencies \fIare\fR still resolved and added to the \fBpackage-lock.json\fR file. They are just not physically installed on disk.
.P
If a package type appears in both the \fB--include\fR and \fB--omit\fR lists, then it will be included.
.P
@@ -167,6 +167,8 @@ Type: Boolean
If true, npm does not run scripts specified in package.json files.
.P
Note that commands explicitly intended to run a particular script, such as \fBnpm start\fR, \fBnpm stop\fR, \fBnpm restart\fR, \fBnpm test\fR, and \fBnpm run\fR will still run their intended script if \fBignore-scripts\fR is set, but they will \fInot\fR run any pre- or post-scripts.
+.P
+Setting \fBignore-scripts\fR also disables \fB.npm-extension\fR execution, as if \fBignore-extension\fR were set.
.SS "\fBallow-directory\fR"
.RS 0
.IP \(bu 4
@@ -194,7 +196,7 @@ Limits the ability for npm to install dependencies from tarball files. That is,
.SS "\fBallow-git\fR"
.RS 0
.IP \(bu 4
-Default: "all"
+Default: "none"
.IP \(bu 4
Type: "all", "none", or "root"
.RE 0
@@ -202,11 +204,13 @@ Type: "all", "none", or "root"
.P
Limits the ability for npm to fetch dependencies from git references. That is, dependencies that point to a git repo instead of a version or semver range. Please note that this could leave your tree incomplete and some packages may not function as intended or designed. Changing this setting will not remove dependencies that are already installed.
.P
+As of npm 12 the default is \fBnone\fR. Git dependencies run \fBgit\fR against a remote repo and may install configuration the project does not control. Opt in explicitly per project (in \fB.npmrc\fR) or per command (on the CLI) when you need git deps.
+.P
\fBall\fR allows any git dependencies to be fetched and installed. \fBnone\fR prevents any git dependencies from being fetched and installed. \fBroot\fR only allows git dependencies defined in your project's package.json to be fetched and installed. Also allows git dependencies to be fetched for other commands like \fBnpm view\fR
.SS "\fBallow-remote\fR"
.RS 0
.IP \(bu 4
-Default: "all"
+Default: "none"
.IP \(bu 4
Type: "all", "none", or "root"
.RE 0
@@ -214,6 +218,8 @@ Type: "all", "none", or "root"
.P
Limits the ability for npm to fetch dependencies from urls. That is, dependencies that point to a tarball url instead of a version or semver range. Please note that this could leave your tree incomplete and some packages may not function as intended or designed. Changing this setting will not remove dependencies that are already installed.
.P
+As of npm 12 the default is \fBnone\fR. Tarballs that share a hostname with the configured registry (the typical case for the npm registry, GitHub Packages, and most private registries) are still installed normally. If your registry serves tarballs from a different host, set \fBreplace-registry-host\fR or override this setting. Opt in explicitly per project (in \fB.npmrc\fR) or per command (on the CLI) when you intentionally install from a URL.
+.P
\fBall\fR allows any url to be installed. \fBnone\fR prevents any url from being installed. \fBroot\fR only allows urls defined in your project's package.json to be installed. Also allows url dependencies to be used for other commands like \fBnpm view\fR
.SS "\fBaudit\fR"
.RS 0
diff --git a/deps/npm/man/man1/npm-deny-scripts.1 b/deps/npm/man/man1/npm-deny-scripts.1
index 70fb96d6fcd..b893be41f70 100644
--- a/deps/npm/man/man1/npm-deny-scripts.1
+++ b/deps/npm/man/man1/npm-deny-scripts.1
@@ -1,4 +1,4 @@
-.TH "NPM-DENY-SCRIPTS" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-DENY-SCRIPTS" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-deny-scripts\fR - Deny install scripts for specific dependencies
.SS "Synopsis"
@@ -15,7 +15,7 @@ Note: This command is unaware of workspaces.
.P
The companion command to npm help approve-scripts. Writes \fBfalse\fR entries into the \fBallowScripts\fR field of your project's \fBpackage.json\fR, recording that a dependency must not run install scripts even if a future version would otherwise be eligible.
.P
-In the current release, install scripts still run by default, so \fBdeny-scripts\fR only affects how installs of denied packages are reported. A future release will block unreviewed install scripts and respect deny entries at install time.
+Dependency install scripts are blocked by default. Adding a \fBfalse\fR entry with \fBdeny-scripts\fR makes the denial explicit (so it survives \fBnpm approve-scripts --all\fR) and excludes the package from any future \fB--allow-scripts-pending\fR review prompts.
.P
.RS 2
.nf
diff --git a/deps/npm/man/man1/npm-deprecate.1 b/deps/npm/man/man1/npm-deprecate.1
index e07bd5829ef..bfcf2fdd2a3 100644
--- a/deps/npm/man/man1/npm-deprecate.1
+++ b/deps/npm/man/man1/npm-deprecate.1
@@ -1,4 +1,4 @@
-.TH "NPM-DEPRECATE" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-DEPRECATE" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-deprecate\fR - Deprecate a version of a package
.SS "Synopsis"
@@ -32,7 +32,7 @@ npm deprecate my-thing@1.x "1.x is no longer supported"
.P
In this case, a version \fBmy-thing@1.0.0-beta.0\fR will also be deprecated.
.P
-You must be the package owner to deprecate something. See the \fBowner\fR and \fBadduser\fR help topics.
+You must be the package owner to deprecate something. See the \fBowner\fR and \fBlogin\fR help topics.
.P
To un-deprecate a package, specify an empty string (\fB""\fR) for the \fBmessage\fR argument. Note that you must use double quotes with no space between them to format an empty string.
.SS "Configuration"
@@ -81,5 +81,5 @@ npm help registry
.IP \(bu 4
npm help owner
.IP \(bu 4
-npm help adduser
+npm help login
.RE 0
diff --git a/deps/npm/man/man1/npm-diff.1 b/deps/npm/man/man1/npm-diff.1
index 42c3903bd46..2301d2b6334 100644
--- a/deps/npm/man/man1/npm-diff.1
+++ b/deps/npm/man/man1/npm-diff.1
@@ -1,4 +1,4 @@
-.TH "NPM-DIFF" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-DIFF" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-diff\fR - The registry diff command
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-dist-tag.1 b/deps/npm/man/man1/npm-dist-tag.1
index 8ebc625273c..81dbdf11ea2 100644
--- a/deps/npm/man/man1/npm-dist-tag.1
+++ b/deps/npm/man/man1/npm-dist-tag.1
@@ -1,4 +1,4 @@
-.TH "NPM-DIST-TAG" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-DIST-TAG" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-dist-tag\fR - Modify package distribution tags
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-docs.1 b/deps/npm/man/man1/npm-docs.1
index 26fa80d54d5..26956eddf9c 100644
--- a/deps/npm/man/man1/npm-docs.1
+++ b/deps/npm/man/man1/npm-docs.1
@@ -1,4 +1,4 @@
-.TH "NPM-DOCS" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-DOCS" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-docs\fR - Open documentation for a package in a web browser
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-doctor.1 b/deps/npm/man/man1/npm-doctor.1
index f5b750fd6a3..53b32040526 100644
--- a/deps/npm/man/man1/npm-doctor.1
+++ b/deps/npm/man/man1/npm-doctor.1
@@ -1,4 +1,4 @@
-.TH "NPM-DOCTOR" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-DOCTOR" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-doctor\fR - Check the health of your npm environment
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-edit.1 b/deps/npm/man/man1/npm-edit.1
index 5055e6feaa5..0455962bae3 100644
--- a/deps/npm/man/man1/npm-edit.1
+++ b/deps/npm/man/man1/npm-edit.1
@@ -1,4 +1,4 @@
-.TH "NPM-EDIT" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-EDIT" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-edit\fR - Edit an installed package
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-exec.1 b/deps/npm/man/man1/npm-exec.1
index 5ae0a77e288..496f9f1d132 100644
--- a/deps/npm/man/man1/npm-exec.1
+++ b/deps/npm/man/man1/npm-exec.1
@@ -1,4 +1,4 @@
-.TH "NPM-EXEC" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-EXEC" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-exec\fR - Run a command from a local or remote npm package
.SS "Synopsis"
@@ -181,6 +181,8 @@ Comma-separated list of packages whose install-time lifecycle scripts (\fBpreins
This setting is intended for one-off and global contexts: \fBnpm exec\fR, \fBnpx\fR, and \fBnpm install -g\fR, where no project \fBpackage.json\fR is involved. For team-wide policy in a project, use the \fBallowScripts\fR field in \fBpackage.json\fR (which also supports explicit denials), or configure it in \fB.npmrc\fR. Passing \fB--allow-scripts\fR on the command line during a project-scoped \fBnpm install\fR, \fBci\fR, \fBupdate\fR, or \fBrebuild\fR is an error.
.P
Each name is matched against a dependency's resolved identity, not against the package's self-reported name. \fB--ignore-scripts\fR and \fB--dangerously-allow-all-scripts\fR both override this setting.
+.P
+This value is not exported to the environment for child processes.
.SS "\fBstrict-allow-scripts\fR"
.RS 0
.IP \(bu 4
@@ -190,9 +192,9 @@ Type: Boolean
.RE 0
.P
-If \fBtrue\fR, turn the install-script policy from a warning into a hard error: any dependency with install scripts not covered by \fBallowScripts\fR will fail the install instead of running with a notice.
+If \fBtrue\fR, turn the install-script policy from a warning into a hard error: any dependency with install scripts that is not covered by \fBallowScripts\fR will fail the install instead of being blocked with a warning.
.P
-Dependencies explicitly denied with \fBfalse\fR in \fBallowScripts\fR are always silently skipped; this setting only affects unreviewed entries. \fB--ignore-scripts\fR and \fB--dangerously-allow-all-scripts\fR both override this setting.
+Dependencies explicitly denied with \fBfalse\fR in \fBallowScripts\fR are always silently skipped; this setting only affects unreviewed entries (packages with install scripts that are neither approved nor denied). \fB--ignore-scripts\fR and \fB--dangerously-allow-all-scripts\fR both override this setting.
.P
Optional dependencies that cannot be installed on the current platform or engine (a non-matching \fBos\fR, \fBcpu\fR, or \fBlibc\fR) are not flagged, because their install scripts never run.
.SS "\fBdangerously-allow-all-scripts\fR"
diff --git a/deps/npm/man/man1/npm-explain.1 b/deps/npm/man/man1/npm-explain.1
index 7869082b6c6..9d6cebd1f81 100644
--- a/deps/npm/man/man1/npm-explain.1
+++ b/deps/npm/man/man1/npm-explain.1
@@ -1,4 +1,4 @@
-.TH "NPM-EXPLAIN" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-EXPLAIN" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-explain\fR - Explain installed packages
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-explore.1 b/deps/npm/man/man1/npm-explore.1
index df1fd2dc651..c40059470a3 100644
--- a/deps/npm/man/man1/npm-explore.1
+++ b/deps/npm/man/man1/npm-explore.1
@@ -1,4 +1,4 @@
-.TH "NPM-EXPLORE" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-EXPLORE" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-explore\fR - Browse an installed package
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-find-dupes.1 b/deps/npm/man/man1/npm-find-dupes.1
index f1f3970dd1d..9d4994e168f 100644
--- a/deps/npm/man/man1/npm-find-dupes.1
+++ b/deps/npm/man/man1/npm-find-dupes.1
@@ -1,4 +1,4 @@
-.TH "NPM-FIND-DUPES" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-FIND-DUPES" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-find-dupes\fR - Find duplication in the package tree
.SS "Synopsis"
@@ -83,7 +83,7 @@ Type: "dev", "optional", or "peer" (can be set multiple times)
.P
Dependency types to omit from the installation tree on disk.
.P
-Note that these dependencies \fIare\fR still resolved and added to the \fBpackage-lock.json\fR or \fBnpm-shrinkwrap.json\fR file. They are just not physically installed on disk.
+Note that these dependencies \fIare\fR still resolved and added to the \fBpackage-lock.json\fR file. They are just not physically installed on disk.
.P
If a package type appears in both the \fB--include\fR and \fB--omit\fR lists, then it will be included.
.P
@@ -114,6 +114,8 @@ Type: Boolean
If true, npm does not run scripts specified in package.json files.
.P
Note that commands explicitly intended to run a particular script, such as \fBnpm start\fR, \fBnpm stop\fR, \fBnpm restart\fR, \fBnpm test\fR, and \fBnpm run\fR will still run their intended script if \fBignore-scripts\fR is set, but they will \fInot\fR run any pre- or post-scripts.
+.P
+Setting \fBignore-scripts\fR also disables \fB.npm-extension\fR execution, as if \fBignore-extension\fR were set.
.SS "\fBaudit\fR"
.RS 0
.IP \(bu 4
diff --git a/deps/npm/man/man1/npm-fund.1 b/deps/npm/man/man1/npm-fund.1
index 88bfe299c31..f7a1ff8b5c6 100644
--- a/deps/npm/man/man1/npm-fund.1
+++ b/deps/npm/man/man1/npm-fund.1
@@ -1,4 +1,4 @@
-.TH "NPM-FUND" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-FUND" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-fund\fR - Retrieve funding information
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-get.1 b/deps/npm/man/man1/npm-get.1
index 7982d28e324..cab4e04b2be 100644
--- a/deps/npm/man/man1/npm-get.1
+++ b/deps/npm/man/man1/npm-get.1
@@ -1,4 +1,4 @@
-.TH "NPM-GET" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-GET" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-get\fR - Get a value from the npm configuration
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-help-search.1 b/deps/npm/man/man1/npm-help-search.1
index e7c7d97ebce..e2fc3a2c0bf 100644
--- a/deps/npm/man/man1/npm-help-search.1
+++ b/deps/npm/man/man1/npm-help-search.1
@@ -1,4 +1,4 @@
-.TH "NPM-HELP-SEARCH" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-HELP-SEARCH" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-help-search\fR - Search npm help documentation
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-help.1 b/deps/npm/man/man1/npm-help.1
index 7725a82d09c..ea019db8185 100644
--- a/deps/npm/man/man1/npm-help.1
+++ b/deps/npm/man/man1/npm-help.1
@@ -1,4 +1,4 @@
-.TH "NPM-HELP" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-HELP" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-help\fR - Get help on npm
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-init.1 b/deps/npm/man/man1/npm-init.1
index bd984db7d20..6b66d92d75d 100644
--- a/deps/npm/man/man1/npm-init.1
+++ b/deps/npm/man/man1/npm-init.1
@@ -1,4 +1,4 @@
-.TH "NPM-INIT" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-INIT" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-init\fR - Create a package.json file
.SS "Synopsis"
@@ -178,13 +178,13 @@ The value \fBnpm init\fR should use by default for the package author's homepage
.SS "\fBinit-license\fR"
.RS 0
.IP \(bu 4
-Default: "ISC"
+Default: ""
.IP \(bu 4
Type: String
.RE 0
.P
-The value \fBnpm init\fR should use by default for the package license.
+The value \fBnpm init\fR should use by default for the package license. If not set, the license field will be omitted from new packages.
.SS "\fBinit-module\fR"
.RS 0
.IP \(bu 4
diff --git a/deps/npm/man/man1/npm-install-ci-test.1 b/deps/npm/man/man1/npm-install-ci-test.1
index b477b4a8b0e..fb1bdf1d589 100644
--- a/deps/npm/man/man1/npm-install-ci-test.1
+++ b/deps/npm/man/man1/npm-install-ci-test.1
@@ -1,4 +1,4 @@
-.TH "NPM-INSTALL-CI-TEST" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-INSTALL-CI-TEST" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-install-ci-test\fR - Install a project with a clean slate and run tests
.SS "Synopsis"
@@ -61,7 +61,7 @@ Type: "dev", "optional", or "peer" (can be set multiple times)
.P
Dependency types to omit from the installation tree on disk.
.P
-Note that these dependencies \fIare\fR still resolved and added to the \fBpackage-lock.json\fR or \fBnpm-shrinkwrap.json\fR file. They are just not physically installed on disk.
+Note that these dependencies \fIare\fR still resolved and added to the \fBpackage-lock.json\fR file. They are just not physically installed on disk.
.P
If a package type appears in both the \fB--include\fR and \fB--omit\fR lists, then it will be included.
.P
@@ -118,6 +118,8 @@ Type: Boolean
If true, npm does not run scripts specified in package.json files.
.P
Note that commands explicitly intended to run a particular script, such as \fBnpm start\fR, \fBnpm stop\fR, \fBnpm restart\fR, \fBnpm test\fR, and \fBnpm run\fR will still run their intended script if \fBignore-scripts\fR is set, but they will \fInot\fR run any pre- or post-scripts.
+.P
+Setting \fBignore-scripts\fR also disables \fB.npm-extension\fR execution, as if \fBignore-extension\fR were set.
.SS "\fBallow-directory\fR"
.RS 0
.IP \(bu 4
@@ -145,7 +147,7 @@ Limits the ability for npm to install dependencies from tarball files. That is,
.SS "\fBallow-git\fR"
.RS 0
.IP \(bu 4
-Default: "all"
+Default: "none"
.IP \(bu 4
Type: "all", "none", or "root"
.RE 0
@@ -153,11 +155,13 @@ Type: "all", "none", or "root"
.P
Limits the ability for npm to fetch dependencies from git references. That is, dependencies that point to a git repo instead of a version or semver range. Please note that this could leave your tree incomplete and some packages may not function as intended or designed. Changing this setting will not remove dependencies that are already installed.
.P
+As of npm 12 the default is \fBnone\fR. Git dependencies run \fBgit\fR against a remote repo and may install configuration the project does not control. Opt in explicitly per project (in \fB.npmrc\fR) or per command (on the CLI) when you need git deps.
+.P
\fBall\fR allows any git dependencies to be fetched and installed. \fBnone\fR prevents any git dependencies from being fetched and installed. \fBroot\fR only allows git dependencies defined in your project's package.json to be fetched and installed. Also allows git dependencies to be fetched for other commands like \fBnpm view\fR
.SS "\fBallow-remote\fR"
.RS 0
.IP \(bu 4
-Default: "all"
+Default: "none"
.IP \(bu 4
Type: "all", "none", or "root"
.RE 0
@@ -165,6 +169,8 @@ Type: "all", "none", or "root"
.P
Limits the ability for npm to fetch dependencies from urls. That is, dependencies that point to a tarball url instead of a version or semver range. Please note that this could leave your tree incomplete and some packages may not function as intended or designed. Changing this setting will not remove dependencies that are already installed.
.P
+As of npm 12 the default is \fBnone\fR. Tarballs that share a hostname with the configured registry (the typical case for the npm registry, GitHub Packages, and most private registries) are still installed normally. If your registry serves tarballs from a different host, set \fBreplace-registry-host\fR or override this setting. Opt in explicitly per project (in \fB.npmrc\fR) or per command (on the CLI) when you intentionally install from a URL.
+.P
\fBall\fR allows any url to be installed. \fBnone\fR prevents any url from being installed. \fBroot\fR only allows urls defined in your project's package.json to be installed. Also allows url dependencies to be used for other commands like \fBnpm view\fR
.SS "\fBallow-scripts\fR"
.RS 0
@@ -180,6 +186,8 @@ Comma-separated list of packages whose install-time lifecycle scripts (\fBpreins
This setting is intended for one-off and global contexts: \fBnpm exec\fR, \fBnpx\fR, and \fBnpm install -g\fR, where no project \fBpackage.json\fR is involved. For team-wide policy in a project, use the \fBallowScripts\fR field in \fBpackage.json\fR (which also supports explicit denials), or configure it in \fB.npmrc\fR. Passing \fB--allow-scripts\fR on the command line during a project-scoped \fBnpm install\fR, \fBci\fR, \fBupdate\fR, or \fBrebuild\fR is an error.
.P
Each name is matched against a dependency's resolved identity, not against the package's self-reported name. \fB--ignore-scripts\fR and \fB--dangerously-allow-all-scripts\fR both override this setting.
+.P
+This value is not exported to the environment for child processes.
.SS "\fBstrict-allow-scripts\fR"
.RS 0
.IP \(bu 4
@@ -189,9 +197,9 @@ Type: Boolean
.RE 0
.P
-If \fBtrue\fR, turn the install-script policy from a warning into a hard error: any dependency with install scripts not covered by \fBallowScripts\fR will fail the install instead of running with a notice.
+If \fBtrue\fR, turn the install-script policy from a warning into a hard error: any dependency with install scripts that is not covered by \fBallowScripts\fR will fail the install instead of being blocked with a warning.
.P
-Dependencies explicitly denied with \fBfalse\fR in \fBallowScripts\fR are always silently skipped; this setting only affects unreviewed entries. \fB--ignore-scripts\fR and \fB--dangerously-allow-all-scripts\fR both override this setting.
+Dependencies explicitly denied with \fBfalse\fR in \fBallowScripts\fR are always silently skipped; this setting only affects unreviewed entries (packages with install scripts that are neither approved nor denied). \fB--ignore-scripts\fR and \fB--dangerously-allow-all-scripts\fR both override this setting.
.P
Optional dependencies that cannot be installed on the current platform or engine (a non-matching \fBos\fR, \fBcpu\fR, or \fBlibc\fR) are not flagged, because their install scripts never run.
.SS "\fBdangerously-allow-all-scripts\fR"
diff --git a/deps/npm/man/man1/npm-install-scripts.1 b/deps/npm/man/man1/npm-install-scripts.1
index b634903e3ec..d210ae1562c 100644
--- a/deps/npm/man/man1/npm-install-scripts.1
+++ b/deps/npm/man/man1/npm-install-scripts.1
@@ -1,4 +1,4 @@
-.TH "NPM-INSTALL-SCRIPTS" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-INSTALL-SCRIPTS" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-install-scripts\fR - Manage install-script approvals for dependencies
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-install-test.1 b/deps/npm/man/man1/npm-install-test.1
index d6774940ea2..876911d59b7 100644
--- a/deps/npm/man/man1/npm-install-test.1
+++ b/deps/npm/man/man1/npm-install-test.1
@@ -1,4 +1,4 @@
-.TH "NPM-INSTALL-TEST" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-INSTALL-TEST" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-install-test\fR - Install package(s) and run tests
.SS "Synopsis"
@@ -104,7 +104,7 @@ Type: "dev", "optional", or "peer" (can be set multiple times)
.P
Dependency types to omit from the installation tree on disk.
.P
-Note that these dependencies \fIare\fR still resolved and added to the \fBpackage-lock.json\fR or \fBnpm-shrinkwrap.json\fR file. They are just not physically installed on disk.
+Note that these dependencies \fIare\fR still resolved and added to the \fBpackage-lock.json\fR file. They are just not physically installed on disk.
.P
If a package type appears in both the \fB--include\fR and \fB--omit\fR lists, then it will be included.
.P
@@ -195,6 +195,8 @@ Type: Boolean
If true, npm does not run scripts specified in package.json files.
.P
Note that commands explicitly intended to run a particular script, such as \fBnpm start\fR, \fBnpm stop\fR, \fBnpm restart\fR, \fBnpm test\fR, and \fBnpm run\fR will still run their intended script if \fBignore-scripts\fR is set, but they will \fInot\fR run any pre- or post-scripts.
+.P
+Setting \fBignore-scripts\fR also disables \fB.npm-extension\fR execution, as if \fBignore-extension\fR were set.
.SS "\fBallow-directory\fR"
.RS 0
.IP \(bu 4
@@ -222,7 +224,7 @@ Limits the ability for npm to install dependencies from tarball files. That is,
.SS "\fBallow-git\fR"
.RS 0
.IP \(bu 4
-Default: "all"
+Default: "none"
.IP \(bu 4
Type: "all", "none", or "root"
.RE 0
@@ -230,11 +232,13 @@ Type: "all", "none", or "root"
.P
Limits the ability for npm to fetch dependencies from git references. That is, dependencies that point to a git repo instead of a version or semver range. Please note that this could leave your tree incomplete and some packages may not function as intended or designed. Changing this setting will not remove dependencies that are already installed.
.P
+As of npm 12 the default is \fBnone\fR. Git dependencies run \fBgit\fR against a remote repo and may install configuration the project does not control. Opt in explicitly per project (in \fB.npmrc\fR) or per command (on the CLI) when you need git deps.
+.P
\fBall\fR allows any git dependencies to be fetched and installed. \fBnone\fR prevents any git dependencies from being fetched and installed. \fBroot\fR only allows git dependencies defined in your project's package.json to be fetched and installed. Also allows git dependencies to be fetched for other commands like \fBnpm view\fR
.SS "\fBallow-remote\fR"
.RS 0
.IP \(bu 4
-Default: "all"
+Default: "none"
.IP \(bu 4
Type: "all", "none", or "root"
.RE 0
@@ -242,6 +246,8 @@ Type: "all", "none", or "root"
.P
Limits the ability for npm to fetch dependencies from urls. That is, dependencies that point to a tarball url instead of a version or semver range. Please note that this could leave your tree incomplete and some packages may not function as intended or designed. Changing this setting will not remove dependencies that are already installed.
.P
+As of npm 12 the default is \fBnone\fR. Tarballs that share a hostname with the configured registry (the typical case for the npm registry, GitHub Packages, and most private registries) are still installed normally. If your registry serves tarballs from a different host, set \fBreplace-registry-host\fR or override this setting. Opt in explicitly per project (in \fB.npmrc\fR) or per command (on the CLI) when you intentionally install from a URL.
+.P
\fBall\fR allows any url to be installed. \fBnone\fR prevents any url from being installed. \fBroot\fR only allows urls defined in your project's package.json to be installed. Also allows url dependencies to be used for other commands like \fBnpm view\fR
.SS "\fBallow-scripts\fR"
.RS 0
@@ -257,6 +263,8 @@ Comma-separated list of packages whose install-time lifecycle scripts (\fBpreins
This setting is intended for one-off and global contexts: \fBnpm exec\fR, \fBnpx\fR, and \fBnpm install -g\fR, where no project \fBpackage.json\fR is involved. For team-wide policy in a project, use the \fBallowScripts\fR field in \fBpackage.json\fR (which also supports explicit denials), or configure it in \fB.npmrc\fR. Passing \fB--allow-scripts\fR on the command line during a project-scoped \fBnpm install\fR, \fBci\fR, \fBupdate\fR, or \fBrebuild\fR is an error.
.P
Each name is matched against a dependency's resolved identity, not against the package's self-reported name. \fB--ignore-scripts\fR and \fB--dangerously-allow-all-scripts\fR both override this setting.
+.P
+This value is not exported to the environment for child processes.
.SS "\fBstrict-allow-scripts\fR"
.RS 0
.IP \(bu 4
@@ -266,9 +274,9 @@ Type: Boolean
.RE 0
.P
-If \fBtrue\fR, turn the install-script policy from a warning into a hard error: any dependency with install scripts not covered by \fBallowScripts\fR will fail the install instead of running with a notice.
+If \fBtrue\fR, turn the install-script policy from a warning into a hard error: any dependency with install scripts that is not covered by \fBallowScripts\fR will fail the install instead of being blocked with a warning.
.P
-Dependencies explicitly denied with \fBfalse\fR in \fBallowScripts\fR are always silently skipped; this setting only affects unreviewed entries. \fB--ignore-scripts\fR and \fB--dangerously-allow-all-scripts\fR both override this setting.
+Dependencies explicitly denied with \fBfalse\fR in \fBallowScripts\fR are always silently skipped; this setting only affects unreviewed entries (packages with install scripts that are neither approved nor denied). \fB--ignore-scripts\fR and \fB--dangerously-allow-all-scripts\fR both override this setting.
.P
Optional dependencies that cannot be installed on the current platform or engine (a non-matching \fBos\fR, \fBcpu\fR, or \fBlibc\fR) are not flagged, because their install scripts never run.
.SS "\fBdangerously-allow-all-scripts\fR"
diff --git a/deps/npm/man/man1/npm-install.1 b/deps/npm/man/man1/npm-install.1
index c6ca10ab642..e0cc75afa65 100644
--- a/deps/npm/man/man1/npm-install.1
+++ b/deps/npm/man/man1/npm-install.1
@@ -1,4 +1,4 @@
-.TH "NPM-INSTALL" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-INSTALL" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-install\fR - Install a package
.SS "Synopsis"
@@ -12,18 +12,16 @@ aliases: add, i, in, ins, inst, insta, instal, isnt, isnta, isntal, isntall
.RE
.SS "Description"
.P
-This command installs a package and any packages that it depends on. If the package has a package-lock, or an npm shrinkwrap file, or a yarn lock file, the installation of dependencies will be driven by that, respecting the following order of precedence:
+This command installs a package and any packages that it depends on. If the package has a package-lock or a yarn lock file, the installation of dependencies will be driven by that, respecting the following order of precedence:
.RS 0
.IP \(bu 4
-\fBnpm-shrinkwrap.json\fR
-.IP \(bu 4
\fBpackage-lock.json\fR
.IP \(bu 4
\fByarn.lock\fR
.RE 0
.P
-See \fBpackage-lock.json\fR \fI\(la/configuring-npm/package-lock-json\(ra\fR and npm help shrinkwrap.
+See \fBpackage-lock.json\fR \fI\(la/configuring-npm/package-lock-json\(ra\fR.
.SS "How \fBnpm install\fR uses \fBpackage-lock.json\fR"
.P
When you run \fBnpm install\fR without arguments, npm compares \fBpackage.json\fR and \fBpackage-lock.json\fR:
@@ -169,7 +167,7 @@ When using any of the above options to save dependencies to your package.json, t
.RE 0
.P
-Further, if you have an \fBnpm-shrinkwrap.json\fR or \fBpackage-lock.json\fR then it will be updated as well.
+Further, if you have a \fBpackage-lock.json\fR then it will be updated as well.
.P
\fB<scope>\fR is optional. The package will be downloaded from the registry associated with the specified scope. If no registry is associated with the given scope the default registry is assumed. See npm help scope.
.P
@@ -494,7 +492,7 @@ Type: "dev", "optional", or "peer" (can be set multiple times)
.P
Dependency types to omit from the installation tree on disk.
.P
-Note that these dependencies \fIare\fR still resolved and added to the \fBpackage-lock.json\fR or \fBnpm-shrinkwrap.json\fR file. They are just not physically installed on disk.
+Note that these dependencies \fIare\fR still resolved and added to the \fBpackage-lock.json\fR file. They are just not physically installed on disk.
.P
If a package type appears in both the \fB--include\fR and \fB--omit\fR lists, then it will be included.
.P
@@ -585,6 +583,8 @@ Type: Boolean
If true, npm does not run scripts specified in package.json files.
.P
Note that commands explicitly intended to run a particular script, such as \fBnpm start\fR, \fBnpm stop\fR, \fBnpm restart\fR, \fBnpm test\fR, and \fBnpm run\fR will still run their intended script if \fBignore-scripts\fR is set, but they will \fInot\fR run any pre- or post-scripts.
+.P
+Setting \fBignore-scripts\fR also disables \fB.npm-extension\fR execution, as if \fBignore-extension\fR were set.
.SS "\fBallow-directory\fR"
.RS 0
.IP \(bu 4
@@ -612,7 +612,7 @@ Limits the ability for npm to install dependencies from tarball files. That is,
.SS "\fBallow-git\fR"
.RS 0
.IP \(bu 4
-Default: "all"
+Default: "none"
.IP \(bu 4
Type: "all", "none", or "root"
.RE 0
@@ -620,11 +620,13 @@ Type: "all", "none", or "root"
.P
Limits the ability for npm to fetch dependencies from git references. That is, dependencies that point to a git repo instead of a version or semver range. Please note that this could leave your tree incomplete and some packages may not function as intended or designed. Changing this setting will not remove dependencies that are already installed.
.P
+As of npm 12 the default is \fBnone\fR. Git dependencies run \fBgit\fR against a remote repo and may install configuration the project does not control. Opt in explicitly per project (in \fB.npmrc\fR) or per command (on the CLI) when you need git deps.
+.P
\fBall\fR allows any git dependencies to be fetched and installed. \fBnone\fR prevents any git dependencies from being fetched and installed. \fBroot\fR only allows git dependencies defined in your project's package.json to be fetched and installed. Also allows git dependencies to be fetched for other commands like \fBnpm view\fR
.SS "\fBallow-remote\fR"
.RS 0
.IP \(bu 4
-Default: "all"
+Default: "none"
.IP \(bu 4
Type: "all", "none", or "root"
.RE 0
@@ -632,6 +634,8 @@ Type: "all", "none", or "root"
.P
Limits the ability for npm to fetch dependencies from urls. That is, dependencies that point to a tarball url instead of a version or semver range. Please note that this could leave your tree incomplete and some packages may not function as intended or designed. Changing this setting will not remove dependencies that are already installed.
.P
+As of npm 12 the default is \fBnone\fR. Tarballs that share a hostname with the configured registry (the typical case for the npm registry, GitHub Packages, and most private registries) are still installed normally. If your registry serves tarballs from a different host, set \fBreplace-registry-host\fR or override this setting. Opt in explicitly per project (in \fB.npmrc\fR) or per command (on the CLI) when you intentionally install from a URL.
+.P
\fBall\fR allows any url to be installed. \fBnone\fR prevents any url from being installed. \fBroot\fR only allows urls defined in your project's package.json to be installed. Also allows url dependencies to be used for other commands like \fBnpm view\fR
.SS "\fBallow-scripts\fR"
.RS 0
@@ -647,6 +651,8 @@ Comma-separated list of packages whose install-time lifecycle scripts (\fBpreins
This setting is intended for one-off and global contexts: \fBnpm exec\fR, \fBnpx\fR, and \fBnpm install -g\fR, where no project \fBpackage.json\fR is involved. For team-wide policy in a project, use the \fBallowScripts\fR field in \fBpackage.json\fR (which also supports explicit denials), or configure it in \fB.npmrc\fR. Passing \fB--allow-scripts\fR on the command line during a project-scoped \fBnpm install\fR, \fBci\fR, \fBupdate\fR, or \fBrebuild\fR is an error.
.P
Each name is matched against a dependency's resolved identity, not against the package's self-reported name. \fB--ignore-scripts\fR and \fB--dangerously-allow-all-scripts\fR both override this setting.
+.P
+This value is not exported to the environment for child processes.
.SS "\fBstrict-allow-scripts\fR"
.RS 0
.IP \(bu 4
@@ -656,9 +662,9 @@ Type: Boolean
.RE 0
.P
-If \fBtrue\fR, turn the install-script policy from a warning into a hard error: any dependency with install scripts not covered by \fBallowScripts\fR will fail the install instead of running with a notice.
+If \fBtrue\fR, turn the install-script policy from a warning into a hard error: any dependency with install scripts that is not covered by \fBallowScripts\fR will fail the install instead of being blocked with a warning.
.P
-Dependencies explicitly denied with \fBfalse\fR in \fBallowScripts\fR are always silently skipped; this setting only affects unreviewed entries. \fB--ignore-scripts\fR and \fB--dangerously-allow-all-scripts\fR both override this setting.
+Dependencies explicitly denied with \fBfalse\fR in \fBallowScripts\fR are always silently skipped; this setting only affects unreviewed entries (packages with install scripts that are neither approved nor denied). \fB--ignore-scripts\fR and \fB--dangerously-allow-all-scripts\fR both override this setting.
.P
Optional dependencies that cannot be installed on the current platform or engine (a non-matching \fBos\fR, \fBcpu\fR, or \fBlibc\fR) are not flagged, because their install scripts never run.
.SS "\fBdangerously-allow-all-scripts\fR"
@@ -933,8 +939,6 @@ npm help dist-tag
.IP \(bu 4
npm help uninstall
.IP \(bu 4
-npm help shrinkwrap
-.IP \(bu 4
\fBpackage.json\fR \fI\(la/configuring-npm/package-json\(ra\fR
.IP \(bu 4
npm help workspaces
diff --git a/deps/npm/man/man1/npm-link.1 b/deps/npm/man/man1/npm-link.1
index ea482b872b8..fbfbe2c1334 100644
--- a/deps/npm/man/man1/npm-link.1
+++ b/deps/npm/man/man1/npm-link.1
@@ -1,4 +1,4 @@
-.TH "NPM-LINK" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-LINK" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-link\fR - Symlink a package folder
.SS "Synopsis"
@@ -195,7 +195,7 @@ Type: "dev", "optional", or "peer" (can be set multiple times)
.P
Dependency types to omit from the installation tree on disk.
.P
-Note that these dependencies \fIare\fR still resolved and added to the \fBpackage-lock.json\fR or \fBnpm-shrinkwrap.json\fR file. They are just not physically installed on disk.
+Note that these dependencies \fIare\fR still resolved and added to the \fBpackage-lock.json\fR file. They are just not physically installed on disk.
.P
If a package type appears in both the \fB--include\fR and \fB--omit\fR lists, then it will be included.
.P
@@ -226,6 +226,8 @@ Type: Boolean
If true, npm does not run scripts specified in package.json files.
.P
Note that commands explicitly intended to run a particular script, such as \fBnpm start\fR, \fBnpm stop\fR, \fBnpm restart\fR, \fBnpm test\fR, and \fBnpm run\fR will still run their intended script if \fBignore-scripts\fR is set, but they will \fInot\fR run any pre- or post-scripts.
+.P
+Setting \fBignore-scripts\fR also disables \fB.npm-extension\fR execution, as if \fBignore-extension\fR were set.
.SS "\fBallow-directory\fR"
.RS 0
.IP \(bu 4
@@ -253,7 +255,7 @@ Limits the ability for npm to install dependencies from tarball files. That is,
.SS "\fBallow-git\fR"
.RS 0
.IP \(bu 4
-Default: "all"
+Default: "none"
.IP \(bu 4
Type: "all", "none", or "root"
.RE 0
@@ -261,11 +263,13 @@ Type: "all", "none", or "root"
.P
Limits the ability for npm to fetch dependencies from git references. That is, dependencies that point to a git repo instead of a version or semver range. Please note that this could leave your tree incomplete and some packages may not function as intended or designed. Changing this setting will not remove dependencies that are already installed.
.P
+As of npm 12 the default is \fBnone\fR. Git dependencies run \fBgit\fR against a remote repo and may install configuration the project does not control. Opt in explicitly per project (in \fB.npmrc\fR) or per command (on the CLI) when you need git deps.
+.P
\fBall\fR allows any git dependencies to be fetched and installed. \fBnone\fR prevents any git dependencies from being fetched and installed. \fBroot\fR only allows git dependencies defined in your project's package.json to be fetched and installed. Also allows git dependencies to be fetched for other commands like \fBnpm view\fR
.SS "\fBallow-remote\fR"
.RS 0
.IP \(bu 4
-Default: "all"
+Default: "none"
.IP \(bu 4
Type: "all", "none", or "root"
.RE 0
@@ -273,6 +277,8 @@ Type: "all", "none", or "root"
.P
Limits the ability for npm to fetch dependencies from urls. That is, dependencies that point to a tarball url instead of a version or semver range. Please note that this could leave your tree incomplete and some packages may not function as intended or designed. Changing this setting will not remove dependencies that are already installed.
.P
+As of npm 12 the default is \fBnone\fR. Tarballs that share a hostname with the configured registry (the typical case for the npm registry, GitHub Packages, and most private registries) are still installed normally. If your registry serves tarballs from a different host, set \fBreplace-registry-host\fR or override this setting. Opt in explicitly per project (in \fB.npmrc\fR) or per command (on the CLI) when you intentionally install from a URL.
+.P
\fBall\fR allows any url to be installed. \fBnone\fR prevents any url from being installed. \fBroot\fR only allows urls defined in your project's package.json to be installed. Also allows url dependencies to be used for other commands like \fBnpm view\fR
.SS "\fBaudit\fR"
.RS 0
diff --git a/deps/npm/man/man1/npm-ll.1 b/deps/npm/man/man1/npm-ll.1
index 136777491e0..ae5351c9197 100644
--- a/deps/npm/man/man1/npm-ll.1
+++ b/deps/npm/man/man1/npm-ll.1
@@ -1,4 +1,4 @@
-.TH "NPM-LL" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-LL" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-ll\fR - List installed packages
.SS "Synopsis"
@@ -103,7 +103,7 @@ Type: "dev", "optional", or "peer" (can be set multiple times)
.P
Dependency types to omit from the installation tree on disk.
.P
-Note that these dependencies \fIare\fR still resolved and added to the \fBpackage-lock.json\fR or \fBnpm-shrinkwrap.json\fR file. They are just not physically installed on disk.
+Note that these dependencies \fIare\fR still resolved and added to the \fBpackage-lock.json\fR file. They are just not physically installed on disk.
.P
If a package type appears in both the \fB--include\fR and \fB--omit\fR lists, then it will be included.
.P
diff --git a/deps/npm/man/man1/npm-login.1 b/deps/npm/man/man1/npm-login.1
index ecc47d745de..7c97ebae364 100644
--- a/deps/npm/man/man1/npm-login.1
+++ b/deps/npm/man/man1/npm-login.1
@@ -1,4 +1,4 @@
-.TH "NPM-LOGIN" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-LOGIN" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-login\fR - Login to a registry user account
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-logout.1 b/deps/npm/man/man1/npm-logout.1
index 22d86e96586..75e1b4b31c2 100644
--- a/deps/npm/man/man1/npm-logout.1
+++ b/deps/npm/man/man1/npm-logout.1
@@ -1,4 +1,4 @@
-.TH "NPM-LOGOUT" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-LOGOUT" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-logout\fR - Log out of the registry
.SS "Synopsis"
@@ -65,7 +65,7 @@ npm init --scope=@foo --yes
.SS "See Also"
.RS 0
.IP \(bu 4
-npm help adduser
+npm help login
.IP \(bu 4
npm help registry
.IP \(bu 4
diff --git a/deps/npm/man/man1/npm-ls.1 b/deps/npm/man/man1/npm-ls.1
index 52224d908c2..f805465a2d2 100644
--- a/deps/npm/man/man1/npm-ls.1
+++ b/deps/npm/man/man1/npm-ls.1
@@ -1,4 +1,4 @@
-.TH "NPM-LS" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-LS" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-ls\fR - List installed packages
.SS "Synopsis"
@@ -20,7 +20,7 @@ Positional arguments are \fBname@version-range\fR identifiers, which will limit
.P
.RS 2
.nf
-npm@11.19.1 /path/to/npm
+npm@12.1.0 /path/to/npm
└─┬ init-package-json@0.0.4
└── promzard@0.1.5
.fi
@@ -123,7 +123,7 @@ Type: "dev", "optional", or "peer" (can be set multiple times)
.P
Dependency types to omit from the installation tree on disk.
.P
-Note that these dependencies \fIare\fR still resolved and added to the \fBpackage-lock.json\fR or \fBnpm-shrinkwrap.json\fR file. They are just not physically installed on disk.
+Note that these dependencies \fIare\fR still resolved and added to the \fBpackage-lock.json\fR file. They are just not physically installed on disk.
.P
If a package type appears in both the \fB--include\fR and \fB--omit\fR lists, then it will be included.
.P
diff --git a/deps/npm/man/man1/npm-org.1 b/deps/npm/man/man1/npm-org.1
index 4b7592722da..8dbf5f5c7b0 100644
--- a/deps/npm/man/man1/npm-org.1
+++ b/deps/npm/man/man1/npm-org.1
@@ -1,4 +1,4 @@
-.TH "NPM-ORG" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-ORG" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-org\fR - Manage orgs
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-outdated.1 b/deps/npm/man/man1/npm-outdated.1
index f83acac0d64..5bd59b029b5 100644
--- a/deps/npm/man/man1/npm-outdated.1
+++ b/deps/npm/man/man1/npm-outdated.1
@@ -1,4 +1,4 @@
-.TH "NPM-OUTDATED" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-OUTDATED" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-outdated\fR - Check for outdated packages
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-owner.1 b/deps/npm/man/man1/npm-owner.1
index 68a98e734ef..cf2f1437674 100644
--- a/deps/npm/man/man1/npm-owner.1
+++ b/deps/npm/man/man1/npm-owner.1
@@ -1,4 +1,4 @@
-.TH "NPM-OWNER" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-OWNER" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-owner\fR - Manage package owners
.SS "Synopsis"
@@ -106,5 +106,5 @@ npm help publish
.IP \(bu 4
npm help registry
.IP \(bu 4
-npm help adduser
+npm help login
.RE 0
diff --git a/deps/npm/man/man1/npm-pack.1 b/deps/npm/man/man1/npm-pack.1
index 58b82df2663..11ea867006b 100644
--- a/deps/npm/man/man1/npm-pack.1
+++ b/deps/npm/man/man1/npm-pack.1
@@ -1,4 +1,4 @@
-.TH "NPM-PACK" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-PACK" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-pack\fR - Create a tarball from a package
.SS "Synopsis"
@@ -118,6 +118,8 @@ Type: Boolean
If true, npm does not run scripts specified in package.json files.
.P
Note that commands explicitly intended to run a particular script, such as \fBnpm start\fR, \fBnpm stop\fR, \fBnpm restart\fR, \fBnpm test\fR, and \fBnpm run\fR will still run their intended script if \fBignore-scripts\fR is set, but they will \fInot\fR run any pre- or post-scripts.
+.P
+Setting \fBignore-scripts\fR also disables \fB.npm-extension\fR execution, as if \fBignore-extension\fR were set.
.SS "Description"
.P
For anything that's installable (that is, a package folder, tarball, tarball url, git url, name@tag, name@version, name, or scoped name), this command will fetch it to the cache, copy the tarball to the current working directory as \fB<name>-<version>.tgz\fR, and then write the filenames out to stdout.
diff --git a/deps/npm/man/man1/npm-patch.1 b/deps/npm/man/man1/npm-patch.1
new file mode 100644
index 00000000000..ce137bf6c3f
--- /dev/null
+++ b/deps/npm/man/man1/npm-patch.1
@@ -0,0 +1,146 @@
+.TH "NPM-PATCH" "1" "September 2026" "NPM@12.1.0" ""
+.SH "NAME"
+\fBnpm-patch\fR - Apply local patches to installed dependencies
+.SS "Synopsis"
+.P
+.RS 2
+.nf
+npm patch <pkg>\[lB]@<version>\[rB]
+npm patch add <pkg>\[lB]@<version>\[rB] \[lB]--edit-dir <path>\[rB] \[lB]--ignore-existing\[rB]
+npm patch commit <edit-dir> \[lB]--patches-dir <dir>\[rB] \[lB]--keep-edit-dir\[rB]
+npm patch update <pkg>\[lB]@<old-version>\[rB] \[lB]--to <new-version>\[rB] \[lB]--patches-dir <dir>\[rB]
+npm patch ls
+npm patch rm <pkg>\[lB]@<version>\[rB]
+.fi
+.RE
+.P
+Note: This command is unaware of workspaces.
+.SS "Description"
+.P
+\fBnpm patch\fR lets you apply small, local modifications to an installed dependency and have them re-applied automatically on every install. Patches are declared in the \fBpatchedDependencies\fR field of your root \fBpackage.json\fR, stored as plain unified diffs under the \fBpatches/\fR directory, and recorded with a content hash in \fBpackage-lock.json\fR.
+.P
+Because patches are applied during the install itself, they work regardless of \fBinstall-strategy\fR, apply to transitive dependencies, and are \fBnot\fR disabled by \fB--ignore-scripts\fR.
+.P
+The bare form \fBnpm patch <pkg>\fR is shorthand for \fBnpm patch add <pkg>\fR. A package literally named like a subcommand must use the explicit form, e.g. \fBnpm patch add add\fR.
+.RS 0
+.IP \(bu 4
+\fBnpm patch add <pkg>\[lB]@<version>\[rB]\fR
+.P
+Prepares a package for editing. npm extracts a clean copy of the resolved package tarball into a temporary directory outside \fBnode_modules\fR and prints its path. Edit the files there, then run \fBnpm patch commit\fR.
+.P
+If more than one version of \fB<pkg>\fR is installed, re-run with an exact selector such as \fBnpm patch add lodash@4.17.21\fR.
+.IP \(bu 4
+\fBnpm patch commit <edit-dir>\fR
+.P
+Diffs the edited directory against a clean copy of the original tarball, writes the unified diff to \fB<patches-dir>/<name>@<version>.patch\fR, adds the entry to \fBpatchedDependencies\fR, and updates \fBpackage-lock.json\fR.
+.IP \(bu 4
+\fBnpm patch ls\fR
+.P
+Lists registered patches and how many installed nodes each one matches.
+.IP \(bu 4
+\fBnpm patch rm <pkg>\[lB]@<version>\[rB]\fR
+.P
+Removes the matching entries from \fBpatchedDependencies\fR, deletes the patch file when no other entry references it, and updates \fBpackage-lock.json\fR. If \fB<version>\fR is omitted, all entries for \fB<pkg>\fR are removed.
+.RE 0
+
+.SS "Failure modes"
+.P
+By default any patch problem is a hard error that aborts the install: a patch that fails to apply, a registered patch that matches no installed package, a missing patch file, or a patch whose hash does not match the lockfile.
+.P
+Two CLI-only flags relax this for one-off cases: \fB--allow-unused-patches\fR and \fB--ignore-patch-failures\fR.
+.SS "Configuration"
+.SS "\fBpatches-dir\fR"
+.RS 0
+.IP \(bu 4
+Default: "patches"
+.IP \(bu 4
+Type: String
+.RE 0
+
+.P
+The directory, relative to the project root, where \fBnpm patch commit\fR writes patch files for \fBpatchedDependencies\fR.
+.SS "\fBallow-unused-patches\fR"
+.RS 0
+.IP \(bu 4
+Default: false
+.IP \(bu 4
+Type: Boolean
+.RE 0
+
+.P
+Install even when a registered patch in \fBpatchedDependencies\fR matches no installed package. Does not silence patch apply failures.
+.P
+This flag is only honored when passed on the command line; it is ignored in \fB.npmrc\fR and environment variables, and rejected by \fBnpm ci\fR.
+.SS "\fBignore-patch-failures\fR"
+.RS 0
+.IP \(bu 4
+Default: false
+.IP \(bu 4
+Type: Boolean
+.RE 0
+
+.P
+Install even when a registered patch fails to apply, with a warning per failure. Intended for incident response only.
+.P
+This flag is only honored when passed on the command line; it is ignored in \fB.npmrc\fR and environment variables, and rejected by \fBnpm ci\fR.
+.SS "\fBedit-dir\fR"
+.RS 0
+.IP \(bu 4
+Default: null
+.IP \(bu 4
+Type: null or Path
+.RE 0
+
+.P
+Override the temporary directory used by \fBnpm patch add\fR to prepare a package for editing.
+.SS "\fBignore-existing\fR"
+.RS 0
+.IP \(bu 4
+Default: false
+.IP \(bu 4
+Type: Boolean
+.RE 0
+
+.P
+With \fBnpm patch add\fR, discard a previous unfinished edit directory and start fresh.
+.SS "\fBkeep-edit-dir\fR"
+.RS 0
+.IP \(bu 4
+Default: false
+.IP \(bu 4
+Type: Boolean
+.RE 0
+
+.P
+With \fBnpm patch commit\fR, do not remove the edit directory after committing the patch.
+.SS "\fBto\fR"
+.RS 0
+.IP \(bu 4
+Default: null
+.IP \(bu 4
+Type: null or String
+.RE 0
+
+.P
+Used by \fBnpm patch update\fR to set the version to rebase a patch onto when it cannot be read from \fBpackage-lock.json\fR \[em] for example an exact-version selector, or a version that has not been installed yet.
+.SS "\fBregistry\fR"
+.RS 0
+.IP \(bu 4
+Default: "https://registry.npmjs.org/"
+.IP \(bu 4
+Type: URL
+.RE 0
+
+.P
+The base URL of the npm registry.
+.SH "SEE ALSO"
+.RS 0
+.IP \(bu 4
+npm help install
+.IP \(bu 4
+npm help ci
+.IP \(bu 4
+\fBpackage-lock.json\fR \fI\(la/configuring-npm/package-lock-json\(ra\fR
+.IP \(bu 4
+npm help config
+.RE 0
diff --git a/deps/npm/man/man1/npm-ping.1 b/deps/npm/man/man1/npm-ping.1
index 4df93fbd993..a8d07fd4264 100644
--- a/deps/npm/man/man1/npm-ping.1
+++ b/deps/npm/man/man1/npm-ping.1
@@ -1,4 +1,4 @@
-.TH "NPM-PING" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-PING" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-ping\fR - Ping npm registry
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-pkg.1 b/deps/npm/man/man1/npm-pkg.1
index ad11f73873a..6bb01b3b514 100644
--- a/deps/npm/man/man1/npm-pkg.1
+++ b/deps/npm/man/man1/npm-pkg.1
@@ -1,4 +1,4 @@
-.TH "NPM-PKG" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-PKG" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-pkg\fR - Manages your package.json
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-prefix.1 b/deps/npm/man/man1/npm-prefix.1
index 6c990176088..96cd2fd7492 100644
--- a/deps/npm/man/man1/npm-prefix.1
+++ b/deps/npm/man/man1/npm-prefix.1
@@ -1,4 +1,4 @@
-.TH "NPM-PREFIX" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-PREFIX" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-prefix\fR - Display prefix
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-profile.1 b/deps/npm/man/man1/npm-profile.1
index 0d5d54620f7..c40afb995a5 100644
--- a/deps/npm/man/man1/npm-profile.1
+++ b/deps/npm/man/man1/npm-profile.1
@@ -1,4 +1,4 @@
-.TH "NPM-PROFILE" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-PROFILE" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-profile\fR - Change settings on your registry profile
.SS "Synopsis"
@@ -29,8 +29,6 @@ email: e@example.com (verified)
two-factor auth: auth-and-writes
fullname: Example User
homepage:
-freenode:
-twitter:
github:
created: 2015-02-26T01:38:35.892Z
updated: 2017-10-02T21:29:45.922Z
@@ -38,7 +36,7 @@ updated: 2017-10-02T21:29:45.922Z
.RE
.RS 0
.IP \(bu 4
-\fBnpm profile set <property> <value>\fR: Set the value of a profile property. You can set the following properties this way: email, fullname, homepage, freenode, twitter, github
+\fBnpm profile set <property> <value>\fR: Set the value of a profile property. You can set the following properties this way: email, fullname, homepage, github
.IP \(bu 4
\fBnpm profile set password\fR: Change your password. This is interactive, you'll be prompted for your current password and a new password. You'll also be prompted for an OTP if you have two-factor authentication enabled.
.IP \(bu 4
@@ -110,7 +108,7 @@ If not set, and a registry response fails with a challenge for a one-time passwo
.SS "See Also"
.RS 0
.IP \(bu 4
-npm help adduser
+npm help login
.IP \(bu 4
npm help registry
.IP \(bu 4
diff --git a/deps/npm/man/man1/npm-prune.1 b/deps/npm/man/man1/npm-prune.1
index 8f67ca9384f..4989bdabc1c 100644
--- a/deps/npm/man/man1/npm-prune.1
+++ b/deps/npm/man/man1/npm-prune.1
@@ -1,4 +1,4 @@
-.TH "NPM-PRUNE" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-PRUNE" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-prune\fR - Remove extraneous packages
.SS "Synopsis"
@@ -33,7 +33,7 @@ Type: "dev", "optional", or "peer" (can be set multiple times)
.P
Dependency types to omit from the installation tree on disk.
.P
-Note that these dependencies \fIare\fR still resolved and added to the \fBpackage-lock.json\fR or \fBnpm-shrinkwrap.json\fR file. They are just not physically installed on disk.
+Note that these dependencies \fIare\fR still resolved and added to the \fBpackage-lock.json\fR file. They are just not physically installed on disk.
.P
If a package type appears in both the \fB--include\fR and \fB--omit\fR lists, then it will be included.
.P
@@ -105,6 +105,8 @@ Type: Boolean
If true, npm does not run scripts specified in package.json files.
.P
Note that commands explicitly intended to run a particular script, such as \fBnpm start\fR, \fBnpm stop\fR, \fBnpm restart\fR, \fBnpm test\fR, and \fBnpm run\fR will still run their intended script if \fBignore-scripts\fR is set, but they will \fInot\fR run any pre- or post-scripts.
+.P
+Setting \fBignore-scripts\fR also disables \fB.npm-extension\fR execution, as if \fBignore-extension\fR were set.
.SS "\fBworkspace\fR"
.RS 0
.IP \(bu 4
diff --git a/deps/npm/man/man1/npm-publish.1 b/deps/npm/man/man1/npm-publish.1
index 4e738ab0bbd..67ef2babd8c 100644
--- a/deps/npm/man/man1/npm-publish.1
+++ b/deps/npm/man/man1/npm-publish.1
@@ -1,4 +1,4 @@
-.TH "NPM-PUBLISH" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-PUBLISH" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-publish\fR - Publish a package
.SS "Synopsis"
@@ -225,6 +225,8 @@ Type: Boolean
.P
When publishing from a supported cloud CI/CD system, the package will be publicly linked to where it was built and published from.
.P
+When the \fBprovenance-file\fR config is set, it takes precedence and automatic provenance generation (including via trusted publishing/OIDC) is skipped.
+.P
This config cannot be used with: \fBprovenance-file\fR
.SS "\fBprovenance-file\fR"
.RS 0
@@ -237,6 +239,8 @@ Type: Path
.P
When publishing, the provenance bundle at the given path will be used.
.P
+This takes precedence over automatic provenance generation in trusted publishing flows.
+.P
This config cannot be used with: \fBprovenance\fR
.SS "See Also"
.RS 0
@@ -249,7 +253,7 @@ npm help registry
.IP \(bu 4
npm help scope
.IP \(bu 4
-npm help adduser
+npm help login
.IP \(bu 4
npm help owner
.IP \(bu 4
diff --git a/deps/npm/man/man1/npm-query.1 b/deps/npm/man/man1/npm-query.1
index 334fc20660e..8fbce54d090 100644
--- a/deps/npm/man/man1/npm-query.1
+++ b/deps/npm/man/man1/npm-query.1
@@ -1,4 +1,4 @@
-.TH "NPM-QUERY" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-QUERY" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-query\fR - Dependency selector query
.SS "Synopsis"
@@ -157,7 +157,7 @@ $ npm query ':root>:outdated(in-range).prod' --no-expect-results
.RE
.SS "Package lock only mode"
.P
-If package-lock-only is enabled, only the information in the package lock (or shrinkwrap) is loaded. This means that information from the package.json files of your dependencies will not be included in the result set (e.g. description, homepage, engines).
+If package-lock-only is enabled, only the information in the package lock is loaded. This means that information from the package.json files of your dependencies will not be included in the result set (e.g. description, homepage, engines).
.SS "Configuration"
.SS "\fBglobal\fR"
.RS 0
diff --git a/deps/npm/man/man1/npm-rebuild.1 b/deps/npm/man/man1/npm-rebuild.1
index 6a09726529b..0242f143473 100644
--- a/deps/npm/man/man1/npm-rebuild.1
+++ b/deps/npm/man/man1/npm-rebuild.1
@@ -1,4 +1,4 @@
-.TH "NPM-REBUILD" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-REBUILD" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-rebuild\fR - Rebuild a package
.SS "Synopsis"
@@ -101,6 +101,8 @@ Type: Boolean
If true, npm does not run scripts specified in package.json files.
.P
Note that commands explicitly intended to run a particular script, such as \fBnpm start\fR, \fBnpm stop\fR, \fBnpm restart\fR, \fBnpm test\fR, and \fBnpm run\fR will still run their intended script if \fBignore-scripts\fR is set, but they will \fInot\fR run any pre- or post-scripts.
+.P
+Setting \fBignore-scripts\fR also disables \fB.npm-extension\fR execution, as if \fBignore-extension\fR were set.
.SS "\fBallow-scripts\fR"
.RS 0
.IP \(bu 4
@@ -115,6 +117,8 @@ Comma-separated list of packages whose install-time lifecycle scripts (\fBpreins
This setting is intended for one-off and global contexts: \fBnpm exec\fR, \fBnpx\fR, and \fBnpm install -g\fR, where no project \fBpackage.json\fR is involved. For team-wide policy in a project, use the \fBallowScripts\fR field in \fBpackage.json\fR (which also supports explicit denials), or configure it in \fB.npmrc\fR. Passing \fB--allow-scripts\fR on the command line during a project-scoped \fBnpm install\fR, \fBci\fR, \fBupdate\fR, or \fBrebuild\fR is an error.
.P
Each name is matched against a dependency's resolved identity, not against the package's self-reported name. \fB--ignore-scripts\fR and \fB--dangerously-allow-all-scripts\fR both override this setting.
+.P
+This value is not exported to the environment for child processes.
.SS "\fBstrict-allow-scripts\fR"
.RS 0
.IP \(bu 4
@@ -124,9 +128,9 @@ Type: Boolean
.RE 0
.P
-If \fBtrue\fR, turn the install-script policy from a warning into a hard error: any dependency with install scripts not covered by \fBallowScripts\fR will fail the install instead of running with a notice.
+If \fBtrue\fR, turn the install-script policy from a warning into a hard error: any dependency with install scripts that is not covered by \fBallowScripts\fR will fail the install instead of being blocked with a warning.
.P
-Dependencies explicitly denied with \fBfalse\fR in \fBallowScripts\fR are always silently skipped; this setting only affects unreviewed entries. \fB--ignore-scripts\fR and \fB--dangerously-allow-all-scripts\fR both override this setting.
+Dependencies explicitly denied with \fBfalse\fR in \fBallowScripts\fR are always silently skipped; this setting only affects unreviewed entries (packages with install scripts that are neither approved nor denied). \fB--ignore-scripts\fR and \fB--dangerously-allow-all-scripts\fR both override this setting.
.P
Optional dependencies that cannot be installed on the current platform or engine (a non-matching \fBos\fR, \fBcpu\fR, or \fBlibc\fR) are not flagged, because their install scripts never run.
.SS "\fBdangerously-allow-all-scripts\fR"
diff --git a/deps/npm/man/man1/npm-repo.1 b/deps/npm/man/man1/npm-repo.1
index 5ff08e9eeb4..ab28777a90b 100644
--- a/deps/npm/man/man1/npm-repo.1
+++ b/deps/npm/man/man1/npm-repo.1
@@ -1,4 +1,4 @@
-.TH "NPM-REPO" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-REPO" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-repo\fR - Open package repository page in the browser
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-restart.1 b/deps/npm/man/man1/npm-restart.1
index d4f5f0d3df1..2db4fbb40a0 100644
--- a/deps/npm/man/man1/npm-restart.1
+++ b/deps/npm/man/man1/npm-restart.1
@@ -1,4 +1,4 @@
-.TH "NPM-RESTART" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-RESTART" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-restart\fR - Restart a package
.SS "Synopsis"
@@ -56,6 +56,8 @@ Type: Boolean
If true, npm does not run scripts specified in package.json files.
.P
Note that commands explicitly intended to run a particular script, such as \fBnpm start\fR, \fBnpm stop\fR, \fBnpm restart\fR, \fBnpm test\fR, and \fBnpm run\fR will still run their intended script if \fBignore-scripts\fR is set, but they will \fInot\fR run any pre- or post-scripts.
+.P
+Setting \fBignore-scripts\fR also disables \fB.npm-extension\fR execution, as if \fBignore-extension\fR were set.
.SS "\fBscript-shell\fR"
.RS 0
.IP \(bu 4
diff --git a/deps/npm/man/man1/npm-root.1 b/deps/npm/man/man1/npm-root.1
index ecd0c64ef6b..f1acff9f88e 100644
--- a/deps/npm/man/man1/npm-root.1
+++ b/deps/npm/man/man1/npm-root.1
@@ -1,4 +1,4 @@
-.TH "NPM-ROOT" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-ROOT" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-root\fR - Display npm root
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-run.1 b/deps/npm/man/man1/npm-run.1
index 8aadcceff7c..2fb828a6fda 100644
--- a/deps/npm/man/man1/npm-run.1
+++ b/deps/npm/man/man1/npm-run.1
@@ -1,4 +1,4 @@
-.TH "NPM-RUN" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-RUN" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-run\fR - Run arbitrary package scripts
.SS "Synopsis"
@@ -192,6 +192,8 @@ Type: Boolean
If true, npm does not run scripts specified in package.json files.
.P
Note that commands explicitly intended to run a particular script, such as \fBnpm start\fR, \fBnpm stop\fR, \fBnpm restart\fR, \fBnpm test\fR, and \fBnpm run\fR will still run their intended script if \fBignore-scripts\fR is set, but they will \fInot\fR run any pre- or post-scripts.
+.P
+Setting \fBignore-scripts\fR also disables \fB.npm-extension\fR execution, as if \fBignore-extension\fR were set.
.SS "\fBforeground-scripts\fR"
.RS 0
.IP \(bu 4
diff --git a/deps/npm/man/man1/npm-sbom.1 b/deps/npm/man/man1/npm-sbom.1
index f694d642f9a..c751d8470f1 100644
--- a/deps/npm/man/man1/npm-sbom.1
+++ b/deps/npm/man/man1/npm-sbom.1
@@ -1,4 +1,4 @@
-.TH "NPM-SBOM" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-SBOM" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-sbom\fR - Generate a Software Bill of Materials (SBOM)
.SS "Synopsis"
@@ -205,7 +205,7 @@ The \fBnpm sbom\fR command generates a Software Bill of Materials (SBOM) listing
.RE
.SS "Package lock only mode"
.P
-If package-lock-only is enabled, only the information in the package lock (or shrinkwrap) is loaded. This means that information from the package.json files of your dependencies will not be included in the result set (e.g. description, homepage, engines).
+If package-lock-only is enabled, only the information in the package lock is loaded. This means that information from the package.json files of your dependencies will not be included in the result set (e.g. description, homepage, engines).
.SS "Configuration"
.SS "\fBomit\fR"
.RS 0
@@ -218,7 +218,7 @@ Type: "dev", "optional", or "peer" (can be set multiple times)
.P
Dependency types to omit from the installation tree on disk.
.P
-Note that these dependencies \fIare\fR still resolved and added to the \fBpackage-lock.json\fR or \fBnpm-shrinkwrap.json\fR file. They are just not physically installed on disk.
+Note that these dependencies \fIare\fR still resolved and added to the \fBpackage-lock.json\fR file. They are just not physically installed on disk.
.P
If a package type appears in both the \fB--include\fR and \fB--omit\fR lists, then it will be included.
.P
diff --git a/deps/npm/man/man1/npm-search.1 b/deps/npm/man/man1/npm-search.1
index 969d0e78490..c26d0e703b2 100644
--- a/deps/npm/man/man1/npm-search.1
+++ b/deps/npm/man/man1/npm-search.1
@@ -1,4 +1,4 @@
-.TH "NPM-SEARCH" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-SEARCH" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-search\fR - Search for packages
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-set.1 b/deps/npm/man/man1/npm-set.1
index 4deaf8e01ac..7b536646dbe 100644
--- a/deps/npm/man/man1/npm-set.1
+++ b/deps/npm/man/man1/npm-set.1
@@ -1,4 +1,4 @@
-.TH "NPM-SET" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-SET" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-set\fR - Set a value in the npm configuration
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-shrinkwrap.1 b/deps/npm/man/man1/npm-shrinkwrap.1
deleted file mode 100644
index 35caa20c3dc..00000000000
--- a/deps/npm/man/man1/npm-shrinkwrap.1
+++ /dev/null
@@ -1,32 +0,0 @@
-.TH "NPM-SHRINKWRAP" "1" "August 2026" "NPM@11.19.1" ""
-.SH "NAME"
-\fBnpm-shrinkwrap\fR - Lock down dependency versions for publication
-.SS "Synopsis"
-.P
-.RS 2
-.nf
-npm shrinkwrap
-.fi
-.RE
-.P
-Note: This command is unaware of workspaces.
-.SS "Description"
-.P
-This command repurposes \fBpackage-lock.json\fR into a publishable \fBnpm-shrinkwrap.json\fR or simply creates a new one. The file created and updated by this command will then take precedence over any other existing or future \fBpackage-lock.json\fR files. For a detailed explanation of the design and purpose of package locks in npm, see npm help package-lock-json.
-.SS "See Also"
-.RS 0
-.IP \(bu 4
-npm help install
-.IP \(bu 4
-npm help run
-.IP \(bu 4
-npm help scripts
-.IP \(bu 4
-\fBpackage.json\fR \fI\(la/configuring-npm/package-json\(ra\fR
-.IP \(bu 4
-\fBpackage-lock.json\fR \fI\(la/configuring-npm/package-lock-json\(ra\fR
-.IP \(bu 4
-\fBnpm-shrinkwrap.json\fR \fI\(la/configuring-npm/npm-shrinkwrap-json\(ra\fR
-.IP \(bu 4
-npm help ls
-.RE 0
diff --git a/deps/npm/man/man1/npm-stage.1 b/deps/npm/man/man1/npm-stage.1
index 8c201605213..57cd8428015 100644
--- a/deps/npm/man/man1/npm-stage.1
+++ b/deps/npm/man/man1/npm-stage.1
@@ -1,4 +1,4 @@
-.TH "NPM-STAGE" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-STAGE" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-stage\fR - Stage packages for publishing
.SS "Synopsis"
@@ -101,7 +101,7 @@ npm stage publish <package-spec>
.RE
.SS "Flags"
.P
-| Flag | Default | Type | Description | | --- | --- | --- | --- | | \fB--tag\fR | "latest" | String | If you ask npm to install a package and don't tell it a specific version, then it will install the specified tag. It is the tag added to the package@version specified in the \fBnpm dist-tag add\fR command, if no explicit tag is given. When used by the \fBnpm diff\fR command, this is the tag used to fetch the tarball that will be compared with the local files by default. If used in the \fBnpm publish\fR command, this is the tag that will be added to the package submitted to the registry. | | \fB--access\fR | 'public' for new packages, existing packages it will not change the current level | null, "restricted", "public", or "private" | If you do not want your scoped package to be publicly viewable (and installable) set \fB--access=restricted\fR. Unscoped packages cannot be set to \fBrestricted\fR. Note: This defaults to not changing the current access level for existing packages. Specifying a value of \fBrestricted\fR or \fBpublic\fR during publish will change the access for an existing package the same way that \fBnpm access set status\fR would. The value \fBprivate\fR is an alias for \fBrestricted\fR. | | \fB--dry-run\fR | false | Boolean | Indicates that you don't want npm to make any changes and that it should only report what it would have done. This can be passed into any of the commands that modify your local installation, eg, \fBinstall\fR, \fBupdate\fR, \fBdedupe\fR, \fBuninstall\fR, as well as \fBpack\fR and \fBpublish\fR. Note: This is NOT honored by other network related commands, eg \fBdist-tags\fR, \fBowner\fR, etc. | | \fB--otp\fR | null | null or String | This is a one-time password from a two-factor authenticator. It's needed when publishing or changing package permissions with \fBnpm access\fR. If not set, and a registry response fails with a challenge for a one-time password, npm will prompt on the command line for one. | | \fB--workspace\fR, \fB-w\fR | | String (can be set multiple times) | Enable running a command in the context of the configured workspaces of the current project while filtering by running only the workspaces defined by this configuration option. Valid values for the \fBworkspace\fR config are either: * Workspace names * Path to a workspace directory * Path to a parent workspace directory (will result in selecting all workspaces within that folder) When set for the \fBnpm init\fR command, this may be set to the folder of a workspace which does not yet exist, to create the folder and set it up as a brand new workspace within the project. | | \fB--workspaces\fR | null | null or Boolean | Set to true to run the command in the context of \fBall\fR configured workspaces. Explicitly setting this to false will cause commands like \fBinstall\fR to ignore workspaces altogether. When not set explicitly: - Commands that operate on the \fBnode_modules\fR tree (install, update, etc.) will link workspaces into the \fBnode_modules\fR folder. - Commands that do other things (test, exec, publish, etc.) will operate on the root project, \fIunless\fR one or more workspaces are specified in the \fBworkspace\fR config. | | \fB--include-workspace-root\fR | false | Boolean | Include the workspace root when workspaces are enabled for a command. When false, specifying individual workspaces via the \fBworkspace\fR config, or all workspaces via the \fBworkspaces\fR flag, will cause npm to operate only on the specified workspaces, and not on the root project. | | \fB--provenance\fR | false | Boolean | When publishing from a supported cloud CI/CD system, the package will be publicly linked to where it was built and published from. |
+| Flag | Default | Type | Description | | --- | --- | --- | --- | | \fB--tag\fR | "latest" | String | If you ask npm to install a package and don't tell it a specific version, then it will install the specified tag. It is the tag added to the package@version specified in the \fBnpm dist-tag add\fR command, if no explicit tag is given. When used by the \fBnpm diff\fR command, this is the tag used to fetch the tarball that will be compared with the local files by default. If used in the \fBnpm publish\fR command, this is the tag that will be added to the package submitted to the registry. | | \fB--access\fR | 'public' for new packages, existing packages it will not change the current level | null, "restricted", "public", or "private" | If you do not want your scoped package to be publicly viewable (and installable) set \fB--access=restricted\fR. Unscoped packages cannot be set to \fBrestricted\fR. Note: This defaults to not changing the current access level for existing packages. Specifying a value of \fBrestricted\fR or \fBpublic\fR during publish will change the access for an existing package the same way that \fBnpm access set status\fR would. The value \fBprivate\fR is an alias for \fBrestricted\fR. | | \fB--dry-run\fR | false | Boolean | Indicates that you don't want npm to make any changes and that it should only report what it would have done. This can be passed into any of the commands that modify your local installation, eg, \fBinstall\fR, \fBupdate\fR, \fBdedupe\fR, \fBuninstall\fR, as well as \fBpack\fR and \fBpublish\fR. Note: This is NOT honored by other network related commands, eg \fBdist-tags\fR, \fBowner\fR, etc. | | \fB--otp\fR | null | null or String | This is a one-time password from a two-factor authenticator. It's needed when publishing or changing package permissions with \fBnpm access\fR. If not set, and a registry response fails with a challenge for a one-time password, npm will prompt on the command line for one. | | \fB--workspace\fR, \fB-w\fR | | String (can be set multiple times) | Enable running a command in the context of the configured workspaces of the current project while filtering by running only the workspaces defined by this configuration option. Valid values for the \fBworkspace\fR config are either: * Workspace names * Path to a workspace directory * Path to a parent workspace directory (will result in selecting all workspaces within that folder) When set for the \fBnpm init\fR command, this may be set to the folder of a workspace which does not yet exist, to create the folder and set it up as a brand new workspace within the project. | | \fB--workspaces\fR | null | null or Boolean | Set to true to run the command in the context of \fBall\fR configured workspaces. Explicitly setting this to false will cause commands like \fBinstall\fR to ignore workspaces altogether. When not set explicitly: - Commands that operate on the \fBnode_modules\fR tree (install, update, etc.) will link workspaces into the \fBnode_modules\fR folder. - Commands that do other things (test, exec, publish, etc.) will operate on the root project, \fIunless\fR one or more workspaces are specified in the \fBworkspace\fR config. | | \fB--include-workspace-root\fR | false | Boolean | Include the workspace root when workspaces are enabled for a command. When false, specifying individual workspaces via the \fBworkspace\fR config, or all workspaces via the \fBworkspaces\fR flag, will cause npm to operate only on the specified workspaces, and not on the root project. | | \fB--provenance\fR | false | Boolean | When publishing from a supported cloud CI/CD system, the package will be publicly linked to where it was built and published from. When the \fBprovenance-file\fR config is set, it takes precedence and automatic provenance generation (including via trusted publishing/OIDC) is skipped. |
.SS "\fBnpm stage list\fR"
.P
List all staged package versions
diff --git a/deps/npm/man/man1/npm-star.1 b/deps/npm/man/man1/npm-star.1
deleted file mode 100644
index a2191c120e3..00000000000
--- a/deps/npm/man/man1/npm-star.1
+++ /dev/null
@@ -1,76 +0,0 @@
-.TH "NPM-STAR" "1" "August 2026" "NPM@11.19.1" ""
-.SH "NAME"
-\fBnpm-star\fR - Mark your favorite packages
-.SS "Synopsis"
-.P
-.RS 2
-.nf
-npm star \[lB]<package-spec>...\[rB]
-.fi
-.RE
-.P
-Note: This command is unaware of workspaces.
-.SS "Description"
-.P
-"Starring" a package means that you have some interest in it. It's a vaguely positive way to show that you care.
-.P
-It's a boolean thing. Starring repeatedly has no additional effect.
-.SS "More"
-.P
-There's also these extra commands to help you manage your favorite packages:
-.SS "Unstar"
-.P
-You can also "unstar" a package using npm help unstar
-.P
-"Unstarring" is the same thing, but in reverse.
-.SS "Listing stars"
-.P
-You can see all your starred packages using npm help stars
-.SS "Configuration"
-.SS "\fBregistry\fR"
-.RS 0
-.IP \(bu 4
-Default: "https://registry.npmjs.org/"
-.IP \(bu 4
-Type: URL
-.RE 0
-
-.P
-The base URL of the npm registry.
-.SS "\fBunicode\fR"
-.RS 0
-.IP \(bu 4
-Default: false on windows, true on mac/unix systems with a unicode locale, as defined by the \fBLC_ALL\fR, \fBLC_CTYPE\fR, or \fBLANG\fR environment variables.
-.IP \(bu 4
-Type: Boolean
-.RE 0
-
-.P
-When set to true, npm uses unicode characters in the tree output. When false, it uses ascii characters instead of unicode glyphs.
-.SS "\fBotp\fR"
-.RS 0
-.IP \(bu 4
-Default: null
-.IP \(bu 4
-Type: null or String
-.RE 0
-
-.P
-This is a one-time password from a two-factor authenticator. It's needed when publishing or changing package permissions with \fBnpm access\fR.
-.P
-If not set, and a registry response fails with a challenge for a one-time password, npm will prompt on the command line for one.
-.SS "See Also"
-.RS 0
-.IP \(bu 4
-npm help "package spec"
-.IP \(bu 4
-npm help unstar
-.IP \(bu 4
-npm help stars
-.IP \(bu 4
-npm help view
-.IP \(bu 4
-npm help whoami
-.IP \(bu 4
-npm help adduser
-.RE 0
diff --git a/deps/npm/man/man1/npm-stars.1 b/deps/npm/man/man1/npm-stars.1
deleted file mode 100644
index aca98ed914a..00000000000
--- a/deps/npm/man/man1/npm-stars.1
+++ /dev/null
@@ -1,41 +0,0 @@
-.TH "NPM-STARS" "1" "August 2026" "NPM@11.19.1" ""
-.SH "NAME"
-\fBnpm-stars\fR - View packages marked as favorites
-.SS "Synopsis"
-.P
-.RS 2
-.nf
-npm stars \[lB]<user>\[rB]
-.fi
-.RE
-.P
-Note: This command is unaware of workspaces.
-.SS "Description"
-.P
-If you have starred a lot of neat things and want to find them again quickly this command lets you do just that.
-.P
-You may also want to see your friend's favorite packages, in this case you will most certainly enjoy this command.
-.SS "Configuration"
-.SS "\fBregistry\fR"
-.RS 0
-.IP \(bu 4
-Default: "https://registry.npmjs.org/"
-.IP \(bu 4
-Type: URL
-.RE 0
-
-.P
-The base URL of the npm registry.
-.SS "See Also"
-.RS 0
-.IP \(bu 4
-npm help star
-.IP \(bu 4
-npm help unstar
-.IP \(bu 4
-npm help view
-.IP \(bu 4
-npm help whoami
-.IP \(bu 4
-npm help adduser
-.RE 0
diff --git a/deps/npm/man/man1/npm-start.1 b/deps/npm/man/man1/npm-start.1
index d2f3b4d87cc..2df0631bb06 100644
--- a/deps/npm/man/man1/npm-start.1
+++ b/deps/npm/man/man1/npm-start.1
@@ -1,4 +1,4 @@
-.TH "NPM-START" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-START" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-start\fR - Start a package
.SS "Synopsis"
@@ -53,6 +53,8 @@ Type: Boolean
If true, npm does not run scripts specified in package.json files.
.P
Note that commands explicitly intended to run a particular script, such as \fBnpm start\fR, \fBnpm stop\fR, \fBnpm restart\fR, \fBnpm test\fR, and \fBnpm run\fR will still run their intended script if \fBignore-scripts\fR is set, but they will \fInot\fR run any pre- or post-scripts.
+.P
+Setting \fBignore-scripts\fR also disables \fB.npm-extension\fR execution, as if \fBignore-extension\fR were set.
.SS "\fBscript-shell\fR"
.RS 0
.IP \(bu 4
diff --git a/deps/npm/man/man1/npm-stop.1 b/deps/npm/man/man1/npm-stop.1
index 7896dd6acd1..1f5093a84c2 100644
--- a/deps/npm/man/man1/npm-stop.1
+++ b/deps/npm/man/man1/npm-stop.1
@@ -1,4 +1,4 @@
-.TH "NPM-STOP" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-STOP" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-stop\fR - Stop a package
.SS "Synopsis"
@@ -49,6 +49,8 @@ Type: Boolean
If true, npm does not run scripts specified in package.json files.
.P
Note that commands explicitly intended to run a particular script, such as \fBnpm start\fR, \fBnpm stop\fR, \fBnpm restart\fR, \fBnpm test\fR, and \fBnpm run\fR will still run their intended script if \fBignore-scripts\fR is set, but they will \fInot\fR run any pre- or post-scripts.
+.P
+Setting \fBignore-scripts\fR also disables \fB.npm-extension\fR execution, as if \fBignore-extension\fR were set.
.SS "\fBscript-shell\fR"
.RS 0
.IP \(bu 4
diff --git a/deps/npm/man/man1/npm-team.1 b/deps/npm/man/man1/npm-team.1
index 21ccc530ad8..b5902750a31 100644
--- a/deps/npm/man/man1/npm-team.1
+++ b/deps/npm/man/man1/npm-team.1
@@ -1,4 +1,4 @@
-.TH "NPM-TEAM" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-TEAM" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-team\fR - Manage organization teams and team memberships
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-test.1 b/deps/npm/man/man1/npm-test.1
index 8cae879d829..ce579644d2d 100644
--- a/deps/npm/man/man1/npm-test.1
+++ b/deps/npm/man/man1/npm-test.1
@@ -1,4 +1,4 @@
-.TH "NPM-TEST" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-TEST" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-test\fR - Test a package
.SS "Synopsis"
@@ -47,6 +47,8 @@ Type: Boolean
If true, npm does not run scripts specified in package.json files.
.P
Note that commands explicitly intended to run a particular script, such as \fBnpm start\fR, \fBnpm stop\fR, \fBnpm restart\fR, \fBnpm test\fR, and \fBnpm run\fR will still run their intended script if \fBignore-scripts\fR is set, but they will \fInot\fR run any pre- or post-scripts.
+.P
+Setting \fBignore-scripts\fR also disables \fB.npm-extension\fR execution, as if \fBignore-extension\fR were set.
.SS "\fBscript-shell\fR"
.RS 0
.IP \(bu 4
diff --git a/deps/npm/man/man1/npm-token.1 b/deps/npm/man/man1/npm-token.1
index fc82daf8d0c..fcad022257f 100644
--- a/deps/npm/man/man1/npm-token.1
+++ b/deps/npm/man/man1/npm-token.1
@@ -1,4 +1,4 @@
-.TH "NPM-TOKEN" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-TOKEN" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-token\fR - Manage your authentication tokens
.SS "Synopsis"
@@ -104,11 +104,11 @@ When creating a Granular Access Token with \fBnpm token create\fR, this limits t
.IP \(bu 4
Default: null
.IP \(bu 4
-Type: null, "read-only", "read-write", or "no-access"
+Type: null, "read-only", "read-write", "read-write-stage-only", or "no-access"
.RE 0
.P
-When creating a Granular Access Token with \fBnpm token create\fR, sets the permission level for packages and scopes. Options are "read-only", "read-write", or "no-access".
+When creating a Granular Access Token with \fBnpm token create\fR, sets the permission level for packages and scopes. Options are "read-only", "read-write", "read-write-stage-only", or "no-access". "read-write-stage-only" grants publish access that stages releases instead of publishing them directly.
.SS "\fBorgs-permission\fR"
.RS 0
.IP \(bu 4
@@ -184,7 +184,7 @@ This is used to mark a token as unable to publish when configuring limited acces
.SS "See Also"
.RS 0
.IP \(bu 4
-npm help adduser
+npm help login
.IP \(bu 4
npm help registry
.IP \(bu 4
diff --git a/deps/npm/man/man1/npm-trust.1 b/deps/npm/man/man1/npm-trust.1
index fce69eb33b7..3d1c1712004 100644
--- a/deps/npm/man/man1/npm-trust.1
+++ b/deps/npm/man/man1/npm-trust.1
@@ -1,4 +1,4 @@
-.TH "NPM-TRUST" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-TRUST" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-trust\fR - Manage trusted publishing relationships between packages and CI/CD providers
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-undeprecate.1 b/deps/npm/man/man1/npm-undeprecate.1
index 11f91ee9b91..7f789a42c7c 100644
--- a/deps/npm/man/man1/npm-undeprecate.1
+++ b/deps/npm/man/man1/npm-undeprecate.1
@@ -1,4 +1,4 @@
-.TH "NPM-UNDEPRECATE" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-UNDEPRECATE" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-undeprecate\fR - Undeprecate a version of a package
.SS "Synopsis"
diff --git a/deps/npm/man/man1/npm-uninstall.1 b/deps/npm/man/man1/npm-uninstall.1
index b9ff997229d..2a2fb75d2be 100644
--- a/deps/npm/man/man1/npm-uninstall.1
+++ b/deps/npm/man/man1/npm-uninstall.1
@@ -1,4 +1,4 @@
-.TH "NPM-UNINSTALL" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-UNINSTALL" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-uninstall\fR - Remove a package
.SS "Synopsis"
@@ -16,11 +16,11 @@ This uninstalls a package, completely removing everything npm installed on its b
.P
It also removes the package from the \fBdependencies\fR, \fBdevDependencies\fR, \fBoptionalDependencies\fR, and \fBpeerDependencies\fR objects in your \fBpackage.json\fR.
.P
-Further, if you have an \fBnpm-shrinkwrap.json\fR or \fBpackage-lock.json\fR, npm will update those files as well.
+Further, if you have a \fBpackage-lock.json\fR, npm will update that file as well.
.P
-\fB--no-save\fR will tell npm not to remove the package from your \fBpackage.json\fR, \fBnpm-shrinkwrap.json\fR, or \fBpackage-lock.json\fR files.
+\fB--no-save\fR will tell npm not to remove the package from your \fBpackage.json\fR or \fBpackage-lock.json\fR files.
.P
-\fB--save\fR or \fB-S\fR will tell npm to remove the package from your \fBpackage.json\fR, \fBnpm-shrinkwrap.json\fR, and \fBpackage-lock.json\fR files. This is the default, but you may need to use this if you have for instance \fBsave=false\fR in your \fBnpmrc\fR file
+\fB--save\fR or \fB-S\fR will tell npm to remove the package from your \fBpackage.json\fR and \fBpackage-lock.json\fR files. This is the default, but you may need to use this if you have for instance \fBsave=false\fR in your \fBnpmrc\fR file
.P
In global mode (ie, with \fB-g\fR or \fB--global\fR appended to the command), it uninstalls the current package context as a global package. \fB--no-save\fR is ignored in this case.
.P
@@ -33,7 +33,7 @@ npm uninstall sax
.fi
.RE
.P
-\fBsax\fR will no longer be in your \fBpackage.json\fR, \fBnpm-shrinkwrap.json\fR, or \fBpackage-lock.json\fR files.
+\fBsax\fR will no longer be in your \fBpackage.json\fR or \fBpackage-lock.json\fR files.
.P
.RS 2
.nf
@@ -41,7 +41,7 @@ npm uninstall lodash --no-save
.fi
.RE
.P
-\fBlodash\fR will not be removed from your \fBpackage.json\fR, \fBnpm-shrinkwrap.json\fR, or \fBpackage-lock.json\fR files.
+\fBlodash\fR will not be removed from your \fBpackage.json\fR or \fBpackage-lock.json\fR files.
.SS "Configuration"
.SS "\fBsave\fR"
.RS 0
diff --git a/deps/npm/man/man1/npm-unpublish.1 b/deps/npm/man/man1/npm-unpublish.1
index 5bbb86e8c8f..f3c1b02fa77 100644
--- a/deps/npm/man/man1/npm-unpublish.1
+++ b/deps/npm/man/man1/npm-unpublish.1
@@ -1,4 +1,4 @@
-.TH "NPM-UNPUBLISH" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-UNPUBLISH" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-unpublish\fR - Remove a package from the registry
.SS "Synopsis"
@@ -129,8 +129,6 @@ npm help publish
.IP \(bu 4
npm help registry
.IP \(bu 4
-npm help adduser
-.IP \(bu 4
npm help owner
.IP \(bu 4
npm help login
diff --git a/deps/npm/man/man1/npm-unstar.1 b/deps/npm/man/man1/npm-unstar.1
deleted file mode 100644
index 0d0e2f2c9e6..00000000000
--- a/deps/npm/man/man1/npm-unstar.1
+++ /dev/null
@@ -1,70 +0,0 @@
-.TH "NPM-UNSTAR" "1" "August 2026" "NPM@11.19.1" ""
-.SH "NAME"
-\fBnpm-unstar\fR - Remove an item from your favorite packages
-.SS "Synopsis"
-.P
-.RS 2
-.nf
-npm unstar \[lB]<package-spec>...\[rB]
-.fi
-.RE
-.P
-Note: This command is unaware of workspaces.
-.SS "Description"
-.P
-"Unstarring" a package is the opposite of npm help star, it removes an item from your list of favorite packages.
-.SS "More"
-.P
-There's also these extra commands to help you manage your favorite packages:
-.SS "Star"
-.P
-You can "star" a package using npm help star
-.SS "Listing stars"
-.P
-You can see all your starred packages using npm help stars
-.SS "Configuration"
-.SS "\fBregistry\fR"
-.RS 0
-.IP \(bu 4
-Default: "https://registry.npmjs.org/"
-.IP \(bu 4
-Type: URL
-.RE 0
-
-.P
-The base URL of the npm registry.
-.SS "\fBunicode\fR"
-.RS 0
-.IP \(bu 4
-Default: false on windows, true on mac/unix systems with a unicode locale, as defined by the \fBLC_ALL\fR, \fBLC_CTYPE\fR, or \fBLANG\fR environment variables.
-.IP \(bu 4
-Type: Boolean
-.RE 0
-
-.P
-When set to true, npm uses unicode characters in the tree output. When false, it uses ascii characters instead of unicode glyphs.
-.SS "\fBotp\fR"
-.RS 0
-.IP \(bu 4
-Default: null
-.IP \(bu 4
-Type: null or String
-.RE 0
-
-.P
-This is a one-time password from a two-factor authenticator. It's needed when publishing or changing package permissions with \fBnpm access\fR.
-.P
-If not set, and a registry response fails with a challenge for a one-time password, npm will prompt on the command line for one.
-.SS "See Also"
-.RS 0
-.IP \(bu 4
-npm help star
-.IP \(bu 4
-npm help stars
-.IP \(bu 4
-npm help view
-.IP \(bu 4
-npm help whoami
-.IP \(bu 4
-npm help adduser
-.RE 0
diff --git a/deps/npm/man/man1/npm-update.1 b/deps/npm/man/man1/npm-update.1
index 4f5e015b20d..4e979a194e9 100644
--- a/deps/npm/man/man1/npm-update.1
+++ b/deps/npm/man/man1/npm-update.1
@@ -1,4 +1,4 @@
-.TH "NPM-UPDATE" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-UPDATE" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-update\fR - Update packages
.SS "Synopsis"
@@ -212,7 +212,7 @@ Type: "dev", "optional", or "peer" (can be set multiple times)
.P
Dependency types to omit from the installation tree on disk.
.P
-Note that these dependencies \fIare\fR still resolved and added to the \fBpackage-lock.json\fR or \fBnpm-shrinkwrap.json\fR file. They are just not physically installed on disk.
+Note that these dependencies \fIare\fR still resolved and added to the \fBpackage-lock.json\fR file. They are just not physically installed on disk.
.P
If a package type appears in both the \fB--include\fR and \fB--omit\fR lists, then it will be included.
.P
@@ -279,6 +279,8 @@ Type: Boolean
If true, npm does not run scripts specified in package.json files.
.P
Note that commands explicitly intended to run a particular script, such as \fBnpm start\fR, \fBnpm stop\fR, \fBnpm restart\fR, \fBnpm test\fR, and \fBnpm run\fR will still run their intended script if \fBignore-scripts\fR is set, but they will \fInot\fR run any pre- or post-scripts.
+.P
+Setting \fBignore-scripts\fR also disables \fB.npm-extension\fR execution, as if \fBignore-extension\fR were set.
.SS "\fBallow-scripts\fR"
.RS 0
.IP \(bu 4
@@ -293,6 +295,8 @@ Comma-separated list of packages whose install-time lifecycle scripts (\fBpreins
This setting is intended for one-off and global contexts: \fBnpm exec\fR, \fBnpx\fR, and \fBnpm install -g\fR, where no project \fBpackage.json\fR is involved. For team-wide policy in a project, use the \fBallowScripts\fR field in \fBpackage.json\fR (which also supports explicit denials), or configure it in \fB.npmrc\fR. Passing \fB--allow-scripts\fR on the command line during a project-scoped \fBnpm install\fR, \fBci\fR, \fBupdate\fR, or \fBrebuild\fR is an error.
.P
Each name is matched against a dependency's resolved identity, not against the package's self-reported name. \fB--ignore-scripts\fR and \fB--dangerously-allow-all-scripts\fR both override this setting.
+.P
+This value is not exported to the environment for child processes.
.SS "\fBstrict-allow-scripts\fR"
.RS 0
.IP \(bu 4
@@ -302,9 +306,9 @@ Type: Boolean
.RE 0
.P
-If \fBtrue\fR, turn the install-script policy from a warning into a hard error: any dependency with install scripts not covered by \fBallowScripts\fR will fail the install instead of running with a notice.
+If \fBtrue\fR, turn the install-script policy from a warning into a hard error: any dependency with install scripts that is not covered by \fBallowScripts\fR will fail the install instead of being blocked with a warning.
.P
-Dependencies explicitly denied with \fBfalse\fR in \fBallowScripts\fR are always silently skipped; this setting only affects unreviewed entries. \fB--ignore-scripts\fR and \fB--dangerously-allow-all-scripts\fR both override this setting.
+Dependencies explicitly denied with \fBfalse\fR in \fBallowScripts\fR are always silently skipped; this setting only affects unreviewed entries (packages with install scripts that are neither approved nor denied). \fB--ignore-scripts\fR and \fB--dangerously-allow-all-scripts\fR both override this setting.
.P
Optional dependencies that cannot be installed on the current platform or engine (a non-matching \fBos\fR, \fBcpu\fR, or \fBlibc\fR) are not flagged, because their install scripts never run.
.SS "\fBdangerously-allow-all-scripts\fR"
@@ -499,8 +503,6 @@ npm help install
.IP \(bu 4
npm help outdated
.IP \(bu 4
-npm help shrinkwrap
-.IP \(bu 4
npm help registry
.IP \(bu 4
npm help folders
diff --git a/deps/npm/man/man1/npm-version.1 b/deps/npm/man/man1/npm-version.1
index c15a0d19acf..8e3286aabe1 100644
--- a/deps/npm/man/man1/npm-version.1
+++ b/deps/npm/man/man1/npm-version.1
@@ -1,4 +1,4 @@
-.TH "NPM-VERSION" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-VERSION" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-version\fR - Bump a package version
.SS "Synopsis"
@@ -174,9 +174,11 @@ Type: Boolean
If true, npm does not run scripts specified in package.json files.
.P
Note that commands explicitly intended to run a particular script, such as \fBnpm start\fR, \fBnpm stop\fR, \fBnpm restart\fR, \fBnpm test\fR, and \fBnpm run\fR will still run their intended script if \fBignore-scripts\fR is set, but they will \fInot\fR run any pre- or post-scripts.
+.P
+Setting \fBignore-scripts\fR also disables \fB.npm-extension\fR execution, as if \fBignore-extension\fR were set.
.SS "Description"
.P
-Run this in a package directory to bump the version and write the new data back to \fBpackage.json\fR, \fBpackage-lock.json\fR, and, if present, \fBnpm-shrinkwrap.json\fR.
+Run this in a package directory to bump the version and write the new data back to \fBpackage.json\fR and \fBpackage-lock.json\fR.
.P
The \fBnewversion\fR argument should be a valid semver string, a valid second argument to \fBsemver.inc\fR \fI\(lahttps://github.com/npm/node-semver#functions\(ra\fR (one of \fBpatch\fR, \fBminor\fR, \fBmajor\fR, \fBprepatch\fR, \fBpreminor\fR, \fBpremajor\fR, \fBprerelease\fR), or \fBfrom-git\fR. In the second case, the existing version will be incremented by 1 in the specified field. \fBfrom-git\fR will try to read the latest git tag, and use that as the new npm version.
.P
diff --git a/deps/npm/man/man1/npm-view.1 b/deps/npm/man/man1/npm-view.1
index b9210c424cd..b49e0338bf7 100644
--- a/deps/npm/man/man1/npm-view.1
+++ b/deps/npm/man/man1/npm-view.1
@@ -1,4 +1,4 @@
-.TH "NPM-VIEW" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-VIEW" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-view\fR - View registry info
.SS "Synopsis"
@@ -262,7 +262,7 @@ This value is not exported to the environment for child processes.
.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 another command. If the field is an object, it will be output as a JavaScript object literal.
.P
-If the \fB--json\fR flag is given, the outputted fields will be JSON.
+If the \fB--json\fR flag is given, the outputted fields will be JSON. Scalar and object results are returned in an array, even if only a single version matches. When the output contains one array-valued result, that array is returned directly without an additional result wrapper. Multiple array-valued results remain separate items in the outer results array.
.P
If the version range matches multiple versions then each printed value will be prefixed with the version it applies to.
.P
diff --git a/deps/npm/man/man1/npm-whoami.1 b/deps/npm/man/man1/npm-whoami.1
index 5d44c35a7f4..b02182e3a90 100644
--- a/deps/npm/man/man1/npm-whoami.1
+++ b/deps/npm/man/man1/npm-whoami.1
@@ -1,4 +1,4 @@
-.TH "NPM-WHOAMI" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM-WHOAMI" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm-whoami\fR - Display npm username
.SS "Synopsis"
@@ -35,5 +35,5 @@ npm help config
.IP \(bu 4
npm help npmrc
.IP \(bu 4
-npm help adduser
+npm help login
.RE 0
diff --git a/deps/npm/man/man1/npm.1 b/deps/npm/man/man1/npm.1
index 25a9e19288c..7f1e9889f7f 100644
--- a/deps/npm/man/man1/npm.1
+++ b/deps/npm/man/man1/npm.1
@@ -1,4 +1,4 @@
-.TH "NPM" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPM" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpm\fR - javascript package manager
.SS "Synopsis"
@@ -12,7 +12,7 @@ npm
Note: This command is unaware of workspaces.
.SS "Version"
.P
-11.19.1
+12.1.0
.SS "Description"
.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 conflicts intelligently.
@@ -64,7 +64,7 @@ link: Links your current working code into Node's path, so that you don't have t
.IP \(bu 4
install: It's a good idea to install things if you don't need the symbolic link. Especially, installing other peoples code from the registry is done via npm help install
.IP \(bu 4
-adduser: Create an account or log in. When you do this, npm will store credentials in the user config file.
+login: Log in to the registry and store credentials. When you do this, npm will store credentials in the user config file.
.IP \(bu 4
publish: Use the npm help publish command to upload your code to the registry.
.RE 0
diff --git a/deps/npm/man/man1/npx.1 b/deps/npm/man/man1/npx.1
index 39fcb358f7c..b4feebbdd0d 100644
--- a/deps/npm/man/man1/npx.1
+++ b/deps/npm/man/man1/npx.1
@@ -1,4 +1,4 @@
-.TH "NPX" "1" "August 2026" "NPM@11.19.1" ""
+.TH "NPX" "1" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBnpx\fR - Run a command from a local or remote npm package
.SS "Synopsis"
diff --git a/deps/npm/man/man5/folders.5 b/deps/npm/man/man5/folders.5
index 7ec71429510..a29476d81c2 100644
--- a/deps/npm/man/man5/folders.5
+++ b/deps/npm/man/man5/folders.5
@@ -1,4 +1,4 @@
-.TH "FOLDERS" "5" "August 2026" "NPM@11.19.1" ""
+.TH "FOLDERS" "5" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBFolders\fR - Folder structures used by npm
.SS "Description"
diff --git a/deps/npm/man/man5/install.5 b/deps/npm/man/man5/install.5
index b54f427c5da..fc36a2fd531 100644
--- a/deps/npm/man/man5/install.5
+++ b/deps/npm/man/man5/install.5
@@ -1,4 +1,4 @@
-.TH "INSTALL" "5" "August 2026" "NPM@11.19.1" ""
+.TH "INSTALL" "5" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBInstall\fR - Download and install node and npm
.SS "Description"
diff --git a/deps/npm/man/man5/npm-extension.5 b/deps/npm/man/man5/npm-extension.5
new file mode 100644
index 00000000000..8d5c5cc3bbd
--- /dev/null
+++ b/deps/npm/man/man5/npm-extension.5
@@ -0,0 +1,97 @@
+.TH ".NPM-EXTENSION" "5" "September 2026" "NPM@12.1.0" ""
+.SH "NAME"
+\fB.npm-extension\fR - Imperative, root-owned manifest repairs
+.SS "Description"
+.P
+A root-owned \fB.npm-extension.mjs\fR or \fB.npm-extension.cjs\fR file lets a project imperatively repair the manifests of third-party dependencies before npm resolves the dependency tree. It exports a \fBtransformManifest(pkg, context)\fR function that receives a candidate dependency manifest and returns the effective manifest npm should use.
+.P
+\fB.npm-extension\fR is the imperative counterpart to the declarative \fB\[rs]fBpackageExtensions\[rs]fR\fR \fI\(la/configuring-npm/package-json#packageextensions\(ra\fR field, and runs in the same pre-resolution phase, \fBbefore\fR \fBpackageExtensions\fR. Prefer \fBpackageExtensions\fR for simple, data-only repairs; reach for \fB.npm-extension\fR when you need comments and links explaining a repair, conditional logic, repeated repairs expressed as code, deletion or range rewrites, stale-repair guards, or a policy location outside \fBpackage.json\fR.
+.SS "Example"
+.P
+.RS 2
+.nf
+// .npm-extension.mjs
+export function transformManifest (pkg, context) {
+ if (pkg.name === 'foo' && pkg.version.startsWith('1.')) {
+ pkg.dependencies = { ...pkg.dependencies, bar: '^2.0.0' }
+ context.log(`added bar to ${pkg.name}@${pkg.version}`)
+ }
+ return pkg
+}
+.fi
+.RE
+.P
+The \fB.cjs\fR form uses CommonJS exports instead:
+.P
+.RS 2
+.nf
+// .npm-extension.cjs
+module.exports = {
+ transformManifest (pkg, context) {
+ return pkg
+ },
+}
+.fi
+.RE
+.SS "The \fBtransformManifest\fR function"
+.P
+\fBtransformManifest(pkg, context)\fR receives a deeply isolated copy of a candidate dependency manifest. It may mutate and return that copy, or return a new manifest object. It \fBmust\fR return a manifest object synchronously; returning \fBnull\fR, \fBundefined\fR, a primitive, an array, or a promise fails the install.
+.P
+The \fBcontext\fR argument is intentionally small:
+.RS 0
+.IP \(bu 4
+\fBcontext.log(message)\fR writes an npm debug log message.
+.IP \(bu 4
+\fBcontext.root\fR is the absolute path to the project root.
+.IP \(bu 4
+\fBcontext.extensionPoint\fR is the string \fB"transformManifest"\fR.
+.RE 0
+
+.P
+npm provides no registry, fetch, lockfile, or extraction helpers. Keep the extension file self-contained or limited to Node builtins; npm does not guarantee that project dependencies are available when the file is loaded.
+.SS "Supported mutations"
+.P
+Only the four resolution-affecting fields may change:
+.RS 0
+.IP \(bu 4
+\fBdependencies\fR
+.IP \(bu 4
+\fBoptionalDependencies\fR
+.IP \(bu 4
+\fBpeerDependencies\fR
+.IP \(bu 4
+\fBpeerDependenciesMeta\fR
+.RE 0
+
+.P
+Within those fields you may add, replace, or delete entries. Changing any other field (such as \fBscripts\fR, \fBbin\fR, \fBengines\fR, \fBos\fR, \fBcpu\fR, \fBexports\fR, or \fBmain\fR) is rejected, and the install fails with an error naming \fB.npm-extension\fR and the package being processed. The package tarball and the installed \fBnode_modules/<pkg>/package.json\fR are never rewritten.
+.SS "Discovery and \fBextension-file\fR"
+.P
+npm looks for a single \fB.npm-extension.mjs\fR or \fB.npm-extension.cjs\fR at the project root (the workspace root in a workspace project). Having both files present is an error. A \fB.npm-extension\fR file in a dependency or in a non-root workspace is ignored; a non-root workspace file produces a warning.
+.P
+The \fB\[rs]fBextension-file\[rs]fR\fR \fI\(la/using-npm/config#extension-file\(ra\fR config selects a different project-local file. It must resolve inside the project root and use a \fB.mjs\fR or \fB.cjs\fR extension, and it is honored only from project config or the command line \[em] never from user, global, or builtin config.
+.SS "Interaction with \fBpackageExtensions\fR and \fBoverrides\fR"
+.P
+When both are present, \fBtransformManifest\fR runs first and \fBpackageExtensions\fR is applied to its output. Avoid targeting the same package with both unless you intend to rely on that ordering. \fBoverrides\fR still controls the final resolution target of any edge, including edges created by \fBtransformManifest\fR.
+.SS "Lockfile and \fBnpm ci\fR"
+.P
+A lockfile influenced by \fB.npm-extension\fR records an \fBnpmExtensionHash\fR (a digest of the selected file's bytes and module format) on its root entry, and minimal \fBnpmExtensionApplied\fR provenance on each affected package entry. Extension state requires \fBlockfileVersion: 4\fR.
+.P
+Changing the file's contents makes \fBnpm install\fR re-resolve the affected packages. \fBnpm ci\fR does \fBnot\fR import or execute \fB.npm-extension\fR; it verifies the recorded hash against the file and reifies the locked graph, failing if the file and lockfile disagree (or if one has extension state and the other does not).
+.P
+The hash proves only that the install uses the same extension file bytes that generated the lockfile. It does not make arbitrary JavaScript deterministic: extension output that depends on environment variables, the network, the clock, or files imported by the extension can still produce non-reproducible installs. Treat \fB.npm-extension\fR as trusted, deterministic project code, and only enable it in repositories you trust.
+.SS "Disabling"
+.P
+Set \fB\[rs]fBignore-extension\[rs]fR\fR \fI\(la/using-npm/config#ignore-extension\(ra\fR to skip importing and executing \fB.npm-extension\fR. \fB\[rs]fBignore-scripts\[rs]fR\fR \fI\(la/using-npm/config#ignore-scripts\(ra\fR implies \fBignore-extension\fR, since both disable root-owned install-time code. \fBnpm ci\fR still verifies the file hash even when execution is disabled.
+.SS "Publishing"
+.P
+\fB.npm-extension.mjs\fR and \fB.npm-extension.cjs\fR are project configuration, not package contents. npm excludes the root file from the package tarball produced by \fBnpm pack\fR and \fBnpm publish\fR, even when the package's \fBfiles\fR list would include it, so a public package can keep \fB.npm-extension\fR in its repository for local use without publishing it.
+.SS "See also"
+.RS 0
+.IP \(bu 4
+\fBpackage.json \[rs]fBpackageExtensions\[rs]fR\fR \fI\(la/configuring-npm/package-json#packageextensions\(ra\fR
+.IP \(bu 4
+\fBpackage-lock.json\fR \fI\(la/configuring-npm/package-lock-json\(ra\fR
+.IP \(bu 4
+npm help config
+.RE 0
diff --git a/deps/npm/man/man5/npm-global.5 b/deps/npm/man/man5/npm-global.5
index 7ec71429510..a29476d81c2 100644
--- a/deps/npm/man/man5/npm-global.5
+++ b/deps/npm/man/man5/npm-global.5
@@ -1,4 +1,4 @@
-.TH "FOLDERS" "5" "August 2026" "NPM@11.19.1" ""
+.TH "FOLDERS" "5" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBFolders\fR - Folder structures used by npm
.SS "Description"
diff --git a/deps/npm/man/man5/npm-json.5 b/deps/npm/man/man5/npm-json.5
index 4a79f278885..89640b5abd9 100644
--- a/deps/npm/man/man5/npm-json.5
+++ b/deps/npm/man/man5/npm-json.5
@@ -1,4 +1,4 @@
-.TH "PACKAGE.JSON" "5" "August 2026" "NPM@11.19.1" ""
+.TH "PACKAGE.JSON" "5" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBpackage.json\fR - Specifics of npm's package.json handling
.SS "Description"
@@ -324,7 +324,7 @@ Some files are always ignored by default:
.IP \(bu 4
\fBnpm-debug.log\fR
.IP \(bu 4
-\fBpackage-lock.json\fR (use \fB\[rs]fBnpm-shrinkwrap.json\[rs]fR\fR \fI\(la/configuring-npm/npm-shrinkwrap-json\(ra\fR if you wish it to be published)
+\fBpackage-lock.json\fR
.IP \(bu 4
\fBpnpm-lock.yaml\fR
.IP \(bu 4
@@ -426,10 +426,15 @@ Note that you can also set the executable files using \fI(directories.bin)\fR.
.P
See \fBfolders\fR \fI\(la/configuring-npm/folders#executables\(ra\fR for more info on executables.
.SS "man"
+.RS 0
.P
-Specify either a single file or an array of filenames to put in place for the \fBman\fR program to find.
+\fBNote:\fR As of npm v12, man pages are no longer registered with the system \fBman\fR program. This field is retained for backward compatibility with package metadata and tools that consume it, but \fBman <pkgname>\fR will not work after a global install. Use \fBnpm help <pkgname>\fR instead where supported.
+.RE 0
+
.P
-If only a single file is provided, then it's installed such that it is the result from \fBman <pkgname>\fR, regardless of its actual filename. For example:
+Specify either a single file or an array of filenames to include as man pages.
+.P
+If only a single file is provided, then it corresponds to \fBman <pkgname>\fR, regardless of its actual filename. For example:
.P
.RS 2
.nf
@@ -443,7 +448,7 @@ If only a single file is provided, then it's installed such that it is the resul
.fi
.RE
.P
-would link the \fB./man/doc.1\fR file in such that it is the target for \fBman foo\fR
+would associate the \fB./man/doc.1\fR file such that it is the target for \fBman foo\fR
.P
If the filename doesn't start with the package name, then it's prefixed. So, this:
.P
@@ -462,9 +467,9 @@ If the filename doesn't start with the package name, then it's prefixed. So, thi
.fi
.RE
.P
-will create files to do \fBman foo\fR and \fBman foo-bar\fR.
+will correspond to \fBman foo\fR and \fBman foo-bar\fR.
.P
-Man files must end with a number, and optionally a \fB.gz\fR suffix if they are compressed. The number dictates which man section the file is installed into.
+Man files must end with a number, and optionally a \fB.gz\fR suffix if they are compressed. The number dictates which man section the file belongs to.
.P
.RS 2
.nf
@@ -494,7 +499,7 @@ If you specify a \fBbin\fR directory in \fBdirectories.bin\fR, all the files in
Because of the way the \fBbin\fR directive works, specifying both a \fBbin\fR path and setting \fBdirectories.bin\fR is an error. If you want to specify individual files, use \fBbin\fR, and for all the files in an existing \fBbin\fR directory, use \fBdirectories.bin\fR.
.SS "directories.man"
.P
-A folder that is full of man pages. Sugar to generate a "man" array by walking the folder.
+A folder that is full of man pages. Sugar to generate a "man" array by walking the folder. See the note on \fB\[rs]fBman\[rs]fR\fR \fI(man)\fR above: as of npm v12, these are no longer installed into the system \fBman\fR path.
.SS "repository"
.P
Specify the place where your code lives. This is helpful for people who want to contribute. If the git repo is on GitHub, then the \fBnpm repo\fR command will be able to find you.
@@ -879,6 +884,18 @@ Alternatively, \fB"bundleDependencies"\fR can be defined as a boolean value. A v
.P
If a dependency can be used, but you would like npm to proceed if it cannot be found or fails to install, then you may put it in the \fBoptionalDependencies\fR object. This is a map of package name to version or URL, just like the \fBdependencies\fR object. The difference is that build failures do not cause installation to fail. Running \fBnpm install --omit=optional\fR will prevent these dependencies from being installed.
.P
+For example:
+.P
+.RS 2
+.nf
+{
+ "optionalDependencies": {
+ "@npm/foo": "^1.0.0"
+ }
+}
+.fi
+.RE
+.P
It is still your program's responsibility to handle the lack of the dependency. For example, something like this:
.P
.RS 2
@@ -908,7 +925,7 @@ If you need to make specific changes to dependencies of your dependencies, for e
.P
Overrides provide a way to replace a package in your dependency tree with another version, or another package entirely. These changes can be scoped as specific or as vague as desired.
.P
-Overrides are only considered in the root \fBpackage.json\fR file for a project. Overrides in installed dependencies (including npm help workspaces) are not considered in dependency tree resolution. Published packages may dictate their resolutions by pinning dependencies or using an \fB\[rs]fBnpm-shrinkwrap.json\[rs]fR\fR \fI\(la/configuring-npm/npm-shrinkwrap-json\(ra\fR file.
+Overrides are only considered in the root \fBpackage.json\fR file for a project. Overrides in installed dependencies (including npm help workspaces) are not considered in dependency tree resolution. Published packages may dictate their resolutions by pinning dependencies or using \fB\[rs]fBbundleDependencies\[rs]fR\fR \fI(bundleDependencies)\fR.
.P
To make sure the package \fB@npm/foo\fR is always installed as version \fB1.0.0\fR no matter what version your dependencies rely on:
.P
@@ -1069,6 +1086,72 @@ These replacement methods work for both top-level overrides and nested overrides
}
.fi
.RE
+.SS "packageExtensions"
+.P
+\fBpackageExtensions\fR lets a project apply small, declarative repairs to the manifests of third-party dependencies before npm resolves the dependency tree. Use it to add a missing \fBdependencies\fR, \fBoptionalDependencies\fR, or \fBpeerDependencies\fR entry, or to correct \fBpeerDependencies\fR and \fBpeerDependenciesMeta\fR, while you wait for the upstream package to publish a fix.
+.P
+This is especially useful with \fB\[rs]fBinstall-strategy=linked\[rs]fR\fR \fI\(la/using-npm/config#install-strategy\(ra\fR, where dependencies are fully isolated and a package only sees what it actually declared. A package that worked under a hoisted layout because a dependency happened to be hoisted above it can fail under \fBlinked\fR; \fBpackageExtensions\fR records the missing edge as explicit, reviewable, root-owned policy.
+.P
+\fBpackageExtensions\fR complements \fB\[rs]fBoverrides\[rs]fR\fR \fI(overrides)\fR: \fBoverrides\fR changes what an existing dependency edge resolves to, while \fBpackageExtensions\fR adds or corrects the dependency metadata that creates the edge in the first place. For changing the resolved version of a dependency that is already declared, use \fBoverrides\fR.
+.P
+Like \fBoverrides\fR, \fBpackageExtensions\fR is only honored in the root \fBpackage.json\fR of a project (the workspace root in a workspace). The field in installed dependencies and in non-root workspace packages is ignored. Because it is root-only project policy, npm refuses to publish a non-private package that contains \fBpackageExtensions\fR; it remains available to private packages and unpublished local projects.
+.P
+Each key is a package selector: a package name with an optional semver range.
+.P
+.RS 2
+.nf
+{
+ "packageExtensions": {
+ "broken-package@1": {
+ "dependencies": {
+ "missing-runtime-dep": "^2.0.0"
+ }
+ },
+ "typescript-plugin@4.3.0": {
+ "peerDependencies": {
+ "typescript": ">=5"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "@scope/uses-types@2": {
+ "dependencies": {
+ "@types/node": "^22.0.0"
+ }
+ }
+ }
+}
+.fi
+.RE
+.RS 0
+.IP \(bu 4
+\fB"foo"\fR matches all versions of \fBfoo\fR.
+.IP \(bu 4
+\fB"foo@1"\fR matches versions satisfying \fB1\fR.
+.IP \(bu 4
+\fB"@scope/foo@^2.3.0"\fR matches versions satisfying \fB^2.3.0\fR.
+.RE 0
+
+.P
+Selectors match a candidate package's own \fBname\fR and \fBversion\fR. They do not accept dist-tags, git, file, directory, URL, or \fBnpm:\fR alias specs. For aliases, the selector matches the underlying package name. At most one selector may match a given package; overlapping selectors that both match the same package fail the install.
+.P
+Only \fBdependencies\fR, \fBoptionalDependencies\fR, \fBpeerDependencies\fR, and \fBpeerDependenciesMeta\fR may be extended. The merge rules are:
+.RS 0
+.IP \(bu 4
+\fBdependencies\fR and \fBoptionalDependencies\fR entries add a missing dependency only. Adding a name that the package already declares in either field is an error; use \fBoverrides\fR to change a version.
+.IP \(bu 4
+\fBpeerDependencies\fR entries are merged by name, replacing an existing range.
+.IP \(bu 4
+\fBpeerDependenciesMeta\fR entries are merged by name and then by key, so you can add \fBoptional: true\fR without dropping other metadata. Every \fBpeerDependenciesMeta\fR entry must correspond to a \fBpeerDependencies\fR entry.
+.RE 0
+
+.P
+Deletion is not supported; a \fBnull\fR, \fBfalse\fR, or \fB"-"\fR value is an error.
+.P
+\fBpackageExtensions\fR does not rewrite the installed package's \fBpackage.json\fR on disk and does not modify \fBbundleDependencies\fR. Affected packages are recorded in \fBpackage-lock.json\fR and surfaced by npm help explain and npm help ls, so each repair is easy to audit and to remove once upstream is fixed.
.SS "engines"
.P
You can specify the version of node that your stuff works on:
diff --git a/deps/npm/man/man5/npm-shrinkwrap-json.5 b/deps/npm/man/man5/npm-shrinkwrap-json.5
deleted file mode 100644
index 1af7bf467c0..00000000000
--- a/deps/npm/man/man5/npm-shrinkwrap-json.5
+++ /dev/null
@@ -1,23 +0,0 @@
-.TH "NPM-SHRINKWRAP.JSON" "5" "August 2026" "NPM@11.19.1" ""
-.SH "NAME"
-\fBnpm-shrinkwrap.json\fR - A publishable lockfile
-.SS "Description"
-.P
-\fBnpm-shrinkwrap.json\fR is a file created by npm help shrinkwrap. It is identical to \fBpackage-lock.json\fR, with one major caveat: Unlike \fBpackage-lock.json\fR, \fBnpm-shrinkwrap.json\fR may be included when publishing a package.
-.P
-The recommended use-case for \fBnpm-shrinkwrap.json\fR is applications deployed through the publishing process on the registry: for example, daemons and command-line tools intended as global installs or \fBdevDependencies\fR. It's strongly discouraged for library authors to publish this file, since that would prevent end users from having control over transitive dependency updates.
-.P
-If both \fBpackage-lock.json\fR and \fBnpm-shrinkwrap.json\fR are present in a package root, \fBnpm-shrinkwrap.json\fR will be preferred over the \fBpackage-lock.json\fR file.
-.P
-For full details and description of the \fBnpm-shrinkwrap.json\fR file format, refer to the manual page for \fBpackage-lock.json\fR \fI\(la/configuring-npm/package-lock-json\(ra\fR.
-.SS "See also"
-.RS 0
-.IP \(bu 4
-npm help shrinkwrap
-.IP \(bu 4
-\fBpackage-lock.json\fR \fI\(la/configuring-npm/package-lock-json\(ra\fR
-.IP \(bu 4
-\fBpackage.json\fR \fI\(la/configuring-npm/package-json\(ra\fR
-.IP \(bu 4
-npm help install
-.RE 0
diff --git a/deps/npm/man/man5/npmrc.5 b/deps/npm/man/man5/npmrc.5
index 9d236112608..109edb999c2 100644
--- a/deps/npm/man/man5/npmrc.5
+++ b/deps/npm/man/man5/npmrc.5
@@ -1,4 +1,4 @@
-.TH ".NPMRC" "5" "August 2026" "NPM@11.19.1" ""
+.TH ".NPMRC" "5" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fB.npmrc\fR - The npm config files
.SS "Description"
diff --git a/deps/npm/man/man5/package-json.5 b/deps/npm/man/man5/package-json.5
index 4a79f278885..89640b5abd9 100644
--- a/deps/npm/man/man5/package-json.5
+++ b/deps/npm/man/man5/package-json.5
@@ -1,4 +1,4 @@
-.TH "PACKAGE.JSON" "5" "August 2026" "NPM@11.19.1" ""
+.TH "PACKAGE.JSON" "5" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBpackage.json\fR - Specifics of npm's package.json handling
.SS "Description"
@@ -324,7 +324,7 @@ Some files are always ignored by default:
.IP \(bu 4
\fBnpm-debug.log\fR
.IP \(bu 4
-\fBpackage-lock.json\fR (use \fB\[rs]fBnpm-shrinkwrap.json\[rs]fR\fR \fI\(la/configuring-npm/npm-shrinkwrap-json\(ra\fR if you wish it to be published)
+\fBpackage-lock.json\fR
.IP \(bu 4
\fBpnpm-lock.yaml\fR
.IP \(bu 4
@@ -426,10 +426,15 @@ Note that you can also set the executable files using \fI(directories.bin)\fR.
.P
See \fBfolders\fR \fI\(la/configuring-npm/folders#executables\(ra\fR for more info on executables.
.SS "man"
+.RS 0
.P
-Specify either a single file or an array of filenames to put in place for the \fBman\fR program to find.
+\fBNote:\fR As of npm v12, man pages are no longer registered with the system \fBman\fR program. This field is retained for backward compatibility with package metadata and tools that consume it, but \fBman <pkgname>\fR will not work after a global install. Use \fBnpm help <pkgname>\fR instead where supported.
+.RE 0
+
.P
-If only a single file is provided, then it's installed such that it is the result from \fBman <pkgname>\fR, regardless of its actual filename. For example:
+Specify either a single file or an array of filenames to include as man pages.
+.P
+If only a single file is provided, then it corresponds to \fBman <pkgname>\fR, regardless of its actual filename. For example:
.P
.RS 2
.nf
@@ -443,7 +448,7 @@ If only a single file is provided, then it's installed such that it is the resul
.fi
.RE
.P
-would link the \fB./man/doc.1\fR file in such that it is the target for \fBman foo\fR
+would associate the \fB./man/doc.1\fR file such that it is the target for \fBman foo\fR
.P
If the filename doesn't start with the package name, then it's prefixed. So, this:
.P
@@ -462,9 +467,9 @@ If the filename doesn't start with the package name, then it's prefixed. So, thi
.fi
.RE
.P
-will create files to do \fBman foo\fR and \fBman foo-bar\fR.
+will correspond to \fBman foo\fR and \fBman foo-bar\fR.
.P
-Man files must end with a number, and optionally a \fB.gz\fR suffix if they are compressed. The number dictates which man section the file is installed into.
+Man files must end with a number, and optionally a \fB.gz\fR suffix if they are compressed. The number dictates which man section the file belongs to.
.P
.RS 2
.nf
@@ -494,7 +499,7 @@ If you specify a \fBbin\fR directory in \fBdirectories.bin\fR, all the files in
Because of the way the \fBbin\fR directive works, specifying both a \fBbin\fR path and setting \fBdirectories.bin\fR is an error. If you want to specify individual files, use \fBbin\fR, and for all the files in an existing \fBbin\fR directory, use \fBdirectories.bin\fR.
.SS "directories.man"
.P
-A folder that is full of man pages. Sugar to generate a "man" array by walking the folder.
+A folder that is full of man pages. Sugar to generate a "man" array by walking the folder. See the note on \fB\[rs]fBman\[rs]fR\fR \fI(man)\fR above: as of npm v12, these are no longer installed into the system \fBman\fR path.
.SS "repository"
.P
Specify the place where your code lives. This is helpful for people who want to contribute. If the git repo is on GitHub, then the \fBnpm repo\fR command will be able to find you.
@@ -879,6 +884,18 @@ Alternatively, \fB"bundleDependencies"\fR can be defined as a boolean value. A v
.P
If a dependency can be used, but you would like npm to proceed if it cannot be found or fails to install, then you may put it in the \fBoptionalDependencies\fR object. This is a map of package name to version or URL, just like the \fBdependencies\fR object. The difference is that build failures do not cause installation to fail. Running \fBnpm install --omit=optional\fR will prevent these dependencies from being installed.
.P
+For example:
+.P
+.RS 2
+.nf
+{
+ "optionalDependencies": {
+ "@npm/foo": "^1.0.0"
+ }
+}
+.fi
+.RE
+.P
It is still your program's responsibility to handle the lack of the dependency. For example, something like this:
.P
.RS 2
@@ -908,7 +925,7 @@ If you need to make specific changes to dependencies of your dependencies, for e
.P
Overrides provide a way to replace a package in your dependency tree with another version, or another package entirely. These changes can be scoped as specific or as vague as desired.
.P
-Overrides are only considered in the root \fBpackage.json\fR file for a project. Overrides in installed dependencies (including npm help workspaces) are not considered in dependency tree resolution. Published packages may dictate their resolutions by pinning dependencies or using an \fB\[rs]fBnpm-shrinkwrap.json\[rs]fR\fR \fI\(la/configuring-npm/npm-shrinkwrap-json\(ra\fR file.
+Overrides are only considered in the root \fBpackage.json\fR file for a project. Overrides in installed dependencies (including npm help workspaces) are not considered in dependency tree resolution. Published packages may dictate their resolutions by pinning dependencies or using \fB\[rs]fBbundleDependencies\[rs]fR\fR \fI(bundleDependencies)\fR.
.P
To make sure the package \fB@npm/foo\fR is always installed as version \fB1.0.0\fR no matter what version your dependencies rely on:
.P
@@ -1069,6 +1086,72 @@ These replacement methods work for both top-level overrides and nested overrides
}
.fi
.RE
+.SS "packageExtensions"
+.P
+\fBpackageExtensions\fR lets a project apply small, declarative repairs to the manifests of third-party dependencies before npm resolves the dependency tree. Use it to add a missing \fBdependencies\fR, \fBoptionalDependencies\fR, or \fBpeerDependencies\fR entry, or to correct \fBpeerDependencies\fR and \fBpeerDependenciesMeta\fR, while you wait for the upstream package to publish a fix.
+.P
+This is especially useful with \fB\[rs]fBinstall-strategy=linked\[rs]fR\fR \fI\(la/using-npm/config#install-strategy\(ra\fR, where dependencies are fully isolated and a package only sees what it actually declared. A package that worked under a hoisted layout because a dependency happened to be hoisted above it can fail under \fBlinked\fR; \fBpackageExtensions\fR records the missing edge as explicit, reviewable, root-owned policy.
+.P
+\fBpackageExtensions\fR complements \fB\[rs]fBoverrides\[rs]fR\fR \fI(overrides)\fR: \fBoverrides\fR changes what an existing dependency edge resolves to, while \fBpackageExtensions\fR adds or corrects the dependency metadata that creates the edge in the first place. For changing the resolved version of a dependency that is already declared, use \fBoverrides\fR.
+.P
+Like \fBoverrides\fR, \fBpackageExtensions\fR is only honored in the root \fBpackage.json\fR of a project (the workspace root in a workspace). The field in installed dependencies and in non-root workspace packages is ignored. Because it is root-only project policy, npm refuses to publish a non-private package that contains \fBpackageExtensions\fR; it remains available to private packages and unpublished local projects.
+.P
+Each key is a package selector: a package name with an optional semver range.
+.P
+.RS 2
+.nf
+{
+ "packageExtensions": {
+ "broken-package@1": {
+ "dependencies": {
+ "missing-runtime-dep": "^2.0.0"
+ }
+ },
+ "typescript-plugin@4.3.0": {
+ "peerDependencies": {
+ "typescript": ">=5"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "@scope/uses-types@2": {
+ "dependencies": {
+ "@types/node": "^22.0.0"
+ }
+ }
+ }
+}
+.fi
+.RE
+.RS 0
+.IP \(bu 4
+\fB"foo"\fR matches all versions of \fBfoo\fR.
+.IP \(bu 4
+\fB"foo@1"\fR matches versions satisfying \fB1\fR.
+.IP \(bu 4
+\fB"@scope/foo@^2.3.0"\fR matches versions satisfying \fB^2.3.0\fR.
+.RE 0
+
+.P
+Selectors match a candidate package's own \fBname\fR and \fBversion\fR. They do not accept dist-tags, git, file, directory, URL, or \fBnpm:\fR alias specs. For aliases, the selector matches the underlying package name. At most one selector may match a given package; overlapping selectors that both match the same package fail the install.
+.P
+Only \fBdependencies\fR, \fBoptionalDependencies\fR, \fBpeerDependencies\fR, and \fBpeerDependenciesMeta\fR may be extended. The merge rules are:
+.RS 0
+.IP \(bu 4
+\fBdependencies\fR and \fBoptionalDependencies\fR entries add a missing dependency only. Adding a name that the package already declares in either field is an error; use \fBoverrides\fR to change a version.
+.IP \(bu 4
+\fBpeerDependencies\fR entries are merged by name, replacing an existing range.
+.IP \(bu 4
+\fBpeerDependenciesMeta\fR entries are merged by name and then by key, so you can add \fBoptional: true\fR without dropping other metadata. Every \fBpeerDependenciesMeta\fR entry must correspond to a \fBpeerDependencies\fR entry.
+.RE 0
+
+.P
+Deletion is not supported; a \fBnull\fR, \fBfalse\fR, or \fB"-"\fR value is an error.
+.P
+\fBpackageExtensions\fR does not rewrite the installed package's \fBpackage.json\fR on disk and does not modify \fBbundleDependencies\fR. Affected packages are recorded in \fBpackage-lock.json\fR and surfaced by npm help explain and npm help ls, so each repair is easy to audit and to remove once upstream is fixed.
.SS "engines"
.P
You can specify the version of node that your stuff works on:
diff --git a/deps/npm/man/man5/package-lock-json.5 b/deps/npm/man/man5/package-lock-json.5
index ace3d4d6959..602e42bcebe 100644
--- a/deps/npm/man/man5/package-lock-json.5
+++ b/deps/npm/man/man5/package-lock-json.5
@@ -1,4 +1,4 @@
-.TH "PACKAGE-LOCK.JSON" "5" "August 2026" "NPM@11.19.1" ""
+.TH "PACKAGE-LOCK.JSON" "5" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBpackage-lock.json\fR - A manifestation of the manifest
.SS "Description"
@@ -21,15 +21,9 @@ As of npm v7, lockfiles include enough information to gain a complete picture of
.P
When \fBnpm\fR creates or updates \fBpackage-lock.json\fR, it will infer line endings and indentation from \fBpackage.json\fR so that the formatting of both files matches.
-.SS "\fBpackage-lock.json\fR vs \fBnpm-shrinkwrap.json\fR"
+.SS "\fBnpm-shrinkwrap.json\fR"
.P
-Both of these files have the same format, and perform similar functions in the root of a project.
-.P
-The difference is that \fBpackage-lock.json\fR cannot be published, and it will be ignored if found in any place other than the root project.
-.P
-In contrast, \fBnpm-shrinkwrap.json\fR \fI\(la/configuring-npm/npm-shrinkwrap-json\(ra\fR allows publication, and defines the dependency tree from the point encountered. This is not recommended unless deploying a CLI tool or otherwise using the publication process for producing production packages.
-.P
-If both \fBpackage-lock.json\fR and \fBnpm-shrinkwrap.json\fR are present in the root of a project, \fBnpm-shrinkwrap.json\fR will take precedence and \fBpackage-lock.json\fR will be ignored.
+As of npm v12, \fBnpm-shrinkwrap.json\fR is no longer read or written by npm. Projects that previously committed \fBnpm-shrinkwrap.json\fR should rename it to \fBpackage-lock.json\fR; the file format is identical. When npm v12 encounters a dependency that ships an \fBnpm-shrinkwrap.json\fR inside its tarball, the file is ignored \[em] publishers who need to ship a locked tree should use \fB\[rs]fBbundleDependencies\[rs]fR\fR \fI\(la/configuring-npm/package-json#bundledependencies\(ra\fR instead.
.SS "Hidden Lockfiles"
.P
In order to avoid processing the \fBnode_modules\fR folder repeatedly, npm as of v7 uses a "hidden" lockfile present in \fBnode_modules/.package-lock.json\fR. This contains information about the tree, and is used in lieu of reading the entire \fBnode_modules\fR hierarchy provided that the following conditions are met:
@@ -65,7 +59,7 @@ An integer version, starting at \fB1\fR with the version number of this document
Note that the file format changed significantly in npm v7 to track information that would have otherwise required looking in \fBnode_modules\fR or the npm registry. Lockfiles generated by npm v7 will contain \fBlockfileVersion: 2\fR.
.RS 0
.IP \(bu 4
-No version provided: an "ancient" shrinkwrap file from a version of npm prior to npm v5.
+No version provided: an "ancient" lockfile from a version of npm prior to npm v5.
.IP \(bu 4
\fB1\fR: The lockfile version used by npm v5 and v6.
.IP \(bu 4
@@ -99,8 +93,6 @@ inBundle: A flag to indicate that the package is a bundled dependency.
.IP \(bu 4
hasInstallScript: A flag to indicate that the package has a \fBpreinstall\fR, \fBinstall\fR, or \fBpostinstall\fR script.
.IP \(bu 4
-hasShrinkwrap: A flag to indicate that the package has an \fBnpm-shrinkwrap.json\fR file.
-.IP \(bu 4
bin, license, engines, dependencies, optionalDependencies: fields from \fBpackage.json\fR
.IP \(bu 4
os: An array of operating systems this package is compatible with, as specified in \fBpackage.json\fR. This field is included when the package specifies OS restrictions.
@@ -156,10 +148,6 @@ dependencies: The dependencies of this dependency, exactly as at the top level.
.SS "See also"
.RS 0
.IP \(bu 4
-npm help shrinkwrap
-.IP \(bu 4
-\fBnpm-shrinkwrap.json\fR \fI\(la/configuring-npm/npm-shrinkwrap-json\(ra\fR
-.IP \(bu 4
\fBpackage.json\fR \fI\(la/configuring-npm/package-json\(ra\fR
.IP \(bu 4
npm help install
diff --git a/deps/npm/man/man7/config.7 b/deps/npm/man/man7/config.7
index 684663e3375..424475b7a0c 100644
--- a/deps/npm/man/man7/config.7
+++ b/deps/npm/man/man7/config.7
@@ -1,4 +1,4 @@
-.TH "CONFIG" "7" "August 2026" "NPM@11.19.1" ""
+.TH "CONFIG" "7" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBConfig\fR - About npm configuration
.SS "Description"
@@ -223,7 +223,7 @@ Limits the ability for npm to install dependencies from tarball files. That is,
.SS "\fBallow-git\fR"
.RS 0
.IP \(bu 4
-Default: "all"
+Default: "none"
.IP \(bu 4
Type: "all", "none", or "root"
.RE 0
@@ -231,11 +231,13 @@ Type: "all", "none", or "root"
.P
Limits the ability for npm to fetch dependencies from git references. That is, dependencies that point to a git repo instead of a version or semver range. Please note that this could leave your tree incomplete and some packages may not function as intended or designed. Changing this setting will not remove dependencies that are already installed.
.P
+As of npm 12 the default is \fBnone\fR. Git dependencies run \fBgit\fR against a remote repo and may install configuration the project does not control. Opt in explicitly per project (in \fB.npmrc\fR) or per command (on the CLI) when you need git deps.
+.P
\fBall\fR allows any git dependencies to be fetched and installed. \fBnone\fR prevents any git dependencies from being fetched and installed. \fBroot\fR only allows git dependencies defined in your project's package.json to be fetched and installed. Also allows git dependencies to be fetched for other commands like \fBnpm view\fR
.SS "\fBallow-remote\fR"
.RS 0
.IP \(bu 4
-Default: "all"
+Default: "none"
.IP \(bu 4
Type: "all", "none", or "root"
.RE 0
@@ -243,6 +245,8 @@ Type: "all", "none", or "root"
.P
Limits the ability for npm to fetch dependencies from urls. That is, dependencies that point to a tarball url instead of a version or semver range. Please note that this could leave your tree incomplete and some packages may not function as intended or designed. Changing this setting will not remove dependencies that are already installed.
.P
+As of npm 12 the default is \fBnone\fR. Tarballs that share a hostname with the configured registry (the typical case for the npm registry, GitHub Packages, and most private registries) are still installed normally. If your registry serves tarballs from a different host, set \fBreplace-registry-host\fR or override this setting. Opt in explicitly per project (in \fB.npmrc\fR) or per command (on the CLI) when you intentionally install from a URL.
+.P
\fBall\fR allows any url to be installed. \fBnone\fR prevents any url from being installed. \fBroot\fR only allows urls defined in your project's package.json to be installed. Also allows url dependencies to be used for other commands like \fBnpm view\fR
.SS "\fBallow-same-version\fR"
.RS 0
@@ -268,6 +272,8 @@ Comma-separated list of packages whose install-time lifecycle scripts (\fBpreins
This setting is intended for one-off and global contexts: \fBnpm exec\fR, \fBnpx\fR, and \fBnpm install -g\fR, where no project \fBpackage.json\fR is involved. For team-wide policy in a project, use the \fBallowScripts\fR field in \fBpackage.json\fR (which also supports explicit denials), or configure it in \fB.npmrc\fR. Passing \fB--allow-scripts\fR on the command line during a project-scoped \fBnpm install\fR, \fBci\fR, \fBupdate\fR, or \fBrebuild\fR is an error.
.P
Each name is matched against a dependency's resolved identity, not against the package's self-reported name. \fB--ignore-scripts\fR and \fB--dangerously-allow-all-scripts\fR both override this setting.
+.P
+This value is not exported to the environment for child processes.
.SS "\fBallow-scripts-pending\fR"
.RS 0
.IP \(bu 4
@@ -288,6 +294,18 @@ Type: Boolean
.P
Write pinned (\fBpkg@version\fR) entries when approving install scripts. Set to \fBfalse\fR to write name-only entries that allow any version. Has no effect on \fBnpm deny-scripts\fR, which always writes name-only entries regardless of this setting.
+.SS "\fBallow-unused-patches\fR"
+.RS 0
+.IP \(bu 4
+Default: false
+.IP \(bu 4
+Type: Boolean
+.RE 0
+
+.P
+Install even when a registered patch in \fBpatchedDependencies\fR matches no installed package. Does not silence patch apply failures.
+.P
+This flag is only honored when passed on the command line; it is ignored in \fB.npmrc\fR and environment variables, and rejected by \fBnpm ci\fR.
.SS "\fBaudit\fR"
.RS 0
.IP \(bu 4
@@ -604,6 +622,16 @@ Type: Boolean
Indicates that you don't want npm to make any changes and that it should only report what it would have done. This can be passed into any of the commands that modify your local installation, eg, \fBinstall\fR, \fBupdate\fR, \fBdedupe\fR, \fBuninstall\fR, as well as \fBpack\fR and \fBpublish\fR.
.P
Note: This is NOT honored by other network related commands, eg \fBdist-tags\fR, \fBowner\fR, etc.
+.SS "\fBedit-dir\fR"
+.RS 0
+.IP \(bu 4
+Default: null
+.IP \(bu 4
+Type: null or Path
+.RE 0
+
+.P
+Override the temporary directory used by \fBnpm patch add\fR to prepare a package for editing.
.SS "\fBeditor\fR"
.RS 0
.IP \(bu 4
@@ -660,6 +688,16 @@ Type: null or Number
.P
When creating a Granular Access Token with \fBnpm token create\fR, this sets the expiration in days. If not specified, the server will determine the default expiration.
+.SS "\fBextension-file\fR"
+.RS 0
+.IP \(bu 4
+Default: null
+.IP \(bu 4
+Type: null or Path
+.RE 0
+
+.P
+Path to a project-local npm extension file to load instead of discovering \fB.npm-extension.mjs\fR / \fB.npm-extension.cjs\fR at the project root. Must resolve inside the project root and use a \fB.mjs\fR or \fB.cjs\fR extension. Only honored from project config or the command line, never from user, global, or builtin config.
.SS "\fBfetch-retries\fR"
.RS 0
.IP \(bu 4
@@ -770,7 +808,7 @@ Type: Boolean
.RE 0
.P
-Format \fBpackage-lock.json\fR or \fBnpm-shrinkwrap.json\fR as a human readable file.
+Format \fBpackage-lock.json\fR as a human readable file.
.SS "\fBfund\fR"
.RS 0
.IP \(bu 4
@@ -820,6 +858,18 @@ bin files are linked to \fB{prefix}/bin\fR
man pages are linked to \fB{prefix}/share/man\fR
.RE 0
+.SS "\fBglobal-ignore-file\fR"
+.RS 0
+.IP \(bu 4
+Default: The global --prefix setting plus 'etc/npmignore'. For example, '/usr/local/etc/npmignore'
+.IP \(bu 4
+Type: Path
+.RE 0
+
+.P
+An additional ignore file applied during \fBnpm pack\fR and \fBnpm publish\fR, owned by the current user rather than the package. Patterns follow the same syntax as a package's local \fB.npmignore\fR file. Useful for keeping editor metadata (such as \fB.idea/\fR or \fB*.iml\fR) and scratch directories out of every package you publish, without adding them to each package's own ignore rules.
+.P
+The global rules apply in addition to a package's local \fB.npmignore\fR. When a package uses a \fBfiles\fR field in its \fBpackage.json\fR, an entry in \fBfiles\fR that contradicts a global rule (i.e., explicitly includes a path the global rule would exclude) still wins.
.SS "\fBglobalconfig\fR"
.RS 0
.IP \(bu 4
@@ -862,6 +912,38 @@ Type: Boolean
If true, npm will not exit with an error code when \fBrun\fR is invoked for a script that isn't defined in the \fBscripts\fR section of \fBpackage.json\fR. This option can be used when it's desirable to optionally run a script when it's present and fail if the script fails. This is useful, for example, when running scripts that may only apply for some builds in an otherwise generic CI setup.
.P
This value is not exported to the environment for child processes.
+.SS "\fBignore-existing\fR"
+.RS 0
+.IP \(bu 4
+Default: false
+.IP \(bu 4
+Type: Boolean
+.RE 0
+
+.P
+With \fBnpm patch add\fR, discard a previous unfinished edit directory and start fresh.
+.SS "\fBignore-extension\fR"
+.RS 0
+.IP \(bu 4
+Default: false
+.IP \(bu 4
+Type: Boolean
+.RE 0
+
+.P
+If true, npm does not import or execute a root \fB.npm-extension.mjs\fR / \fB.npm-extension.cjs\fR file (or one selected via \fBextension-file\fR). \fBignore-scripts\fR implies \fBignore-extension\fR, since both disable root-owned install-time code.
+.SS "\fBignore-patch-failures\fR"
+.RS 0
+.IP \(bu 4
+Default: false
+.IP \(bu 4
+Type: Boolean
+.RE 0
+
+.P
+Install even when a registered patch fails to apply, with a warning per failure. Intended for incident response only.
+.P
+This flag is only honored when passed on the command line; it is ignored in \fB.npmrc\fR and environment variables, and rejected by \fBnpm ci\fR.
.SS "\fBignore-scripts\fR"
.RS 0
.IP \(bu 4
@@ -874,6 +956,8 @@ Type: Boolean
If true, npm does not run scripts specified in package.json files.
.P
Note that commands explicitly intended to run a particular script, such as \fBnpm start\fR, \fBnpm stop\fR, \fBnpm restart\fR, \fBnpm test\fR, and \fBnpm run\fR will still run their intended script if \fBignore-scripts\fR is set, but they will \fInot\fR run any pre- or post-scripts.
+.P
+Setting \fBignore-scripts\fR also disables \fB.npm-extension\fR execution, as if \fBignore-extension\fR were set.
.SS "\fBinclude\fR"
.RS 0
.IP \(bu 4
@@ -957,13 +1041,13 @@ The value \fBnpm init\fR should use by default for the package author's homepage
.SS "\fBinit-license\fR"
.RS 0
.IP \(bu 4
-Default: "ISC"
+Default: ""
.IP \(bu 4
Type: String
.RE 0
.P
-The value \fBnpm init\fR should use by default for the package license.
+The value \fBnpm init\fR should use by default for the package license. If not set, the license field will be omitted from new packages.
.SS "\fBinit-module\fR"
.RS 0
.IP \(bu 4
@@ -1043,6 +1127,16 @@ In \fBnpm pkg set\fR it enables parsing set values with JSON.parse() before savi
.P
Not supported by all npm commands.
+.SS "\fBkeep-edit-dir\fR"
+.RS 0
+.IP \(bu 4
+Default: false
+.IP \(bu 4
+Type: Boolean
+.RE 0
+
+.P
+With \fBnpm patch commit\fR, do not remove the edit directory after committing the patch.
.SS "\fBlegacy-peer-deps\fR"
.RS 0
.IP \(bu 4
@@ -1119,7 +1213,7 @@ Type: null, 1, 2, 3, "1", "2", or "3"
.RE 0
.P
-Set the lockfile format version to be used in package-lock.json and npm-shrinkwrap-json files. Possible options are:
+Set the lockfile format version to be used in package-lock.json files. Possible options are:
.P
1: The lockfile version used by npm versions 5 and 6. Lacks some data that is used during the install, resulting in slower and possibly less deterministic installs. Prevents lockfile churn when interoperating with older npm versions.
.P
@@ -1303,7 +1397,7 @@ Type: "dev", "optional", or "peer" (can be set multiple times)
.P
Dependency types to omit from the installation tree on disk.
.P
-Note that these dependencies \fIare\fR still resolved and added to the \fBpackage-lock.json\fR or \fBnpm-shrinkwrap.json\fR file. They are just not physically installed on disk.
+Note that these dependencies \fIare\fR still resolved and added to the \fBpackage-lock.json\fR file. They are just not physically installed on disk.
.P
If a package type appears in both the \fB--include\fR and \fB--omit\fR lists, then it will be included.
.P
@@ -1429,11 +1523,11 @@ When creating a Granular Access Token with \fBnpm token create\fR, grants the to
.IP \(bu 4
Default: null
.IP \(bu 4
-Type: null, "read-only", "read-write", or "no-access"
+Type: null, "read-only", "read-write", "read-write-stage-only", or "no-access"
.RE 0
.P
-When creating a Granular Access Token with \fBnpm token create\fR, sets the permission level for packages and scopes. Options are "read-only", "read-write", or "no-access".
+When creating a Granular Access Token with \fBnpm token create\fR, sets the permission level for packages and scopes. Options are "read-only", "read-write", "read-write-stage-only", or "no-access". "read-write-stage-only" grants publish access that stages releases instead of publishing them directly.
.SS "\fBparseable\fR"
.RS 0
.IP \(bu 4
@@ -1454,6 +1548,16 @@ Type: null or String
.P
Password for authentication. Can be provided via command line when creating tokens, though it's generally safer to be prompted for it.
+.SS "\fBpatches-dir\fR"
+.RS 0
+.IP \(bu 4
+Default: "patches"
+.IP \(bu 4
+Type: String
+.RE 0
+
+.P
+The directory, relative to the project root, where \fBnpm patch commit\fR writes patch files for \fBpatchedDependencies\fR.
.SS "\fBprefer-dedupe\fR"
.RS 0
.IP \(bu 4
@@ -1527,6 +1631,8 @@ Type: Boolean
.P
When publishing from a supported cloud CI/CD system, the package will be publicly linked to where it was built and published from.
.P
+When the \fBprovenance-file\fR config is set, it takes precedence and automatic provenance generation (including via trusted publishing/OIDC) is skipped.
+.P
This config cannot be used with: \fBprovenance-file\fR
.SS "\fBprovenance-file\fR"
.RS 0
@@ -1539,6 +1645,8 @@ Type: Path
.P
When publishing, the provenance bundle at the given path will be used.
.P
+This takes precedence over automatic provenance generation in trusted publishing flows.
+.P
This config cannot be used with: \fBprovenance\fR
.SS "\fBproxy\fR"
.RS 0
@@ -1853,11 +1961,23 @@ Type: Boolean
.RE 0
.P
-If \fBtrue\fR, turn the install-script policy from a warning into a hard error: any dependency with install scripts not covered by \fBallowScripts\fR will fail the install instead of running with a notice.
+If \fBtrue\fR, turn the install-script policy from a warning into a hard error: any dependency with install scripts that is not covered by \fBallowScripts\fR will fail the install instead of being blocked with a warning.
.P
-Dependencies explicitly denied with \fBfalse\fR in \fBallowScripts\fR are always silently skipped; this setting only affects unreviewed entries. \fB--ignore-scripts\fR and \fB--dangerously-allow-all-scripts\fR both override this setting.
+Dependencies explicitly denied with \fBfalse\fR in \fBallowScripts\fR are always silently skipped; this setting only affects unreviewed entries (packages with install scripts that are neither approved nor denied). \fB--ignore-scripts\fR and \fB--dangerously-allow-all-scripts\fR both override this setting.
.P
Optional dependencies that cannot be installed on the current platform or engine (a non-matching \fBos\fR, \fBcpu\fR, or \fBlibc\fR) are not flagged, because their install scripts never run.
+.SS "\fBstrict-npmrc\fR"
+.RS 0
+.IP \(bu 4
+Default: false
+.IP \(bu 4
+Type: Boolean
+.RE 0
+
+.P
+If set to \fBtrue\fR, unknown configuration keys found in \fB.npmrc\fR files are treated as a hard error instead of a warning.
+.P
+Unknown command line flags and abbreviated flags always error regardless of this setting.
.SS "\fBstrict-peer-deps\fR"
.RS 0
.IP \(bu 4
@@ -1927,6 +2047,16 @@ If true, writes timing information to a process specific json file in the cache
You can quickly view it with this \fBjson\fR \fI\(lahttps://npm.im/json\(ra\fR command line: \fBcat ~/.npm/_logs/*-timing.json | npm exec -- json -g\fR.
.P
Timing information will also be reported in the terminal. To suppress this while still writing the timing file, use \fB--silent\fR.
+.SS "\fBto\fR"
+.RS 0
+.IP \(bu 4
+Default: null
+.IP \(bu 4
+Type: null or String
+.RE 0
+
+.P
+Used by \fBnpm patch update\fR to set the version to rebase a patch onto when it cannot be read from \fBpackage-lock.json\fR \[em] for example an exact-version selector, or a version that has not been installed yet.
.SS "\fBtoken-description\fR"
.RS 0
.IP \(bu 4
@@ -2249,7 +2379,7 @@ Alias for \fB--init-author-url\fR
.SS "\fBinit.license\fR"
.RS 0
.IP \(bu 4
-Default: "ISC"
+Default: ""
.IP \(bu 4
Type: String
.IP \(bu 4
@@ -2352,18 +2482,6 @@ DEPRECATED: Use \fB--omit=dev\fR instead.
.P
Alias for \fB--omit=dev\fR
-.SS "\fBshrinkwrap\fR"
-.RS 0
-.IP \(bu 4
-Default: true
-.IP \(bu 4
-Type: Boolean
-.IP \(bu 4
-DEPRECATED: Use the --package-lock setting instead.
-.RE 0
-
-.P
-Alias for --package-lock
.SS "See also"
.RS 0
.IP \(bu 4
diff --git a/deps/npm/man/man7/dependency-selectors.7 b/deps/npm/man/man7/dependency-selectors.7
index ec08ce0750b..8332b010444 100644
--- a/deps/npm/man/man7/dependency-selectors.7
+++ b/deps/npm/man/man7/dependency-selectors.7
@@ -1,4 +1,4 @@
-.TH "SELECTORS" "7" "August 2026" "NPM@11.19.1" ""
+.TH "SELECTORS" "7" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBSelectors\fR - Dependency Selector Syntax & Querying
.SS "Description"
diff --git a/deps/npm/man/man7/developers.7 b/deps/npm/man/man7/developers.7
index aebb1f99a74..05a05a0b404 100644
--- a/deps/npm/man/man7/developers.7
+++ b/deps/npm/man/man7/developers.7
@@ -1,4 +1,4 @@
-.TH "DEVELOPERS" "7" "August 2026" "NPM@11.19.1" ""
+.TH "DEVELOPERS" "7" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBDevelopers\fR - Developer guide
.SS "Description"
@@ -203,17 +203,7 @@ npm test
.SS "Create a User Account"
.P
-Create a user with the adduser command. It works like this:
-.P
-.RS 2
-.nf
-npm adduser
-.fi
-.RE
-.P
-and then follow the prompts.
-.P
-This is documented better in npm help adduser.
+Create a user account on the \fBnpm website\fR \fI\(lahttps://www.npmjs.com/signup\(ra\fR.
.SS "Publish your Package"
.P
This part's easy. In the root of your folder, do this:
@@ -245,7 +235,7 @@ npm help scripts
.IP \(bu 4
npm help publish
.IP \(bu 4
-npm help adduser
+npm help login
.IP \(bu 4
npm help registry
.RE 0
diff --git a/deps/npm/man/man7/logging.7 b/deps/npm/man/man7/logging.7
index 7fab6e08925..68fc1eab610 100644
--- a/deps/npm/man/man7/logging.7
+++ b/deps/npm/man/man7/logging.7
@@ -1,4 +1,4 @@
-.TH "LOGGING" "7" "August 2026" "NPM@11.19.1" ""
+.TH "LOGGING" "7" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBLogging\fR - Why, What & How we Log
.SS "Description"
diff --git a/deps/npm/man/man7/orgs.7 b/deps/npm/man/man7/orgs.7
index 975eded22df..591a852e236 100644
--- a/deps/npm/man/man7/orgs.7
+++ b/deps/npm/man/man7/orgs.7
@@ -1,4 +1,4 @@
-.TH "ORGANIZATIONS" "7" "August 2026" "NPM@11.19.1" ""
+.TH "ORGANIZATIONS" "7" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBOrganizations\fR - Working with teams & organizations
.SS "Description"
diff --git a/deps/npm/man/man7/package-spec.7 b/deps/npm/man/man7/package-spec.7
index a68e9b8f7e7..85a71352446 100644
--- a/deps/npm/man/man7/package-spec.7
+++ b/deps/npm/man/man7/package-spec.7
@@ -1,4 +1,4 @@
-.TH "SPEC" "7" "August 2026" "NPM@11.19.1" ""
+.TH "SPEC" "7" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBspec\fR - Package name specifier
.SS "Description"
diff --git a/deps/npm/man/man7/registry.7 b/deps/npm/man/man7/registry.7
index a91c60c1456..6dab903239f 100644
--- a/deps/npm/man/man7/registry.7
+++ b/deps/npm/man/man7/registry.7
@@ -1,4 +1,4 @@
-.TH "REGISTRY" "7" "August 2026" "NPM@11.19.1" ""
+.TH "REGISTRY" "7" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBRegistry\fR - The JavaScript Package Registry
.SS "Description"
@@ -13,7 +13,7 @@ npm's package registry implementation supports several write APIs as well, to al
.P
The registry URL used is determined by the scope of the package (see npm help scope. If no scope is specified, the default registry is used, which is supplied by the \fB\[rs]fBregistry\[rs]fR config\fR \fI\(la/using-npm/config#registry\(ra\fR parameter. See npm help config, npm help npmrc, and npm help config for more on managing npm's configuration. Authentication configuration such as auth tokens and certificates are configured specifically scoped to an individual registry. See \fBAuth Related Configuration\fR \fI\(la/configuring-npm/npmrc#auth-related-configuration\(ra\fR
.P
-When the default registry is used in a package-lock or shrinkwrap it has the special meaning of "the currently configured registry". If you create a lock file while using the default registry you can switch to another registry and npm will install packages from the new registry, but if you create a lock file while using a custom registry packages will be installed from that registry even after you change to another registry.
+When the default registry is used in a package-lock it has the special meaning of "the currently configured registry". If you create a lock file while using the default registry you can switch to another registry and npm will install packages from the new registry, but if you create a lock file while using a custom registry packages will be installed from that registry even after you change to another registry.
.SS "Does npm send any information about me back to the registry?"
.P
Yes.
diff --git a/deps/npm/man/man7/removal.7 b/deps/npm/man/man7/removal.7
index bb4d7a8d436..544909b02d0 100644
--- a/deps/npm/man/man7/removal.7
+++ b/deps/npm/man/man7/removal.7
@@ -1,4 +1,4 @@
-.TH "REMOVAL" "7" "August 2026" "NPM@11.19.1" ""
+.TH "REMOVAL" "7" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBRemoval\fR - Cleaning the slate
.SS "Synopsis"
diff --git a/deps/npm/man/man7/scope.7 b/deps/npm/man/man7/scope.7
index f2744feb134..b606850f25d 100644
--- a/deps/npm/man/man7/scope.7
+++ b/deps/npm/man/man7/scope.7
@@ -1,4 +1,4 @@
-.TH "SCOPE" "7" "August 2026" "NPM@11.19.1" ""
+.TH "SCOPE" "7" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBScope\fR - Scoped packages
.SS "Description"
diff --git a/deps/npm/man/man7/scripts.7 b/deps/npm/man/man7/scripts.7
index 4af3522042b..6c9017dade9 100644
--- a/deps/npm/man/man7/scripts.7
+++ b/deps/npm/man/man7/scripts.7
@@ -1,4 +1,4 @@
-.TH "SCRIPTS" "7" "August 2026" "NPM@11.19.1" ""
+.TH "SCRIPTS" "7" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBScripts\fR - How npm handles the "scripts" field
.SS "Description"
@@ -131,7 +131,7 @@ The \fBdependencies\fR script is run any time an \fBnpm\fR command causes change
.SS "npm help ci"
.RS 0
.IP \(bu 4
-\fBpreinstall\fR
+\fBpreinstall\fR (before dependencies are installed)
.IP \(bu 4
\fBinstall\fR
.IP \(bu 4
@@ -147,7 +147,9 @@ The \fBdependencies\fR script is run any time an \fBnpm\fR command causes change
.RE 0
.P
-These all run after the actual installation of modules into \fBnode_modules\fR, in order, with no internal actions happening in between
+\fBpreinstall\fR runs before any dependencies are fetched or unpacked into \fBnode_modules\fR, so scripts can prepare the environment (for example, setting up authentication for a private registry) before tarballs are fetched. For \fBnpm ci\fR, \fBpreinstall\fR fires \fIafter\fR the lockfile has been validated against \fBpackage.json\fR, so it cannot influence dependency resolution \[em] that remains locked to \fBpackage-lock.json\fR. The remaining scripts run after the installation of modules into \fBnode_modules\fR, in order, with no internal actions happening in between.
+.P
+Because \fBpreinstall\fR runs before reify, scripts cannot rely on packages from \fBnode_modules\fR. \fBnpm ci\fR wipes \fBnode_modules\fR before \fBpreinstall\fR fires, so \fBrequire()\fR of a dependency will always fail. Use \fBinstall\fR or \fBpostinstall\fR for setup that depends on installed packages.
.SS "npm help diff"
.RS 0
.IP \(bu 4
@@ -156,10 +158,10 @@ These all run after the actual installation of modules into \fBnode_modules\fR,
.SS "npm help install"
.P
-These also run when you run \fBnpm install -g <pkg-name>\fR
+These run on a bare \fBnpm install\fR in a local project (no package arguments).
.RS 0
.IP \(bu 4
-\fBpreinstall\fR
+\fBpreinstall\fR (before dependencies are installed)
.IP \(bu 4
\fBinstall\fR
.IP \(bu 4
@@ -174,6 +176,10 @@ These also run when you run \fBnpm install -g <pkg-name>\fR
\fBpostprepare\fR
.RE 0
+.P
+\fBpreinstall\fR runs before any dependencies are fetched or unpacked into \fBnode_modules\fR, so scripts can prepare the environment (for example, setting up authentication for a private registry) before resolution begins. The remaining scripts run after installation has completed.
+.P
+Because \fBpreinstall\fR runs before reify, scripts cannot rely on packages from \fBnode_modules\fR. On a fresh checkout, \fBrequire()\fR of a dependency will fail. On a repeat \fBnpm install\fR against an existing \fBnode_modules/\fR, it may incidentally succeed because the previously-installed tree is still on disk, but the version available is whatever was previously installed and may be removed or replaced by the upcoming install. Use \fBinstall\fR or \fBpostinstall\fR for setup that depends on installed packages.
.P
If there is a \fBbinding.gyp\fR file in the root of your package and you haven't defined your own \fBinstall\fR or \fBpreinstall\fR scripts, npm will default the \fBinstall\fR command to compile using node-gyp via \fBnode-gyp rebuild\fR
.P
diff --git a/deps/npm/man/man7/workspaces.7 b/deps/npm/man/man7/workspaces.7
index b31d897d2f3..96c0881beaa 100644
--- a/deps/npm/man/man7/workspaces.7
+++ b/deps/npm/man/man7/workspaces.7
@@ -1,4 +1,4 @@
-.TH "WORKSPACES" "7" "August 2026" "NPM@11.19.1" ""
+.TH "WORKSPACES" "7" "September 2026" "NPM@12.1.0" ""
.SH "NAME"
\fBWorkspaces\fR - Working with workspaces
.SS "Description"
diff --git a/deps/npm/node_modules/@npmcli/agent/lib/agents.js b/deps/npm/node_modules/@npmcli/agent/lib/agents.js
index e9624dfeb90..8514f9892bb 100644
--- a/deps/npm/node_modules/@npmcli/agent/lib/agents.js
+++ b/deps/npm/node_modules/@npmcli/agent/lib/agents.js
@@ -161,6 +161,16 @@ module.exports = class Agent extends AgentBase {
return socket
}
+ keepSocketAlive (socket) {
+ const keepAlive = super.keepSocketAlive(socket)
+
+ if (keepAlive && this.#timeouts.idle) {
+ socket.setTimeout(this.#timeouts.idle)
+ }
+
+ return keepAlive
+ }
+
addRequest (request, options) {
const proxy = this.#getProxy(options)
// it would be better to call proxy.addRequest here but this causes the
diff --git a/deps/npm/node_modules/agent-base/LICENSE b/deps/npm/node_modules/@npmcli/agent/node_modules/agent-base/LICENSE
similarity index 100%
rename from deps/npm/node_modules/agent-base/LICENSE
rename to deps/npm/node_modules/@npmcli/agent/node_modules/agent-base/LICENSE
diff --git a/deps/npm/node_modules/@npmcli/agent/node_modules/agent-base/dist/helpers.js b/deps/npm/node_modules/@npmcli/agent/node_modules/agent-base/dist/helpers.js
new file mode 100644
index 00000000000..42c6ed2a0fe
--- /dev/null
+++ b/deps/npm/node_modules/@npmcli/agent/node_modules/agent-base/dist/helpers.js
@@ -0,0 +1,37 @@
+import * as http from 'http';
+import * as https from 'https';
+export async function toBuffer(stream) {
+ let length = 0;
+ const chunks = [];
+ for await (const chunk of stream) {
+ length += chunk.length;
+ chunks.push(chunk);
+ }
+ return Buffer.concat(chunks, length);
+}
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export async function json(stream) {
+ const buf = await toBuffer(stream);
+ const str = buf.toString('utf8');
+ try {
+ return JSON.parse(str);
+ }
+ catch (_err) {
+ const err = _err;
+ err.message += ` (input: ${str})`;
+ throw err;
+ }
+}
+export function req(url, opts = {}) {
+ const href = typeof url === 'string' ? url : url.href;
+ const req = (href.startsWith('https:') ? https : http).request(url, opts);
+ const promise = new Promise((resolve, reject) => {
+ req
+ .once('response', resolve)
+ .once('error', reject)
+ .end();
+ });
+ req.then = promise.then.bind(promise);
+ return req;
+}
+//# sourceMappingURL=helpers.js.map
\ No newline at end of file
diff --git a/deps/npm/node_modules/agent-base/dist/index.js b/deps/npm/node_modules/@npmcli/agent/node_modules/agent-base/dist/index.js
similarity index 74%
rename from deps/npm/node_modules/agent-base/dist/index.js
rename to deps/npm/node_modules/@npmcli/agent/node_modules/agent-base/dist/index.js
index 57ac85205e8..15aa6e9d745 100644
--- a/deps/npm/node_modules/agent-base/dist/index.js
+++ b/deps/npm/node_modules/@npmcli/agent/node_modules/agent-base/dist/index.js
@@ -1,38 +1,9 @@
-"use strict";
-var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
- if (k2 === undefined) k2 = k;
- var desc = Object.getOwnPropertyDescriptor(m, k);
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
- desc = { enumerable: true, get: function() { return m[k]; } };
- }
- Object.defineProperty(o, k2, desc);
-}) : (function(o, m, k, k2) {
- if (k2 === undefined) k2 = k;
- o[k2] = m[k];
-}));
-var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
- Object.defineProperty(o, "default", { enumerable: true, value: v });
-}) : function(o, v) {
- o["default"] = v;
-});
-var __importStar = (this && this.__importStar) || function (mod) {
- if (mod && mod.__esModule) return mod;
- var result = {};
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
- __setModuleDefault(result, mod);
- return result;
-};
-var __exportStar = (this && this.__exportStar) || function(m, exports) {
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.Agent = void 0;
-const net = __importStar(require("net"));
-const http = __importStar(require("http"));
-const https_1 = require("https");
-__exportStar(require("./helpers"), exports);
+import * as net from 'net';
+import * as http from 'http';
+import { Agent as HttpsAgent } from 'https';
+export * from './helpers.js';
const INTERNAL = Symbol('AgentBaseInternalState');
-class Agent extends http.Agent {
+export class Agent extends http.Agent {
constructor(opts) {
super(opts);
this[INTERNAL] = {};
@@ -113,10 +84,8 @@ class Agent extends http.Agent {
getName(options) {
const secureEndpoint = this.isSecureEndpoint(options);
if (secureEndpoint) {
- // @ts-expect-error `getName()` isn't defined in `@types/node`
- return https_1.Agent.prototype.getName.call(this, options);
+ return HttpsAgent.prototype.getName.call(this, options);
}
- // @ts-expect-error `getName()` isn't defined in `@types/node`
return super.getName(options);
}
createSocket(req, options, cb) {
@@ -130,9 +99,9 @@ class Agent extends http.Agent {
.then(() => this.connect(req, connectOpts))
.then((socket) => {
this.decrementSockets(name, fakeSocket);
- if (socket instanceof http.Agent) {
+ if (typeof socket
+ .addRequest === 'function') {
try {
- // @ts-expect-error `addRequest()` isn't defined in `@types/node`
return socket.addRequest(req, connectOpts);
}
catch (err) {
@@ -174,5 +143,4 @@ class Agent extends http.Agent {
}
}
}
-exports.Agent = Agent;
//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/deps/npm/node_modules/agent-base/package.json b/deps/npm/node_modules/@npmcli/agent/node_modules/agent-base/package.json
similarity index 68%
rename from deps/npm/node_modules/agent-base/package.json
rename to deps/npm/node_modules/@npmcli/agent/node_modules/agent-base/package.json
index 1b4964a83f6..8ef80c2bb09 100644
--- a/deps/npm/node_modules/agent-base/package.json
+++ b/deps/npm/node_modules/@npmcli/agent/node_modules/agent-base/package.json
@@ -1,9 +1,12 @@
{
"name": "agent-base",
- "version": "7.1.4",
+ "version": "9.0.0",
+ "type": "module",
"description": "Turn a function into an `http.Agent` instance",
- "main": "./dist/index.js",
- "types": "./dist/index.d.ts",
+ "exports": {
+ "types": "./dist/index.d.ts",
+ "default": "./dist/index.js"
+ },
"files": [
"dist"
],
@@ -23,23 +26,20 @@
"license": "MIT",
"devDependencies": {
"@types/debug": "^4.1.7",
- "@types/jest": "^29.5.1",
- "@types/node": "^14.18.45",
+ "@types/node": "^22.13.0",
"@types/semver": "^7.3.13",
- "@types/ws": "^6.0.4",
+ "@types/ws": "^8.5.4",
"async-listen": "^3.0.0",
- "jest": "^29.5.0",
- "ts-jest": "^29.1.0",
- "typescript": "^5.0.4",
- "ws": "^5.2.4",
+ "typescript": "^5.1.6",
+ "ws": "^8.13.0",
"tsconfig": "0.0.0"
},
"engines": {
- "node": ">= 14"
+ "node": ">= 20"
},
"scripts": {
"build": "tsc",
- "test": "jest --env node --verbose --bail",
+ "test": "vitest",
"lint": "eslint . --ext .ts",
"pack": "node ../../scripts/pack.mjs"
}
diff --git a/deps/npm/node_modules/http-proxy-agent/LICENSE b/deps/npm/node_modules/@npmcli/agent/node_modules/http-proxy-agent/LICENSE
similarity index 100%
rename from deps/npm/node_modules/http-proxy-agent/LICENSE
rename to deps/npm/node_modules/@npmcli/agent/node_modules/http-proxy-agent/LICENSE
diff --git a/deps/npm/node_modules/http-proxy-agent/dist/index.js b/deps/npm/node_modules/@npmcli/agent/node_modules/http-proxy-agent/dist/index.js
similarity index 68%
rename from deps/npm/node_modules/http-proxy-agent/dist/index.js
rename to deps/npm/node_modules/@npmcli/agent/node_modules/http-proxy-agent/dist/index.js
index fb2751c2264..441f27c99b1 100644
--- a/deps/npm/node_modules/http-proxy-agent/dist/index.js
+++ b/deps/npm/node_modules/@npmcli/agent/node_modules/http-proxy-agent/dist/index.js
@@ -1,49 +1,27 @@
-"use strict";
-var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
- if (k2 === undefined) k2 = k;
- var desc = Object.getOwnPropertyDescriptor(m, k);
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
- desc = { enumerable: true, get: function() { return m[k]; } };
- }
- Object.defineProperty(o, k2, desc);
-}) : (function(o, m, k, k2) {
- if (k2 === undefined) k2 = k;
- o[k2] = m[k];
-}));
-var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
- Object.defineProperty(o, "default", { enumerable: true, value: v });
-}) : function(o, v) {
- o["default"] = v;
-});
-var __importStar = (this && this.__importStar) || function (mod) {
- if (mod && mod.__esModule) return mod;
- var result = {};
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
- __setModuleDefault(result, mod);
- return result;
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.HttpProxyAgent = void 0;
-const net = __importStar(require("net"));
-const tls = __importStar(require("tls"));
-const debug_1 = __importDefault(require("debug"));
-const events_1 = require("events");
-const agent_base_1 = require("agent-base");
-const url_1 = require("url");
-const debug = (0, debug_1.default)('http-proxy-agent');
+import * as net from 'net';
+import * as tls from 'tls';
+import createDebug from 'debug';
+import { once } from 'events';
+import { Agent } from 'agent-base';
+import { URL } from 'url';
+import { createNegotiateAuth, } from 'proxy-agent-negotiate';
+const debug = createDebug('http-proxy-agent');
/**
* The `HttpProxyAgent` implements an HTTP Agent subclass that connects
* to the specified "HTTP proxy server" in order to proxy HTTP requests.
*/
-class HttpProxyAgent extends agent_base_1.Agent {
+export class HttpProxyAgent extends Agent {
constructor(proxy, opts) {
super(opts);
- this.proxy = typeof proxy === 'string' ? new url_1.URL(proxy) : proxy;
+ this.proxy = typeof proxy === 'string' ? new URL(proxy) : proxy;
this.proxyHeaders = opts?.headers ?? {};
debug('Creating new HttpProxyAgent instance: %o', this.proxy.href);
+ if (opts?.negotiate) {
+ this.onProxyAuth = createNegotiateAuth();
+ }
+ else if (opts?.onProxyAuth) {
+ this.onProxyAuth = opts.onProxyAuth;
+ }
// Trim off the brackets from IPv6 addresses
const host = (this.proxy.hostname || this.proxy.host).replace(/^\[|\]$/g, '');
const port = this.proxy.port
@@ -52,7 +30,9 @@ class HttpProxyAgent extends agent_base_1.Agent {
? 443
: 80;
this.connectOpts = {
- ...(opts ? omit(opts, 'headers') : null),
+ ...(opts
+ ? omit(opts, 'headers', 'onProxyAuth', 'negotiate')
+ : null),
host,
port,
};
@@ -68,7 +48,7 @@ class HttpProxyAgent extends agent_base_1.Agent {
const protocol = opts.secureEndpoint ? 'https:' : 'http:';
const hostname = req.getHeader('host') || 'localhost';
const base = `${protocol}//${hostname}`;
- const url = new url_1.URL(req.path, base);
+ const url = new URL(req.path, base);
if (opts.port !== 80) {
url.port = String(opts.port);
}
@@ -129,12 +109,16 @@ class HttpProxyAgent extends agent_base_1.Agent {
// function throws instead of the `http` request machinery. This is
// important for i.e. `PacProxyAgent` which determines a failed proxy
// connection via the `callback()` function throwing.
- await (0, events_1.once)(socket, 'connect');
+ await once(socket, 'connect');
+ // Emit the 'proxyConnect' event for parity with https-proxy-agent
+ const connect = { socket };
+ req.emit('proxyConnect', connect);
+ this.emit('proxyConnect', connect, req);
+ req.emit('proxy', { proxy: this.proxy.href, socket });
return socket;
}
}
HttpProxyAgent.protocols = ['http', 'https'];
-exports.HttpProxyAgent = HttpProxyAgent;
function omit(obj, ...keys) {
const ret = {};
let key;
diff --git a/deps/npm/node_modules/http-proxy-agent/package.json b/deps/npm/node_modules/@npmcli/agent/node_modules/http-proxy-agent/package.json
similarity index 64%
rename from deps/npm/node_modules/http-proxy-agent/package.json
rename to deps/npm/node_modules/@npmcli/agent/node_modules/http-proxy-agent/package.json
index a53940a3d88..c821fe00b5d 100644
--- a/deps/npm/node_modules/http-proxy-agent/package.json
+++ b/deps/npm/node_modules/@npmcli/agent/node_modules/http-proxy-agent/package.json
@@ -1,9 +1,12 @@
{
"name": "http-proxy-agent",
- "version": "7.0.2",
+ "version": "9.1.0",
+ "type": "module",
"description": "An HTTP(s) proxy `http.Agent` implementation for HTTP",
- "main": "./dist/index.js",
- "types": "./dist/index.d.ts",
+ "exports": {
+ "types": "./dist/index.d.ts",
+ "default": "./dist/index.js"
+ },
"files": [
"dist"
],
@@ -21,26 +24,24 @@
"author": "Nathan Rajlich <nathan@tootallnate.net> (http://n8.io/)",
"license": "MIT",
"dependencies": {
- "agent-base": "^7.1.0",
- "debug": "^4.3.4"
+ "debug": "^4.3.4",
+ "agent-base": "9.0.0",
+ "proxy-agent-negotiate": "1.1.0"
},
"devDependencies": {
"@types/debug": "^4.1.7",
- "@types/jest": "^29.5.1",
- "@types/node": "^14.18.45",
+ "@types/node": "^22.13.0",
"async-listen": "^3.0.0",
- "jest": "^29.5.0",
- "ts-jest": "^29.1.0",
- "typescript": "^5.0.4",
- "proxy": "2.1.1",
- "tsconfig": "0.0.0"
+ "typescript": "^5.1.6",
+ "tsconfig": "0.0.0",
+ "proxy": "4.1.0"
},
"engines": {
- "node": ">= 14"
+ "node": ">= 20"
},
"scripts": {
"build": "tsc",
- "test": "jest --env node --verbose --bail",
+ "test": "vitest",
"lint": "eslint . --ext .ts",
"pack": "node ../../scripts/pack.mjs"
}
diff --git a/deps/npm/node_modules/https-proxy-agent/LICENSE b/deps/npm/node_modules/@npmcli/agent/node_modules/https-proxy-agent/LICENSE
similarity index 100%
rename from deps/npm/node_modules/https-proxy-agent/LICENSE
rename to deps/npm/node_modules/@npmcli/agent/node_modules/https-proxy-agent/LICENSE
diff --git a/deps/npm/node_modules/https-proxy-agent/dist/index.js b/deps/npm/node_modules/@npmcli/agent/node_modules/https-proxy-agent/dist/index.js
similarity index 55%
rename from deps/npm/node_modules/https-proxy-agent/dist/index.js
rename to deps/npm/node_modules/@npmcli/agent/node_modules/https-proxy-agent/dist/index.js
index 1857f464724..207a134b355 100644
--- a/deps/npm/node_modules/https-proxy-agent/dist/index.js
+++ b/deps/npm/node_modules/@npmcli/agent/node_modules/https-proxy-agent/dist/index.js
@@ -1,40 +1,12 @@
-"use strict";
-var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
- if (k2 === undefined) k2 = k;
- var desc = Object.getOwnPropertyDescriptor(m, k);
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
- desc = { enumerable: true, get: function() { return m[k]; } };
- }
- Object.defineProperty(o, k2, desc);
-}) : (function(o, m, k, k2) {
- if (k2 === undefined) k2 = k;
- o[k2] = m[k];
-}));
-var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
- Object.defineProperty(o, "default", { enumerable: true, value: v });
-}) : function(o, v) {
- o["default"] = v;
-});
-var __importStar = (this && this.__importStar) || function (mod) {
- if (mod && mod.__esModule) return mod;
- var result = {};
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
- __setModuleDefault(result, mod);
- return result;
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.HttpsProxyAgent = void 0;
-const net = __importStar(require("net"));
-const tls = __importStar(require("tls"));
-const assert_1 = __importDefault(require("assert"));
-const debug_1 = __importDefault(require("debug"));
-const agent_base_1 = require("agent-base");
-const url_1 = require("url");
-const parse_proxy_response_1 = require("./parse-proxy-response");
-const debug = (0, debug_1.default)('https-proxy-agent');
+import * as net from 'net';
+import * as tls from 'tls';
+import assert from 'assert';
+import createDebug from 'debug';
+import { Agent } from 'agent-base';
+import { URL } from 'url';
+import { parseProxyResponse } from './parse-proxy-response.js';
+import { createNegotiateAuth, } from 'proxy-agent-negotiate';
+const debug = createDebug('https-proxy-agent');
const setServernameFromNonIpHost = (options) => {
if (options.servername === undefined &&
options.host &&
@@ -58,13 +30,19 @@ const setServernameFromNonIpHost = (options) => {
* `https:` requests have their socket connection upgraded to TLS once
* the connection to the proxy server has been established.
*/
-class HttpsProxyAgent extends agent_base_1.Agent {
+export class HttpsProxyAgent extends Agent {
constructor(proxy, opts) {
super(opts);
this.options = { path: undefined };
- this.proxy = typeof proxy === 'string' ? new url_1.URL(proxy) : proxy;
+ this.proxy = typeof proxy === 'string' ? new URL(proxy) : proxy;
this.proxyHeaders = opts?.headers ?? {};
debug('Creating new HttpsProxyAgent instance: %o', this.proxy.href);
+ if (opts?.negotiate) {
+ this.onProxyAuth = createNegotiateAuth();
+ }
+ else if (opts?.onProxyAuth) {
+ this.onProxyAuth = opts.onProxyAuth;
+ }
// Trim off the brackets from IPv6 addresses
const host = (this.proxy.hostname || this.proxy.host).replace(/^\[|\]$/g, '');
const port = this.proxy.port
@@ -75,7 +53,9 @@ class HttpsProxyAgent extends agent_base_1.Agent {
this.connectOpts = {
// Attempt to negotiate http/1.1 for proxy servers that support http/2
ALPNProtocols: ['http/1.1'],
- ...(opts ? omit(opts, 'headers') : null),
+ ...(opts
+ ? omit(opts, 'headers', 'onProxyAuth', 'negotiate')
+ : null),
host,
port,
};
@@ -118,11 +98,12 @@ class HttpsProxyAgent extends agent_base_1.Agent {
for (const name of Object.keys(headers)) {
payload += `${name}: ${headers[name]}\r\n`;
}
- const proxyResponsePromise = (0, parse_proxy_response_1.parseProxyResponse)(socket);
+ const proxyResponsePromise = parseProxyResponse(socket);
socket.write(`${payload}\r\n`);
const { connect, buffered } = await proxyResponsePromise;
req.emit('proxyConnect', connect);
this.emit('proxyConnect', connect, req);
+ req.emit('proxy', { proxy: this.proxy.href, socket });
if (connect.statusCode === 200) {
req.once('socket', resume);
if (opts.secureEndpoint) {
@@ -136,6 +117,21 @@ class HttpsProxyAgent extends agent_base_1.Agent {
}
return socket;
}
+ // Handle 407 Proxy Authentication Required
+ if (connect.statusCode === 407 && this.onProxyAuth) {
+ debug('Got 407 response, invoking onProxyAuth callback');
+ socket.destroy();
+ const proxyAuthenticate = connect.headers['proxy-authenticate'] || '';
+ const scheme = Array.isArray(proxyAuthenticate)
+ ? proxyAuthenticate[0].split(/\s/)[0]
+ : proxyAuthenticate.split(/\s/)[0];
+ const authResponse = await this.onProxyAuth({
+ response: connect,
+ scheme,
+ });
+ // Retry with the auth headers
+ return this._connectWithAuth(req, opts, authResponse.headers);
+ }
// Some other status code that's not 200... need to re-play the HTTP
// header "data" events onto the socket once the HTTP machinery is
// attached so that the node core `http` can parse and handle the
@@ -152,7 +148,7 @@ class HttpsProxyAgent extends agent_base_1.Agent {
// Need to wait for the "socket" event to re-play the "data" events.
req.once('socket', (s) => {
debug('Replaying proxy buffer for failed request');
- (0, assert_1.default)(s.listenerCount('data') > 0);
+ assert(s.listenerCount('data') > 0);
// Replay the "buffered" Buffer onto the fake `socket`, since at
// this point the HTTP module machinery has been hooked up for
// the user.
@@ -161,11 +157,69 @@ class HttpsProxyAgent extends agent_base_1.Agent {
});
return fakeSocket;
}
+ /**
+ * Retry a CONNECT request with additional auth headers.
+ */
+ async _connectWithAuth(req, opts, authHeaders) {
+ const { proxy } = this;
+ let socket;
+ if (proxy.protocol === 'https:') {
+ socket = tls.connect(setServernameFromNonIpHost(this.connectOpts));
+ }
+ else {
+ socket = net.connect(this.connectOpts);
+ }
+ const headers = typeof this.proxyHeaders === 'function'
+ ? this.proxyHeaders()
+ : { ...this.proxyHeaders };
+ const host = net.isIPv6(opts.host) ? `[${opts.host}]` : opts.host;
+ let payload = `CONNECT ${host}:${opts.port} HTTP/1.1\r\n`;
+ if (proxy.username || proxy.password) {
+ const auth = `${decodeURIComponent(proxy.username)}:${decodeURIComponent(proxy.password)}`;
+ headers['Proxy-Authorization'] = `Basic ${Buffer.from(auth).toString('base64')}`;
+ }
+ // Merge auth headers (overrides existing)
+ Object.assign(headers, authHeaders);
+ headers.Host = `${host}:${opts.port}`;
+ if (!headers['Proxy-Connection']) {
+ headers['Proxy-Connection'] = this.keepAlive
+ ? 'Keep-Alive'
+ : 'close';
+ }
+ for (const name of Object.keys(headers)) {
+ payload += `${name}: ${headers[name]}\r\n`;
+ }
+ const proxyResponsePromise = parseProxyResponse(socket);
+ socket.write(`${payload}\r\n`);
+ const { connect } = await proxyResponsePromise;
+ req.emit('proxyConnect', connect);
+ this.emit('proxyConnect', connect, req);
+ if (connect.statusCode === 200) {
+ req.once('socket', resume);
+ if (opts.secureEndpoint) {
+ debug('Upgrading socket connection to TLS');
+ return tls.connect({
+ ...omit(setServernameFromNonIpHost(opts), 'host', 'path', 'port'),
+ socket,
+ });
+ }
+ return socket;
+ }
+ // If still not 200, throw
+ socket.destroy();
+ throw new Error(`Proxy authentication failed with status ${connect.statusCode} after retry`);
+ }
}
HttpsProxyAgent.protocols = ['http', 'https'];
-exports.HttpsProxyAgent = HttpsProxyAgent;
function resume(socket) {
- socket.resume();
+ // Defer the resume so that all 'socket' event handlers have a chance
+ // to attach their listeners (e.g. the HTTP client's 'data' handler)
+ // before data starts flowing. Without this, buffered proxy-response
+ // data can be emitted synchronously before listeners are ready.
+ // See: https://github.com/nicolo-ribaudo/tc39-proposal-await-dictionary/issues/7
+ setImmediate(() => {
+ socket.resume();
+ });
}
function omit(obj, ...keys) {
const ret = {};
diff --git a/deps/npm/node_modules/https-proxy-agent/dist/parse-proxy-response.js b/deps/npm/node_modules/@npmcli/agent/node_modules/https-proxy-agent/dist/parse-proxy-response.js
similarity index 87%
rename from deps/npm/node_modules/https-proxy-agent/dist/parse-proxy-response.js
rename to deps/npm/node_modules/@npmcli/agent/node_modules/https-proxy-agent/dist/parse-proxy-response.js
index d3f506f9413..6ecc13a5529 100644
--- a/deps/npm/node_modules/https-proxy-agent/dist/parse-proxy-response.js
+++ b/deps/npm/node_modules/@npmcli/agent/node_modules/https-proxy-agent/dist/parse-proxy-response.js
@@ -1,12 +1,6 @@
-"use strict";
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.parseProxyResponse = void 0;
-const debug_1 = __importDefault(require("debug"));
-const debug = (0, debug_1.default)('https-proxy-agent:parse-proxy-response');
-function parseProxyResponse(socket) {
+import createDebug from 'debug';
+const debug = createDebug('https-proxy-agent:parse-proxy-response');
+export function parseProxyResponse(socket) {
return new Promise((resolve, reject) => {
// we need to buffer any HTTP traffic that happens with the proxy before we get
// the CONNECT response, so that if the response is anything other than an "200"
@@ -97,5 +91,4 @@ function parseProxyResponse(socket) {
read();
});
}
-exports.parseProxyResponse = parseProxyResponse;
//# sourceMappingURL=parse-proxy-response.js.map
\ No newline at end of file
diff --git a/deps/npm/node_modules/https-proxy-agent/package.json b/deps/npm/node_modules/@npmcli/agent/node_modules/https-proxy-agent/package.json
similarity index 62%
rename from deps/npm/node_modules/https-proxy-agent/package.json
rename to deps/npm/node_modules/@npmcli/agent/node_modules/https-proxy-agent/package.json
index 51b7e1175ff..ae575a2aefa 100644
--- a/deps/npm/node_modules/https-proxy-agent/package.json
+++ b/deps/npm/node_modules/@npmcli/agent/node_modules/https-proxy-agent/package.json
@@ -1,9 +1,12 @@
{
"name": "https-proxy-agent",
- "version": "7.0.6",
+ "version": "9.1.0",
+ "type": "module",
"description": "An HTTP(s) proxy `http.Agent` implementation for HTTPS",
- "main": "./dist/index.js",
- "types": "./dist/index.d.ts",
+ "exports": {
+ "types": "./dist/index.d.ts",
+ "default": "./dist/index.js"
+ },
"files": [
"dist"
],
@@ -21,29 +24,27 @@
"author": "Nathan Rajlich <nathan@tootallnate.net> (http://n8.io/)",
"license": "MIT",
"dependencies": {
- "agent-base": "^7.1.2",
- "debug": "4"
+ "debug": "^4.3.4",
+ "agent-base": "9.0.0",
+ "proxy-agent-negotiate": "1.1.0"
},
"devDependencies": {
"@types/async-retry": "^1.4.5",
- "@types/debug": "4",
- "@types/jest": "^29.5.1",
- "@types/node": "^14.18.45",
+ "@types/debug": "^4.1.7",
+ "@types/node": "^22.13.0",
"async-listen": "^3.0.0",
"async-retry": "^1.3.3",
- "jest": "^29.5.0",
- "ts-jest": "^29.1.0",
- "typescript": "^5.0.4",
- "proxy": "2.2.0",
+ "typescript": "^5.1.6",
+ "proxy": "4.1.0",
"tsconfig": "0.0.0"
},
"engines": {
- "node": ">= 14"
+ "node": ">= 20"
},
"scripts": {
"build": "tsc",
- "test": "jest --env node --verbose --bail test/test.ts",
- "test-e2e": "jest --env node --verbose --bail test/e2e.test.ts",
+ "test": "vitest --exclude test/e2e.test.ts",
+ "test-e2e": "vitest run test/e2e.test.ts",
"lint": "eslint --ext .ts",
"pack": "node ../../scripts/pack.mjs"
}
diff --git a/deps/npm/node_modules/@npmcli/agent/package.json b/deps/npm/node_modules/@npmcli/agent/package.json
index 8c0d358b02a..178d4bf4daf 100644
--- a/deps/npm/node_modules/@npmcli/agent/package.json
+++ b/deps/npm/node_modules/@npmcli/agent/package.json
@@ -1,6 +1,6 @@
{
"name": "@npmcli/agent",
- "version": "4.0.2",
+ "version": "5.0.2",
"description": "the http/https agent used by the npm cli",
"main": "lib/index.js",
"scripts": {
@@ -25,27 +25,26 @@
"lib/"
],
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.30.0",
+ "version": "5.1.1",
"publish": "true",
- "updateNpm": false,
- "latestCiVersion": 24
+ "updateNpm": false
},
"dependencies": {
- "agent-base": "^7.1.0",
- "http-proxy-agent": "^7.0.0",
- "https-proxy-agent": "^7.0.1",
+ "agent-base": "^9.0.0",
+ "http-proxy-agent": "^9.0.0",
+ "https-proxy-agent": "^9.0.0",
"lru-cache": "^11.2.1",
- "socks-proxy-agent": "^8.0.3"
+ "socks-proxy-agent": "^10.0.0"
},
"devDependencies": {
- "@npmcli/eslint-config": "^6.0.0",
- "@npmcli/template-oss": "4.30.0",
+ "@npmcli/eslint-config": "^7.0.0",
+ "@npmcli/template-oss": "5.1.1",
"ip-address": "^10.1.0",
- "minipass-fetch": "^5.0.0",
+ "minipass-fetch": "^6.0.0",
"nock": "^14.0.3",
"tap": "^16.3.0"
},
diff --git a/deps/npm/node_modules/@npmcli/arborist/README.md b/deps/npm/node_modules/@npmcli/arborist/README.md
index bdffaf4041a..7263a83f6b3 100644
--- a/deps/npm/node_modules/@npmcli/arborist/README.md
+++ b/deps/npm/node_modules/@npmcli/arborist/README.md
@@ -60,7 +60,7 @@ arb.loadActual().then(tree => {
// tree is also stored at arb.virtualTree
})
-// read just what the package-lock.json/npm-shrinkwrap says
+// read just what the package-lock.json says
// This *also* loads the yarn.lock file, but that's only relevant
// when building the ideal tree.
arb.loadVirtual().then(tree => {
@@ -301,7 +301,7 @@ pruning nodes from the tree.
that the dep is brought in by a peer dep at some point, rather than a
normal non-peer dependency.
-Note: `devOptional` is only set in the shrinkwrap/package-lock file if
+Note: `devOptional` is only set in the package-lock file if
_neither_ `dev` nor `optional` are set, as it would be redundant.
## BIN
diff --git a/deps/npm/node_modules/@npmcli/arborist/bin/index.js b/deps/npm/node_modules/@npmcli/arborist/bin/index.js
index 0b559687ac0..4e8e8adb621 100755
--- a/deps/npm/node_modules/@npmcli/arborist/bin/index.js
+++ b/deps/npm/node_modules/@npmcli/arborist/bin/index.js
@@ -20,8 +20,7 @@ ${message && '\n' + message + '\n'}
* prune: prune the ideal tree and reify (like npm prune)
* ideal: generate and print the ideal tree
* actual: read and print the actual tree in node_modules
- * virtual: read and print the virtual tree in the local shrinkwrap file
- * shrinkwrap: load a local shrinkwrap and print its data
+ * virtual: read and print the virtual tree in the local package-lock.json
* audit: perform a security audit on project dependencies
* funding: query funding information in the local package tree. A second
positional argument after the path name can limit to a package name.
diff --git a/deps/npm/node_modules/@npmcli/arborist/bin/shrinkwrap.js b/deps/npm/node_modules/@npmcli/arborist/bin/shrinkwrap.js
deleted file mode 100644
index 56603224e99..00000000000
--- a/deps/npm/node_modules/@npmcli/arborist/bin/shrinkwrap.js
+++ /dev/null
@@ -1,7 +0,0 @@
-const Shrinkwrap = require('../lib/shrinkwrap.js')
-
-module.exports = (options, time) => Shrinkwrap
- .load(options)
- .then((s) => s.commit())
- .then(time)
- .then(({ result: s }) => JSON.stringify(s, 0, 2))
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js
index 2f8ed83e115..f7497c2bda4 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js
@@ -25,6 +25,10 @@ const debug = require('../debug.js')
const fromPath = require('../from-path.js')
const calcDepFlags = require('../calc-dep-flags.js')
const { isReleaseAgeExcluded, trustedSpecName } = require('../release-age-exclude.js')
+const { resolvePatchedDependencies } = require('../patched-dependencies.js')
+const PackageExtensions = require('../package-extensions.js')
+const NpmExtension = require('../npm-extension.js')
+const { hasExtensionFile } = require('../npm-extension.js')
const Shrinkwrap = require('../shrinkwrap.js')
const { defaultLockfileVersion } = Shrinkwrap
const Node = require('../node.js')
@@ -97,6 +101,8 @@ module.exports = cls => class IdealTreeBuilder extends cls {
#loadFailures = new Set()
#manifests = new Map()
#mutateTree = false
+ #packageExtensions = null
+ #npmExtension = null
#requestedTreeMutation = false
// a map of each module in a peer set to the thing that depended on
// that set of peers in the first place. Use a WeakMap so that we
@@ -175,12 +181,21 @@ module.exports = cls => class IdealTreeBuilder extends cls {
try {
await this.#initTree()
+ await this.#loadNpmExtension()
+ this.#loadPackageExtensions()
await this.#inflateAncientLockfile()
await this.#applyUserRequests(options)
await this.#buildDeps()
await this.#fixDepFlags()
await this.#pruneFailedOptional()
await this.#checkEngineAndPlatform()
+ await resolvePatchedDependencies(this.idealTree, {
+ path: this.path,
+ allowUnusedPatches: this.options.allowUnusedPatches,
+ rm: options.rm || [],
+ })
+ this.#warnWorkspacePackageExtensions()
+ this.#warnWorkspaceNpmExtension()
} finally {
timeEnd()
this.finishTracker('idealTree')
@@ -228,6 +243,131 @@ module.exports = cls => class IdealTreeBuilder extends cls {
}
}
+ // Load the root project's packageExtensions rule set.
+ // Only the workspace root is authoritative, matching the root-only model of overrides.
+ // The canonical hash is stashed on the lockfile meta so commit() can persist it.
+ #loadPackageExtensions () {
+ const rootPkg = this.idealTree.target.package
+ const lockedHash = this.idealTree.meta.packageExtensionsHash
+ this.#packageExtensions = new PackageExtensions(rootPkg.packageExtensions)
+ this.idealTree.meta.packageExtensionsHash = this.#packageExtensions.hash
+
+ // When the rule set has changed since the lockfile was written, the locked manifests for affected packages are stale.
+ // The locked manifest is the effective, already-extended manifest, so detach those nodes and rebuild them from fresh manifests under the current rules.
+ if (this.idealTree.meta.loadedFromDisk && lockedHash !== this.#packageExtensions.hash) {
+ for (const node of [...this.idealTree.inventory.values()]) {
+ if (node.isProjectRoot || node.isWorkspace || node.isTop) {
+ continue
+ }
+ // a node is affected if it carries provenance from the old rules or matches a current selector
+ const affected = node.packageExtensionsApplied ||
+ this.#packageExtensions.wouldMatch(node.packageName, node.version)
+ if (affected) {
+ for (const edge of node.edgesIn) {
+ this.#depsQueue.push(edge.from)
+ }
+ node.parent = null
+ }
+ }
+ }
+ }
+
+ // Apply a matching root packageExtension to a copy of a candidate manifest.
+ // Returns the possibly-extended manifest and the provenance to attach to the node.
+ // Workspace candidates are never extended; that warning is emitted separately.
+ #applyPackageExtension (pkg) {
+ if (!this.#packageExtensions?.present) {
+ return { pkg, applied: null }
+ }
+ const res = this.#packageExtensions.apply(pkg)
+ return res ? { pkg: res.pkg, applied: res.applied } : { pkg, applied: null }
+ }
+
+ // Load the root project's .npm-extension file and its transformManifest export.
+ // ignore-extension (and, via flatten, ignore-scripts) disables discovery and execution; the lockfile then carries no extension state.
+ // The selected file's hash is stashed on the lockfile meta so commit() can persist it and npm ci can detect stale extension state.
+ async #loadNpmExtension () {
+ const lockedHash = this.idealTree.meta.npmExtensionHash
+ // ignore-extension (and, via flatten, ignore-scripts) disables discovery and execution.
+ // Leave any locked extension state untouched so npm ci reifies the locked graph as-is and the lockfile stays internally consistent.
+ if (this.options.ignoreExtension) {
+ return
+ }
+ const ext = new NpmExtension({
+ root: this.idealTree.realpath,
+ extensionFile: this.options.extensionFile,
+ })
+ this.#npmExtension = ext
+ this.idealTree.meta.npmExtensionHash = ext.hash
+ if (ext.present) {
+ await ext.load()
+ }
+
+ // When the extension file changed since the lockfile was written, locked manifests may no longer reflect its output.
+ // This also covers removal: a now-absent file hashes to null, which differs from the locked hash and reverts the previously transformed nodes.
+ // Arbitrary code has no selector to predict which packages it affects, so re-resolve any node that carried old provenance or that the current file now transforms.
+ if (this.idealTree.meta.loadedFromDisk && lockedHash !== ext.hash) {
+ for (const node of [...this.idealTree.inventory.values()]) {
+ if (node.isProjectRoot || node.isWorkspace || node.isTop || node.isLink) {
+ continue
+ }
+ // A node with old provenance carries an already-transformed manifest, so always refetch it.
+ // Otherwise probe the locked manifest (without caching, so the authoritative full-manifest fetch is not pre-seeded).
+ // The locked manifest carries every resolution-relevant field (name, version, dependencies, peer metadata); a transform that newly targets a node by a field not persisted in the lockfile is the documented edge that may need a manual re-lock.
+ const affected = node.npmExtensionApplied || ext.apply(node.package, { memoize: false })
+ if (affected) {
+ for (const edge of node.edgesIn) {
+ this.#depsQueue.push(edge.from)
+ }
+ node.parent = null
+ }
+ }
+ }
+ }
+
+ // Apply the root transformManifest to a copy of a candidate manifest, before any packageExtensions rule.
+ // Returns the possibly-transformed manifest and the provenance to attach to the node.
+ #applyNpmExtension (pkg) {
+ const res = this.#npmExtension?.apply(pkg)
+ return res ? { pkg: res.pkg, applied: res.applied } : { pkg, applied: null }
+ }
+
+ // Warn when packageExtensions appears in a non-root workspace, or when a root selector matches a workspace member.
+ // Workspace package manifests are edited directly and are never extension targets.
+ #warnWorkspacePackageExtensions () {
+ if (!this.#packageExtensions?.present) {
+ return
+ }
+ for (const node of this.idealTree.inventory.values()) {
+ // a workspace is in the inventory as both a Link and its target node; warn once by skipping the link
+ if (!node.isWorkspace || node.isLink) {
+ continue
+ }
+ if (node.package.packageExtensions !== undefined) {
+ log.warn('packageExtensions',
+ `"packageExtensions" in workspace ${node.name} is ignored; it is only honored at the workspace root`)
+ }
+ if (this.#packageExtensions.wouldMatch(node.name, node.version)) {
+ log.warn('packageExtensions',
+ `selector matches workspace package ${node.name}@${node.version}; edit its package.json directly instead of using packageExtensions`)
+ }
+ }
+ }
+
+ // Warn when a non-root workspace package contains a .npm-extension file; only the workspace root's file is honored.
+ #warnWorkspaceNpmExtension () {
+ for (const node of this.idealTree.inventory.values()) {
+ // a workspace is in the inventory as both a Link and its target node; warn once by skipping the link
+ if (!node.isWorkspace || node.isLink || node.isProjectRoot) {
+ continue
+ }
+ if (hasExtensionFile(node.realpath)) {
+ log.warn('npm-extension',
+ `".npm-extension" in workspace ${node.name} is ignored; it is only honored at the workspace root`)
+ }
+ }
+ }
+
#parseSettings (options) {
const update = options.update === true ? { all: true }
: Array.isArray(options.update) ? { names: options.update }
@@ -257,6 +397,22 @@ module.exports = cls => class IdealTreeBuilder extends cls {
this[_updateNames] = update.names
this[_updateAll] = update.all
+
+ // validates list of rm names, they must
+ // be dep names only, no semver ranges are supported
+ for (const name of options.rm || []) {
+ const spec = npa(name)
+ const validationError =
+ new TypeError(`Remove arguments must only contain package names, eg:
+ npm rm ${spec.name || '<pkg>'}`)
+ validationError.code = 'ERMARGS'
+
+ // If they gave us anything other than a bare package name
+ if (spec.raw !== spec.name) {
+ throw validationError
+ }
+ }
+
// we prune by default unless explicitly set to boolean false
this.#prune = options.prune !== false
@@ -731,7 +887,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
for (const node of this.idealTree.inventory.values()) {
// XXX add any invalid edgesOut to the queue
if (this[_updateNames].includes(node.name) &&
- !node.isTop && !node.inDepBundle && !node.inShrinkwrap) {
+ !node.isTop && !node.inDepBundle) {
for (const edge of node.edgesIn) {
this.addTracker('idealTree', edge.from.name, edge.from.location)
this.#depsQueue.push(edge.from)
@@ -855,15 +1011,11 @@ This is a one-time fix-up, please be patient...
const node = this.#depsQueue.pop()
const bd = node.package.bundleDependencies
const hasBundle = bd && Array.isArray(bd) && bd.length
- const { hasShrinkwrap } = node
// if the node was already visited, or has since been removed from the
- // tree, skip over it and process the rest of the queue. If a node has
- // a shrinkwrap, also skip it, because it's going to get its deps
- // satisfied by whatever's in that file anyway.
+ // tree, skip over it and process the rest of the queue.
if (this.#depsSeen.has(node) ||
- node.root !== this.idealTree ||
- hasShrinkwrap && !this.#complete) {
+ node.root !== this.idealTree) {
return this.#buildDepStep()
}
@@ -873,15 +1025,15 @@ This is a one-time fix-up, please be patient...
// if we're loading a _complete_ ideal tree, for a --package-lock-only
// installation for example, we have to crack open the tarball and
- // look inside if it has bundle deps or shrinkwraps. note that this is
+ // look inside if it has bundle deps. note that this is
// not necessary during a reification, because we just update the
- // ideal tree by reading bundles/shrinkwraps in place.
+ // ideal tree by reading bundles in place.
// Don't bother if the node is from the actual tree and hasn't
// been resolved, because we can't fetch it anyway, could be anything!
const crackOpen = this.#complete &&
node !== this.idealTree &&
node.resolved &&
- (hasBundle || hasShrinkwrap) &&
+ hasBundle &&
!node.inert
if (crackOpen) {
const Arborist = this.constructor
@@ -894,15 +1046,8 @@ This is a one-time fix-up, please be patient...
integrity: node.integrity,
})
- if (hasShrinkwrap) {
- await new Arborist({ ...this.options, path })
- .loadVirtual({ root: node, subtreeOnly: true })
- }
-
- if (hasBundle) {
- await new Arborist({ ...this.options, path })
- .loadActual({ root: node, ignoreMissing: true })
- }
+ await new Arborist({ ...this.options, path })
+ .loadActual({ root: node, ignoreMissing: true })
})
}
@@ -1256,11 +1401,6 @@ This is a one-time fix-up, please be patient...
continue
}
- // If it's shrinkwrapped, we use what the shrinkwap wants.
- if (edge.to && edge.to.inShrinkwrap) {
- continue
- }
-
// If the edge has no destination, that's a problem, unless
// if it's peerOptional and not explicitly requested.
if (!edge.to) {
@@ -1428,7 +1568,17 @@ This is a one-time fix-up, please be patient...
)
return this.#failureNode(name, parent, error, edge)
}
- return new Node({ name, pkg, parent, installLinks, legacyPeerDeps })
+ // Transform the manifest copy before any packageExtensions rule and before the Node reads its dependency and peer edges.
+ const transformed = this.#applyNpmExtension(pkg)
+ const { pkg: extended, applied } = this.#applyPackageExtension(transformed.pkg)
+ const node = new Node({ name, pkg: extended, parent, installLinks, legacyPeerDeps })
+ if (transformed.applied) {
+ node.npmExtensionApplied = transformed.applied
+ }
+ if (applied) {
+ node.packageExtensionsApplied = applied
+ }
+ return node
},
error => this.#failureNode(name, parent, error, edge)
)
@@ -1473,6 +1623,16 @@ This is a one-time fix-up, please be patient...
if (!edge.to) {
if (!parentEdge) {
+ // the peer is missing from the virtual root; check the real tree before skipping.
+ // we can avoid a fetch for an optional peer, or a compatible provider, though
+ // an incompatible provider still has to be resolved here so that the
+ // optional peer set nests instead of displacing required peers.
+ if (edge.type === 'peerOptional') {
+ const current = node.parent.sourceReference.resolve(edge.name)
+ if (!current || current.satisfies(edge)) {
+ continue
+ }
+ }
// easy, just put the thing there
await this.#nodeFromEdge(edge, node.parent, null, required)
continue
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/isolated-reifier.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/isolated-reifier.js
index a07c55e3f28..784c389c437 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/isolated-reifier.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/isolated-reifier.js
@@ -1,5 +1,3 @@
-const { mkdirSync } = require('node:fs')
-const pacote = require('pacote')
const { join } = require('node:path')
const { depth } = require('treeverse')
const crypto = require('node:crypto')
@@ -15,7 +13,10 @@ const getKey = (startNode) => {
getChildren: node => node.dependencies,
visit: node => {
branch.push(`${node.packageName}@${node.version}`)
- deps.push(`${branch.join('->')}::${node.resolved}`)
+ // a patch changes the materialized contents, so it must change the store key.
+ // the patch segment is only appended when present, so unpatched keys are unchanged.
+ const patch = node.patched ? `::patch:${node.patched.integrity}` : ''
+ deps.push(`${branch.join('->')}::${node.resolved}${patch}`)
},
leave: () => {
branch.pop()
@@ -30,7 +31,9 @@ const getKey = (startNode) => {
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/m, '')
- return `${startNode.packageName}@${startNode.version}-${hash}`
+ // a patched entry gets a distinct, identifiable side-store key so unpatched consumers keep sharing the original
+ const patchSuffix = startNode.patched ? '+patch' : ''
+ return `${startNode.packageName}@${startNode.version}-${hash}${patchSuffix}`
}
module.exports = cls => class IsolatedReifier extends cls {
@@ -51,6 +54,7 @@ module.exports = cls => class IsolatedReifier extends cls {
optional: node.optional,
package: pkg,
parent: root,
+ patched: node.patched,
path: join(this.idealGraph.localPath, location),
resolved: node.resolved,
root,
@@ -153,46 +157,7 @@ module.exports = cls => class IsolatedReifier extends cls {
const result = {}
// XXX this goes recursive if we don't set here because assignCommonProperties also calls this.#externalProxy
this.#externalProxies.set(node, result)
- await this.#assignCommonProperties(node, result, !node.hasShrinkwrap)
- if (node.hasShrinkwrap) {
- // strip any path traversal from package.json name fields before they hit path.join below
- /* istanbul ignore next - packageName is always set for real packages */
- const safeName = nameFromFolder(node.packageName || node.path)
- const dir = join(
- node.root.path,
- 'node_modules',
- '.store',
- `${safeName}@${node.version}`
- )
- mkdirSync(dir, { recursive: true })
- // TODO this approach feels wrong and shouldn't be necessary for shrinkwraps
- await pacote.extract(node.resolved, dir, {
- ...this.options,
- resolved: node.resolved,
- integrity: node.integrity,
- // TODO _isRoot
- })
- const Arborist = this.constructor
- const arb = new Arborist({ ...this.options, path: dir })
- // Make sure that the ideal tree is build as the rest of the algorithm depends on it.
- await arb.buildIdealTree({
- complete: false,
- dev: false,
- })
- await arb.makeIdealGraph()
- this.idealGraph.external.push(...arb.idealGraph.external)
- for (const edge of arb.idealGraph.external) {
- edge.root = this.idealGraph
- edge.id = `${node.id}=>${edge.id}`
- }
- result.localDependencies = []
- result.externalDependencies = arb.idealGraph.externalDependencies
- result.externalOptionalDependencies = arb.idealGraph.externalOptionalDependencies
- result.dependencies = [
- ...result.externalDependencies,
- ...result.externalOptionalDependencies,
- ]
- }
+ await this.#assignCommonProperties(node, result)
result.optional = node.optional
result.resolved = node.resolved
result.version = node.version
@@ -206,7 +171,7 @@ module.exports = cls => class IsolatedReifier extends cls {
return result
}
- async #assignCommonProperties (node, result, populateDeps = true) {
+ async #assignCommonProperties (node, result) {
result.root = this.idealGraph
// XXX does anything need this?
result.id = this.counter++
@@ -214,13 +179,10 @@ module.exports = cls => class IsolatedReifier extends cls {
result.name = result.isWorkspace ? (node.packageName || node.name) : node.name
// strip any path traversal from package.json name fields before they hit path.join below
result.packageName = nameFromFolder(node.packageName || node.path)
+ result.patched = node.patched
result.package = { ...node.package }
result.package.bundleDependencies = undefined
- if (!populateDeps) {
- return
- }
-
let edges = [...node.edgesOut.values()].filter(edge =>
edge.to?.target &&
!(node.package.bundledDependencies || node.package.bundleDependencies)?.includes(edge.to.name)
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-actual.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-actual.js
index 2158f6d32ae..02a466e655a 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-actual.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-actual.js
@@ -13,6 +13,8 @@ const calcDepFlags = require('../calc-dep-flags.js')
const Node = require('../node.js')
const Link = require('../link.js')
const realpath = require('../realpath.js')
+const PackageExtensions = require('../package-extensions.js')
+const NpmExtension = require('../npm-extension.js')
// public symbols
const _changePath = Symbol.for('_changePath')
@@ -177,6 +179,10 @@ module.exports = cls => class ActualLoader extends cls {
this.#linkActualWorkspaces()
+ // .npm-extension runs before packageExtensions, matching the ideal-tree resolution order
+ await this.#applyNpmExtension()
+ this.#applyPackageExtensions()
+
if (!ignoreMissing) {
await this.#findMissingEdges()
}
@@ -401,6 +407,34 @@ module.exports = cls => class ActualLoader extends cls {
}
}
+ // packageExtensions never rewrite a package's package.json, so a filesystem-scanned actual tree lacks the extension-created edges and provenance.
+ // Re-derive them from the root rule set, as buildIdealTree does.
+ // This is always required under the linked strategy, whose store layout forces the filesystem-scan path.
+ #applyPackageExtensions () {
+ const rootPkg = this.#actualTree.target?.package
+ const pe = new PackageExtensions(rootPkg?.packageExtensions)
+ if (!pe.present || !pe.selectors.length) {
+ return
+ }
+ for (const node of this.#actualTree.inventory.values()) {
+ // only installed dependencies are extended, never the root or a workspace
+ if (node.isLink || node.isProjectRoot || !node.name || !node.inNodeModules()) {
+ continue
+ }
+ const res = pe.apply(node.package)
+ if (res) {
+ node.package = res.pkg
+ node.packageExtensionsApplied = res.applied
+ }
+ }
+ // mirror the provenance onto links so the logical tree location reports it too
+ for (const node of this.#actualTree.inventory.values()) {
+ if (node.isLink && node.target?.packageExtensionsApplied) {
+ node.packageExtensionsApplied = node.target.packageExtensionsApplied
+ }
+ }
+ }
+
// Re-forward overrides through links once all edges are resolved, since a Link may forward before its subtree resolves and miss a transitive match (npm/cli#9619, #9659).
#repropagateOverrides () {
if (!this.#actualTree.overrides) {
@@ -413,6 +447,39 @@ module.exports = cls => class ActualLoader extends cls {
}
}
+ // .npm-extension transformManifest, like packageExtensions, never rewrites a package's package.json, so re-derive its edges and provenance on a filesystem-scanned actual tree.
+ // This executes the root extension code; ignore-extension (and ignore-scripts via flatten) disables it.
+ async #applyNpmExtension () {
+ if (this.options.ignoreExtension) {
+ return
+ }
+ const ext = new NpmExtension({
+ root: this.#actualTree.realpath,
+ extensionFile: this.options.extensionFile,
+ })
+ if (!ext.present) {
+ return
+ }
+ await ext.load()
+ for (const node of this.#actualTree.inventory.values()) {
+ // only installed dependencies are transformed, never the root or a workspace
+ if (node.isLink || node.isProjectRoot || !node.name || !node.inNodeModules()) {
+ continue
+ }
+ const res = ext.apply(node.package)
+ if (res) {
+ node.package = res.pkg
+ node.npmExtensionApplied = res.applied
+ }
+ }
+ // mirror the provenance onto links so the logical tree location reports it too
+ for (const node of this.#actualTree.inventory.values()) {
+ if (node.isLink && node.target?.npmExtensionApplied) {
+ node.npmExtensionApplied = node.target.npmExtensionApplied
+ }
+ }
+ }
+
async #findMissingEdges () {
// try to resolve any missing edges by walking up the directory tree,
// checking for the package in each node_modules folder. stop at the
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js
index 13626fc5ded..7e876adc016 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js
@@ -1,4 +1,4 @@
-const { isAbsolute, resolve } = require('node:path')
+const { resolve } = require('node:path')
// mixin providing the loadVirtual method
const mapWorkspaces = require('@npmcli/map-workspaces')
const PackageJson = require('@npmcli/package-json')
@@ -17,8 +17,6 @@ const setWorkspaces = Symbol.for('setWorkspaces')
module.exports = cls => class VirtualLoader extends cls {
#rootOptionProvided
- // when true, lockfile entries must stay inside `this.path`
- #subtreeOnly = false
// public method
async loadVirtual (options = {}) {
@@ -30,8 +28,6 @@ module.exports = cls => class VirtualLoader extends cls {
// XXX: deprecate separate reify() options object.
options = { ...this.options, ...options }
- this.#subtreeOnly = !!options.subtreeOnly
-
if (options.root && options.root.meta) {
await this.#loadFromShrinkwrap(options.root.meta, options.root)
return treeCheck(this.virtualTree)
@@ -43,7 +39,7 @@ module.exports = cls => class VirtualLoader extends cls {
resolveOptions: this.options,
})
if (!s.loadedFromDisk && !options.root) {
- const er = new Error('loadVirtual requires existing shrinkwrap file')
+ const er = new Error('loadVirtual requires existing package-lock.json file')
throw Object.assign(er, { code: 'ENOLOCK' })
}
@@ -170,40 +166,12 @@ module.exports = cls => class VirtualLoader extends cls {
}
}
- // throw if the resolved path is outside `base`, only in subtreeOnly mode
- #assertContained (base, resolvedPath, location) {
- if (!this.#subtreeOnly) {
- return
- }
- if (isAbsolute(location)) {
- throw Object.assign(
- new Error(`invalid lockfile entry: "${location}" must be a relative location`),
- { code: 'EINVALIDLOCATION', location, base }
- )
- }
- const rel = relpath(base, resolvedPath)
- if (
- rel === '..' ||
- rel.startsWith('../') ||
- isAbsolute(rel) ||
- // non-root key that collapses back to base (e.g. 'node_modules/..')
- (rel === '' && location !== '')
- ) {
- throw Object.assign(
- new Error(`invalid lockfile entry: "${location}" resolves outside of "${base}"`),
- { code: 'EINVALIDLOCATION', location, base, resolvedPath }
- )
- }
- }
-
// links is the set of metadata, and nodes is the map of non-Link nodes
// Set the targets to nodes in the set, if we have them (we might not)
// XXX build-ideal-tree also has a #resolveLinks, is there overlap?
async #resolveLinks (links, nodes) {
for (const [location, meta] of links.entries()) {
const targetPath = resolve(this.path, meta.resolved)
- // check before nodes.get so we surface EINVALIDLOCATION instead of EMISSINGTARGET
- this.#assertContained(this.path, targetPath, meta.resolved || location)
const targetLoc = relpath(this.path, targetPath)
const target = nodes.get(targetLoc)
@@ -262,7 +230,6 @@ To fix:
#loadNode (location, sw, loadOverrides) {
const p = this.virtualTree ? this.virtualTree.realpath : this.path
const path = resolve(p, location)
- this.#assertContained(p, path, location)
// shrinkwrap doesn't include package name unless necessary
if (!sw.name) {
sw.name = nameFromFolder(path)
@@ -275,9 +242,11 @@ To fix:
path,
realpath: path,
integrity: sw.integrity,
+ patched: sw.patched,
+ packageExtensionsApplied: sw.packageExtensionsApplied,
+ npmExtensionApplied: sw.npmExtensionApplied,
resolved: consistentResolve(sw.resolved, this.path, path),
pkg: sw,
- hasShrinkwrap: sw.hasShrinkwrap,
loadOverrides,
// cast to boolean because they're undefined in the lock file when false
extraneous: !!sw.extraneous,
@@ -292,7 +261,6 @@ To fix:
#loadLink (location, targetLoc, target) {
const path = resolve(this.path, location)
- this.#assertContained(this.path, path, location)
const link = new Link({
installLinks: this.installLinks,
legacyPeerDeps: this.legacyPeerDeps,
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/rebuild.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/rebuild.js
index a99d328f5d2..53c6f63e77d 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/rebuild.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/rebuild.js
@@ -199,18 +199,25 @@ module.exports = cls => class Builder extends cls {
const { package: { bin, scripts = {} } } = node.target
const { preinstall, install, postinstall, prepare } = scripts
const tests = { bin, preinstall, install, postinstall, prepare }
- // A denied package (allowScripts resolves to `false`) still gets its
- // bins linked; only its lifecycle scripts are skipped, matching
- // --ignore-scripts (npm/cli#9681). --dangerously-allow-all-scripts
- // bypasses the gate.
- const scriptsDenied =
- !this.options.dangerouslyAllowAllScripts &&
- isScriptAllowed(node, this.options.allowScripts) === false
+ // allowScripts gate (RFC npm/rfcs#868): `true` runs lifecycle
+ // scripts; `false` and `null` (unreviewed) block. Bypassed by
+ // --dangerously-allow-all-scripts and workspaces (owner-managed).
+ // --ignore-scripts still wins (in #build); bins are never gated.
+ //
+ // Checked on node.target, not the Link: a Link's `resolved` is
+ // node_modules-relative (`file:../../dep`) so it can't match a
+ // project-root-relative policy key; the target carries the realpath
+ // and link specs that script-allowed.js matches on (npm/cli#9498).
+ // For non-links node.target === node, so registry deps are unaffected.
+ const scriptsAllowed =
+ this.options.dangerouslyAllowAllScripts ||
+ node.isWorkspace ||
+ isScriptAllowed(node.target, this.options.allowScripts) === true
for (const [key, has] of Object.entries(tests)) {
if (!has) {
continue
}
- if (key !== 'bin' && scriptsDenied) {
+ if (key !== 'bin' && !scriptsAllowed) {
continue
}
this.#queues[key].push(node)
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js
index db5171ff736..b099d4d72c6 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js
@@ -24,6 +24,8 @@ const debug = require('../debug.js')
const onExit = require('../signal-handling.js')
const optionalSet = require('../optional-set.js')
const relpath = require('../relpath.js')
+const { applyPatchToDir, patchIntegrity } = require('../patch.js')
+const { readFile } = require('node:fs/promises')
const retirePath = require('../retire-path.js')
const treeCheck = require('../tree-check.js')
const Shrinkwrap = require('../shrinkwrap.js')
@@ -49,7 +51,6 @@ const _checkBins = Symbol.for('checkBins')
// TODO tests should not be this deep into internals
const _diffTrees = Symbol.for('diffTrees')
const _createSparseTree = Symbol.for('createSparseTree')
-const _loadShrinkwrapsAndUpdateTrees = Symbol.for('loadShrinkwrapsAndUpdateTrees')
const _reifyNode = Symbol.for('reifyNode')
const _updateAll = Symbol.for('updateAll')
const _updateNames = Symbol.for('updateNames')
@@ -74,7 +75,6 @@ module.exports = cls => class Reifier extends cls {
#omit
#retiredPaths = {}
#retiredUnchanged = {}
- #shrinkwrapInflated = new Set()
#sparseTreeDirs = new Set()
#sparseTreeRoots = new Set()
#linkedActualForDiff = null
@@ -337,7 +337,6 @@ module.exports = cls => class Reifier extends cls {
]],
[_rollbackCreateSparseTree, [
_createSparseTree,
- _loadShrinkwrapsAndUpdateTrees,
_loadBundlesAndUpdateTrees,
_submitQuickAudit,
_unpackNewModules,
@@ -500,7 +499,6 @@ module.exports = cls => class Reifier extends cls {
// and ideal trees.
this.diff = Diff.calculate({
omit: this.#omit,
- shrinkwrapInflated: this.#shrinkwrapInflated,
filterNodes,
actual: this.#linkedActualForDiff || this.actualTree,
ideal: this.idealTree,
@@ -651,39 +649,6 @@ module.exports = cls => class Reifier extends cls {
.then(() => this[_rollbackRetireShallowNodes](er))
}
- // shrinkwrap nodes define their dependency branches with a file, so
- // 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.#shrinkwrapInflated
- const shrinkwraps = this.diff.leaves
- .filter(d => (d.action === 'CHANGE' || d.action === 'ADD' || !d.action) &&
- d.ideal.hasShrinkwrap && !seen.has(d.ideal) &&
- !this[_trashList].has(d.ideal.path))
-
- if (!shrinkwraps.length) {
- return
- }
-
- const timeEnd = time.start('reify:loadShrinkwraps')
-
- const Arborist = this.constructor
- return promiseAllRejectLate(shrinkwraps.map(diff => {
- const node = diff.ideal
- seen.add(node)
- return diff.action ? this[_reifyNode](node) : node
- }))
- .then(nodes => promiseAllRejectLate(nodes.map(node => new Arborist({
- ...this.options,
- path: node.path,
- }).loadVirtual({ root: node, subtreeOnly: true }))))
- // reload the diff and sparse tree because the ideal tree changed
- .then(() => this[_diffTrees]())
- .then(() => this[_createSparseTree]())
- .then(() => this[_loadShrinkwrapsAndUpdateTrees]())
- .then(timeEnd)
- }
-
// create a symlink for Links, extract for Nodes
// return the node object, since we usually want that
// handle optional dep failures here
@@ -791,6 +756,7 @@ module.exports = cls => class Reifier extends cls {
const { content: pkg } = await PackageJson.normalize(node.path)
node.package.scripts = pkg.scripts
}
+ await this.#applyPatch(node)
return
}
@@ -818,10 +784,61 @@ module.exports = cls => class Reifier extends cls {
return symlink(rel, node.path, 'junction')
}
+ // apply a registered patch to a freshly extracted node, after extract and before rebuild
+ async #applyPatch (node) {
+ if (!node.patched) {
+ return
+ }
+ const { path: patchPath, integrity } = node.patched
+
+ // validate the patch file here too, since reify can run on an ideal tree that skipped resolvePatchedDependencies
+ let contents
+ try {
+ contents = await readFile(resolve(this.path, patchPath))
+ } catch {
+ throw Object.assign(
+ new Error(`patch file not found: ${patchPath}`),
+ { code: 'EPATCHNOTFOUND', path: patchPath, node: node.name }
+ )
+ }
+ if (patchIntegrity(contents) !== integrity) {
+ throw Object.assign(
+ new Error(`patch file ${patchPath} does not match the recorded integrity`),
+ { code: 'EPATCHINTEGRITY', path: patchPath, node: node.name }
+ )
+ }
+
+ try {
+ await applyPatchToDir({ patch: contents, cwd: node.path })
+ } catch (er) {
+ if (this.options.ignorePatchFailures) {
+ // the linked side-store keys a package by its patch, so an unpatched package cannot be represented at a patched key and would be trusted on later installs
+ if (node.isInStore) {
+ throw Object.assign(
+ new Error(`Cannot skip the failed patch for ${node.name} under install-strategy=linked. ` +
+ `Fix the patch or install with a different strategy.`),
+ { code: 'EPATCHFAILED', path: patchPath, node: node.name }
+ )
+ }
+ log.warn('patch', `failed to apply ${patchPath} to ${node.name}: ${er.message}`)
+ // the patch was not applied, so do not record it in the lockfile
+ // the lockfile and package.json now disagree, so warn that npm ci will reject the tree
+ log.warn('patch', `${node.name} was installed unpatched; package.json still declares this patch, so the lockfile is out of sync and \`npm ci\` will fail until the patch is fixed or its patchedDependencies entry is removed`)
+ node.patched = null
+ return
+ }
+ throw er
+ }
+ }
+
// if the node is optional, then the failure of the promise is nonfatal
// just add it and its optional set to the trash list.
[_handleOptionalFailure] (node, p) {
- return (node.optional ? p.catch(() => {
+ return (node.optional ? p.catch((er) => {
+ // a declared patch must apply or fail loudly, even on an optional dep
+ if (typeof er?.code === 'string' && er.code.startsWith('EPATCH')) {
+ throw er
+ }
const set = optionalSet(node)
for (const node of set) {
log.verbose('reify', 'failed optional dependency', node.path)
@@ -1278,7 +1295,6 @@ module.exports = cls => class Reifier extends cls {
const node = diff.ideal
const bd = this.#bundleUnpacked.has(node)
- const sw = this.#shrinkwrapInflated.has(node)
const bundleMissing = this.#bundleMissing.has(node)
// check whether we still need to unpack this one.
@@ -1288,8 +1304,6 @@ module.exports = cls => class Reifier extends cls {
!node.isRoot &&
// already unpacked to read bundle
!bd &&
- // already unpacked to read sw
- !sw &&
// already unpacked by another dep's bundle
(bundleMissing || !node.inDepBundle)
@@ -1833,7 +1847,7 @@ module.exports = cls => class Reifier extends cls {
// save the git+https url if it has auth; otherwise, shortcut
const h = req.hosted
const opt = { noCommittish: false }
- if (h.https && h.auth) {
+ if (h.https && (h.auth || h.default === 'https')) {
newSpec = `git+${h.https(opt)}`
} else {
newSpec = h.shortcut(opt)
@@ -1988,6 +2002,8 @@ module.exports = cls => class Reifier extends cls {
// field so defaulting this to an empty array would add that field to
// every package.json file.
bundleDependencies,
+ // resolvePatchedDependencies drops entries orphaned by uninstall; persist that removal
+ patchedDependencies,
} = tree.package
pkgJson.update({
@@ -1996,6 +2012,7 @@ module.exports = cls => class Reifier extends cls {
optionalDependencies,
peerDependencies,
bundleDependencies,
+ patchedDependencies,
})
await pkgJson.save()
}
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/consistent-resolve.js b/deps/npm/node_modules/@npmcli/arborist/lib/consistent-resolve.js
index 890caa32f10..20b119ac9ee 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/consistent-resolve.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/consistent-resolve.js
@@ -26,7 +26,7 @@ const consistentResolve = (resolved, fromPath, toPath, relPaths = false) => {
return `file:${fetchSpec}`
}
if (hosted) {
- return `git+${hosted.auth ? hosted.https(hostedOpt) : hosted.sshurl(hostedOpt)}`
+ return `git+${(hosted.auth || hosted.default === 'https') ? hosted.https(hostedOpt) : hosted.sshurl(hostedOpt)}`
}
if (type === 'git') {
return saveSpec
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/diff.js b/deps/npm/node_modules/@npmcli/arborist/lib/diff.js
index 5a20749ad13..704dc7bafc4 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/diff.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/diff.js
@@ -11,10 +11,9 @@ const { existsSync } = require('node:fs')
const ssri = require('ssri')
class Diff {
- constructor ({ actual, ideal, filterSet, shrinkwrapInflated, omit }) {
+ constructor ({ actual, ideal, filterSet, omit }) {
this.omit = omit
this.filterSet = filterSet
- this.shrinkwrapInflated = shrinkwrapInflated
this.children = []
this.actual = actual
this.ideal = ideal
@@ -36,7 +35,6 @@ class Diff {
actual,
ideal,
filterNodes = [],
- shrinkwrapInflated = new Set(),
omit = new Set(),
}) {
// if there's a filterNode, then:
@@ -102,7 +100,7 @@ class Diff {
}
return depth({
- tree: new Diff({ actual, ideal, filterSet, shrinkwrapInflated, omit }),
+ tree: new Diff({ actual, ideal, filterSet, omit }),
getChildren,
leave,
})
@@ -132,6 +130,16 @@ const getAction = ({ actual, ideal }) => {
return 'CHANGE'
}
+ // a change in patch state requires re-extracting and re-applying
+ if ((ideal.patched?.integrity || null) !== (actual.patched?.integrity || null)) {
+ return 'CHANGE'
+ }
+
+ // a node whose patch was just removed must be re-extracted to revert the patched files
+ if (ideal.patchRemoved) {
+ return 'CHANGE'
+ }
+
const binsExist = ideal.binPaths.every((path) => existsSync(path))
// top nodes, links, and git deps won't have integrity, but do have resolved
@@ -191,26 +199,16 @@ const getChildren = diff => {
unchanged,
removed,
filterSet,
- shrinkwrapInflated,
omit,
} = diff
// Note: we DON'T diff fsChildren themselves, because they are either
- // included in the package contents, or part of some other project, and
- // will never appear in legacy shrinkwraps anyway. but we _do_ include the
- // child nodes of fsChildren, because those are nodes that we are typically
- // responsible for installing.
+ // included in the package contents, or part of some other project.
+ // But we _do_ include the child nodes of fsChildren, because those are
+ // nodes that we are typically 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)
@@ -222,7 +220,6 @@ const getChildren = diff => {
unchanged,
removed,
filterSet,
- shrinkwrapInflated,
omit,
})
}
@@ -241,7 +238,6 @@ const diffNode = ({
unchanged,
removed,
filterSet,
- shrinkwrapInflated,
omit,
}) => {
if (filterSet.size && !(filterSet.has(ideal) || filterSet.has(actual))) {
@@ -264,11 +260,11 @@ const diffNode = ({
// if it's a match, then get its children
// otherwise, this is the child diff node
- if (action || (!shrinkwrapInflated.has(ideal) && ideal.hasShrinkwrap)) {
+ if (action) {
if (action === 'REMOVE') {
removed.push(actual)
}
- children.push(new Diff({ actual, ideal, filterSet, shrinkwrapInflated, omit }))
+ children.push(new Diff({ actual, ideal, filterSet, omit }))
} else {
unchanged.push(ideal)
// !*! Weird dirty hack warning !*!
@@ -307,7 +303,6 @@ const diffNode = ({
unchanged,
removed,
filterSet,
- shrinkwrapInflated,
omit,
}))
}
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/edge.js b/deps/npm/node_modules/@npmcli/arborist/lib/edge.js
index 83a9c18cb6a..1ed2446c809 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/edge.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/edge.js
@@ -109,8 +109,8 @@ class Edge {
}
// NOTE: this condition means we explicitly do not support overriding
- // bundled or shrinkwrapped dependencies
- if (node.hasShrinkwrap || node.inShrinkwrap || node.inBundle) {
+ // bundled dependencies
+ if (node.inDepBundle) {
return depValid(node, this.rawSpec, this.#accept, this.#from)
}
@@ -160,6 +160,26 @@ class Edge {
}
if (this.#from) {
explanation.from = this.#from.explain(null, seen)
+ // note when this edge was created or changed by a root packageExtensions repair on the from node
+ const applied = this.#from.packageExtensionsApplied
+ if (applied) {
+ for (const field of ['dependencies', 'optionalDependencies', 'peerDependencies', 'peerDependenciesMeta']) {
+ if (applied[field]?.includes(this.#name)) {
+ explanation.packageExtensions = { selector: applied.selector, field }
+ break
+ }
+ }
+ }
+ // note when this edge was created or changed by a root .npm-extension transformManifest repair on the from node
+ const transformed = this.#from.npmExtensionApplied
+ if (transformed) {
+ for (const field of ['dependencies', 'optionalDependencies', 'peerDependencies', 'peerDependenciesMeta']) {
+ if (transformed[field]?.includes(this.#name)) {
+ explanation.npmExtension = { extensionPoint: transformed.extensionPoint, field }
+ break
+ }
+ }
+ }
}
this.#explanation = explanation
}
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/index.js b/deps/npm/node_modules/@npmcli/arborist/lib/index.js
index 5baaee6ee7c..4236427d6c4 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/index.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/index.js
@@ -4,3 +4,5 @@ module.exports.Node = require('./node.js')
module.exports.Link = require('./link.js')
module.exports.Edge = require('./edge.js')
module.exports.Shrinkwrap = require('./shrinkwrap.js')
+module.exports.PackageExtensions = require('./package-extensions.js')
+module.exports.NpmExtension = require('./npm-extension.js')
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/isolated-classes.js b/deps/npm/node_modules/@npmcli/arborist/lib/isolated-classes.js
index fc119119664..c5b7abbb64a 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/isolated-classes.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/isolated-classes.js
@@ -9,7 +9,6 @@ class IsolatedNode {
edgesIn = new Set()
edgesOut = new CaseInsensitiveMap()
fsChildren = new Set()
- hasShrinkwrap = false
integrity = null
inventory = new Map()
isInStore = false
@@ -19,6 +18,7 @@ class IsolatedNode {
linksIn = new Set()
meta = { loadedFromDisk: false }
optional = false
+ patched = null
parent = null
root = null
tops = new Set()
@@ -55,6 +55,9 @@ class IsolatedNode {
if (options.optional) {
this.optional = true
}
+ if (options.patched) {
+ this.patched = options.patched
+ }
}
get isRoot () {
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/node.js b/deps/npm/node_modules/@npmcli/arborist/lib/node.js
index 87b0ac41740..13370a50ab4 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/node.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/node.js
@@ -82,7 +82,6 @@ class Node {
fsChildren,
fsParent,
global = false,
- hasShrinkwrap,
inert = false,
installLinks = false,
integrity,
@@ -94,7 +93,10 @@ class Node {
name, // allow setting name explicitly when we haven't set a path yet
optional = true,
overrides,
+ packageExtensionsApplied = null,
+ npmExtensionApplied = null,
parent,
+ patched = null,
path,
peer = true,
realpath,
@@ -170,7 +172,14 @@ class Node {
}
}
this.integrity = integrity || this.package._integrity || null
- this.hasShrinkwrap = hasShrinkwrap || this.package._hasShrinkwrap || false
+ // Patch record { path, integrity } or null, set from patchedDependencies or the lockfile.
+ this.patched = patched || null
+ // Provenance for a root packageExtensions repair applied to this node's manifest, or null.
+ // Shape: { selector, dependencies?, optionalDependencies?, peerDependencies?, peerDependenciesMeta? }.
+ this.packageExtensionsApplied = packageExtensionsApplied
+ // Provenance for a root .npm-extension transformManifest repair applied to this node's manifest, or null.
+ // Shape: { extensionPoint, dependencies?, optionalDependencies?, peerDependencies?, peerDependenciesMeta? }.
+ this.npmExtensionApplied = npmExtensionApplied
this.installLinks = installLinks
this.legacyPeerDeps = legacyPeerDeps
@@ -1102,8 +1111,8 @@ class Node {
// 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, explicitRequest = false) {
- // not allowed to mess with shrinkwraps or bundles
- if (this.inDepBundle || this.inShrinkwrap) {
+ // not allowed to mess with bundles
+ if (this.inDepBundle) {
return false
}
@@ -1250,11 +1259,6 @@ class Node {
treeCheck(this)
}
- get inShrinkwrap () {
- return this.parent &&
- (this.parent.hasShrinkwrap || this.parent.inShrinkwrap)
- }
-
get parent () {
// setter prevents _parent from being this
return this[_parent]
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/npm-extension.js b/deps/npm/node_modules/@npmcli/arborist/lib/npm-extension.js
new file mode 100644
index 00000000000..505920968be
--- /dev/null
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/npm-extension.js
@@ -0,0 +1,237 @@
+// Root-owned `.npm-extension.{mjs,cjs}`: an imperative `transformManifest(pkg, context)` extension point that repairs third-party manifests before Arborist reads a candidate's dependency edges.
+// See RFC: https://github.com/npm/rfcs/pull/903
+// This module discovers and hashes the root extension file, loads its `transformManifest` export, and applies it to a deeply isolated manifest copy, returning an extended manifest plus minimal provenance.
+// It never mutates the input manifest or any shared cache object.
+const { resolve, sep } = require('node:path')
+const { readFileSync, existsSync } = require('node:fs')
+const { pathToFileURL } = require('node:url')
+const { isDeepStrictEqual } = require('node:util')
+const { log } = require('proc-log')
+const ssri = require('ssri')
+const { EXTENSION_FIELDS } = require('./package-extensions.js')
+
+const EXTENSION_POINT = 'transformManifest'
+
+// The two supported module formats and their default discovery filenames.
+const FORMATS = [
+ { ext: 'mjs', file: '.npm-extension.mjs' },
+ { ext: 'cjs', file: '.npm-extension.cjs' },
+]
+
+const err = (message, code, extra = {}) =>
+ Object.assign(new Error(message), { code, ...extra })
+
+// Read a file's bytes, or null when it does not exist.
+const readBytes = path => {
+ try {
+ return readFileSync(path)
+ } catch (e) {
+ if (e.code === 'ENOENT') {
+ return null
+ }
+ throw e
+ }
+}
+
+// Resolve which extension file to load, returning { path, format, bytes } or null when none is present.
+// A configured `extension-file` wins over default discovery; it must resolve inside the project root and use a `.mjs` or `.cjs` extension.
+// When both default files exist npm fails rather than choosing one implicitly.
+const discover = (root, extensionFile) => {
+ if (extensionFile) {
+ const path = resolve(root, extensionFile)
+ if (path !== root && !path.startsWith(root + sep)) {
+ throw err(`extension-file "${extensionFile}" must resolve inside the project root`, 'ENPMEXTENSIONPATH')
+ }
+ const format = FORMATS.find(f => path.endsWith(`.${f.ext}`))?.ext
+ if (!format) {
+ throw err(`extension-file "${extensionFile}" must use a .mjs or .cjs extension`, 'ENPMEXTENSIONPATH')
+ }
+ const bytes = readBytes(path)
+ if (bytes === null) {
+ throw err(`extension-file "${extensionFile}" was not found`, 'ENPMEXTENSIONPATH')
+ }
+ return { path, format, bytes }
+ }
+ const found = FORMATS
+ .map(f => ({ path: resolve(root, f.file), format: f.ext, bytes: readBytes(resolve(root, f.file)) }))
+ .filter(f => f.bytes !== null)
+ if (found.length > 1) {
+ throw err('found both .npm-extension.mjs and .npm-extension.cjs; keep only one', 'ENPMEXTENSIONDUP')
+ }
+ return found[0] || null
+}
+
+// Hash the selected extension file: a format-tagged prefix plus the raw file bytes, using npm's lockfile digest encoding.
+// The prefix keeps `.mjs` and `.cjs` files with identical bytes distinct, and excludes any path so the digest is machine-independent.
+const hashFile = (format, bytes) =>
+ ssri.fromData(
+ Buffer.concat([Buffer.from(`npm-extension:v1:${format}\n`), bytes]),
+ { algorithms: ['sha512'] }
+ ).toString()
+
+class NpmExtension {
+ #cache = new Map()
+ #transform = null
+
+ constructor ({ root, extensionFile = null } = {}) {
+ this.root = root
+ this.path = null
+ this.format = null
+ this.hash = null
+
+ const selected = root ? discover(root, extensionFile) : null
+ if (!selected) {
+ this.present = false
+ return
+ }
+ this.present = true
+ this.path = selected.path
+ this.format = selected.format
+ this.hash = hashFile(selected.format, selected.bytes)
+ }
+
+ // Import the extension module and capture its `transformManifest` export.
+ // ESM files are loaded with dynamic import; CommonJS files with require.
+ // The export must be a function; anything else fails the install.
+ async load () {
+ if (!this.present) {
+ return
+ }
+ // Key the module load by the file hash so a changed file is reloaded rather than served stale from a module cache within one process.
+ let mod
+ if (this.format === 'mjs') {
+ mod = await import(`${pathToFileURL(this.path).href}?h=${this.hash}`)
+ } else {
+ delete require.cache[require.resolve(this.path)]
+ mod = require(this.path)
+ }
+ const transform = mod?.transformManifest ?? mod?.default?.transformManifest
+ if (typeof transform !== 'function') {
+ throw err(`.npm-extension must export a transformManifest function`, 'ENPMEXTENSIONSHAPE')
+ }
+ this.#transform = transform
+ }
+
+ // Apply transformManifest to a candidate manifest, returning { pkg, applied } or null when nothing changed.
+ // Results are cached once per resolved package identity; consumers get a deeply isolated copy so they cannot mutate the cached effective manifest.
+ // Pass { memoize: false } to run without caching, e.g. a staleness probe over partial lockfile manifests that must not seed the cache used by full-manifest fetches.
+ apply (pkg, { memoize = true } = {}) {
+ if (!this.#transform || !pkg?.name) {
+ return null
+ }
+ const key = this.#identity(pkg)
+ let result
+ if (this.#cache.has(key)) {
+ result = this.#cache.get(key)
+ } else {
+ result = this.#run(pkg)
+ if (memoize) {
+ this.#cache.set(key, result)
+ }
+ }
+ return result && { pkg: structuredClone(result.pkg), applied: structuredClone(result.applied) }
+ }
+
+ // Identity key for the transform cache: package integrity when available, otherwise resolved source plus name and version.
+ #identity (pkg) {
+ return pkg._integrity || `${pkg._resolved || ''}:${pkg.name}@${pkg.version || ''}`
+ }
+
+ // Run transformManifest on a deeply isolated copy and validate the result.
+ // Returns { pkg, applied } when dependency or peer metadata changed, or null when it did not.
+ #run (pkg) {
+ const context = {
+ log: message => log.silly('npm-extension', message),
+ root: this.root,
+ extensionPoint: EXTENSION_POINT,
+ }
+ let returned
+ try {
+ returned = this.#transform(structuredClone(pkg), context)
+ } catch (e) {
+ throw err(
+ `.npm-extension transformManifest threw while processing ${pkg.name}@${pkg.version}: ${e.message}`,
+ 'ENPMEXTENSIONTHROW', { pkgid: `${pkg.name}@${pkg.version}` })
+ }
+ if (returned && typeof returned.then === 'function') {
+ throw err(
+ `.npm-extension transformManifest must return a manifest synchronously, not a promise, for ${pkg.name}@${pkg.version}`,
+ 'ENPMEXTENSIONRETURN', { pkgid: `${pkg.name}@${pkg.version}` })
+ }
+ if (!returned || typeof returned !== 'object' || Array.isArray(returned)) {
+ throw err(
+ `.npm-extension transformManifest must return a manifest object for ${pkg.name}@${pkg.version}`,
+ 'ENPMEXTENSIONRETURN', { pkgid: `${pkg.name}@${pkg.version}` })
+ }
+ // Only dependency and peer fields may change; any other field the returned manifest explicitly alters is rejected.
+ // Fields the returned object omits are left untouched, so a handler may return a new object with only the fields it repairs.
+ for (const k of Object.keys(returned)) {
+ if (!EXTENSION_FIELDS.includes(k) && !isDeepStrictEqual(returned[k], pkg[k])) {
+ throw err(
+ `.npm-extension transformManifest changed unsupported field "${k}" on ${pkg.name}@${pkg.version}; only ${EXTENSION_FIELDS.join(', ')} may change`,
+ 'ENPMEXTENSIONFIELD', { pkgid: `${pkg.name}@${pkg.version}`, field: k })
+ }
+ }
+ // Build the effective manifest from the normalized baseline plus the returned allowlisted fields.
+ // A field the handler omits is left as the baseline; delete individual entries by returning a field object without them.
+ const next = { ...pkg }
+ for (const field of EXTENSION_FIELDS) {
+ if (returned[field] === undefined) {
+ continue
+ }
+ this.#validateField(field, returned[field], pkg)
+ next[field] = returned[field]
+ }
+ const applied = this.#provenance(pkg, next)
+ return applied && { pkg: next, applied }
+ }
+
+ // Validate a returned allowlisted field and its entries, so invalid output fails with .npm-extension and package context.
+ // Dependency maps hold version strings; peerDependenciesMeta holds metadata objects.
+ #validateField (field, value, pkg) {
+ const fail = (suffix) => err(
+ `.npm-extension transformManifest set ${suffix} to an invalid value on ${pkg.name}@${pkg.version}`,
+ 'ENPMEXTENSIONVALUE', { pkgid: `${pkg.name}@${pkg.version}`, field })
+ if (value === null || typeof value !== 'object' || Array.isArray(value)) {
+ throw fail(field)
+ }
+ for (const [name, entry] of Object.entries(value)) {
+ if (field === 'peerDependenciesMeta') {
+ if (entry === null || typeof entry !== 'object' || Array.isArray(entry)) {
+ throw fail(`${field}.${name}`)
+ }
+ } else if (typeof entry !== 'string') {
+ throw fail(`${field}.${name}`)
+ }
+ }
+ }
+
+ // Minimal provenance: the extension point plus, for each changed allowlisted field, a sorted array of affected dependency names.
+ // Returns null when nothing changed.
+ #provenance (before, after) {
+ const applied = { extensionPoint: EXTENSION_POINT }
+ let changed = false
+ for (const field of EXTENSION_FIELDS) {
+ const b = before[field] || {}
+ const a = after[field] || {}
+ const names = [...new Set([...Object.keys(b), ...Object.keys(a)])]
+ .filter(n => !isDeepStrictEqual(b[n], a[n]))
+ .sort()
+ if (names.length) {
+ applied[field] = names
+ changed = true
+ }
+ }
+ return changed ? applied : null
+ }
+}
+
+// Whether a directory contains any default .npm-extension file; a non-throwing existence check used for non-root workspace warnings.
+const hasExtensionFile = dir => FORMATS.some(f => existsSync(resolve(dir, f.file)))
+
+module.exports = NpmExtension
+module.exports.NpmExtension = NpmExtension
+module.exports.discover = discover
+module.exports.hasExtensionFile = hasExtensionFile
+module.exports.hashFile = hashFile
+module.exports.EXTENSION_POINT = EXTENSION_POINT
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/package-extensions.js b/deps/npm/node_modules/@npmcli/arborist/lib/package-extensions.js
new file mode 100644
index 00000000000..870ac4cbeaf
--- /dev/null
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/package-extensions.js
@@ -0,0 +1,236 @@
+// Root-owned `packageExtensions`: declarative repairs to third-party manifests applied before Arborist reads a candidate's dependency edges.
+// See RFC: https://github.com/npm/rfcs/pull/889
+// This module is pure: it parses and validates the root rule set, matches a candidate manifest by name and version, and returns an extended manifest copy plus minimal provenance.
+// It never mutates the input manifest or any shared cache object.
+const semver = require('semver')
+const ssri = require('ssri')
+const validateName = require('validate-npm-package-name')
+
+// The only manifest fields a package extension may add or correct, because they are the fields that affect dependency and peer resolution.
+const EXTENSION_FIELDS = [
+ 'dependencies',
+ 'optionalDependencies',
+ 'peerDependencies',
+ 'peerDependenciesMeta',
+]
+
+// The two normal dependency fields; a name may exist in only one of them.
+const NORMAL_DEP_FIELDS = ['dependencies', 'optionalDependencies']
+
+const err = (message, code, extra = {}) =>
+ Object.assign(new Error(message), { code, ...extra })
+
+// Parse a selector key into { name, range }, where range is null for a name-only key.
+// Selectors are a package name with an optional semver range; dist-tags, git, file, directory, url, and alias specs are rejected.
+const parseSelector = key => {
+ if (typeof key !== 'string' || !key) {
+ throw err(`Invalid packageExtensions selector: ${JSON.stringify(key)}`, 'EEXTENSIONSELECTOR')
+ }
+ // The separator @ is the first @ after a leading scope @.
+ const at = key.indexOf('@', key.startsWith('@') ? 1 : 0)
+ const name = at === -1 ? key : key.slice(0, at)
+ const range = at === -1 ? null : key.slice(at + 1)
+
+ const { validForOldPackages, validForNewPackages } = validateName(name)
+ if (!validForOldPackages && !validForNewPackages) {
+ throw err(`Invalid package name in packageExtensions selector: "${key}"`, 'EEXTENSIONSELECTOR', { selector: key })
+ }
+ // A blank range such as "foo@" is malformed; the name-only form "foo" is how you match every version.
+ if (range !== null && range.trim() === '') {
+ throw err(
+ `Invalid packageExtensions selector: "${key}". Use the name only to match every version.`,
+ 'EEXTENSIONSELECTOR', { selector: key })
+ }
+ // A versioned selector must be a valid semver range, which rejects dist-tags, git, file, url, and alias specs.
+ if (range !== null && semver.validRange(range, { loose: true }) === null) {
+ throw err(
+ `Invalid version range in packageExtensions selector: "${key}". Selectors accept a package name with an optional semver range only.`,
+ 'EEXTENSIONSELECTOR', { selector: key })
+ }
+ return { name, range }
+}
+
+// A selector matches a candidate manifest by its own name and version.
+// Name-only selectors match every version, including non-semver versions.
+// Versioned selectors only match versions that parse as semver and satisfy the range.
+const rangeMatches = (range, version) => {
+ if (range === null) {
+ return true
+ }
+ return semver.valid(version, { loose: true }) !== null &&
+ semver.satisfies(version, range, { loose: true })
+}
+
+// Validate a single selector's extension object before it is ever applied.
+const validateExtensionObject = (key, ext) => {
+ if (ext === null || typeof ext !== 'object' || Array.isArray(ext)) {
+ throw err(`packageExtensions["${key}"] must be an object`, 'EEXTENSIONVALUE', { selector: key })
+ }
+ for (const field of Object.keys(ext)) {
+ if (!EXTENSION_FIELDS.includes(field)) {
+ throw err(
+ `packageExtensions["${key}"] has unsupported field "${field}". Supported fields: ${EXTENSION_FIELDS.join(', ')}.`,
+ 'EEXTENSIONFIELD', { selector: key, field })
+ }
+ const val = ext[field]
+ if (val === null || typeof val !== 'object' || Array.isArray(val)) {
+ throw err(`packageExtensions["${key}"].${field} must be an object`, 'EEXTENSIONVALUE', { selector: key, field })
+ }
+ }
+ // Deletion is not supported in v1, so a null, false, or "-" value is an error.
+ for (const field of [...NORMAL_DEP_FIELDS, 'peerDependencies']) {
+ for (const [name, spec] of Object.entries(ext[field] || {})) {
+ if (spec === null || spec === false || spec === '-') {
+ throw err(
+ `packageExtensions["${key}"].${field}.${name} attempts deletion, which is not supported.`,
+ 'EEXTENSIONDELETE', { selector: key, field, name })
+ }
+ }
+ }
+ // Each peerDependenciesMeta entry must be a non-null metadata object, never a deletion sentinel or primitive.
+ for (const [name, meta] of Object.entries(ext.peerDependenciesMeta || {})) {
+ if (meta === null || typeof meta !== 'object' || Array.isArray(meta)) {
+ throw err(
+ `packageExtensions["${key}"].peerDependenciesMeta.${name} must be an object`,
+ 'EEXTENSIONVALUE', { selector: key, field: 'peerDependenciesMeta', name })
+ }
+ }
+}
+
+// Apply a matched extension to a manifest, returning { pkg, applied } where pkg is a copy with extended fields and applied is minimal provenance.
+// The input manifest is never mutated.
+const applyExtension = (pkg, { key, ext }) => {
+ const applied = { selector: key }
+
+ // Clone only the fields we may touch; the rest of the manifest is shared by reference since it is never mutated.
+ const next = { ...pkg }
+ for (const field of EXTENSION_FIELDS) {
+ if (pkg[field] && typeof pkg[field] === 'object') {
+ next[field] = field === 'peerDependenciesMeta'
+ ? Object.fromEntries(Object.entries(pkg[field]).map(([n, m]) => [n, { ...m }]))
+ : { ...pkg[field] }
+ }
+ }
+
+ // dependencies and optionalDependencies add missing names only.
+ // A name already declared in either normal dependency field is an error, which also prevents moving a name between the fields.
+ for (const field of NORMAL_DEP_FIELDS) {
+ const adds = ext[field]
+ if (!adds) {
+ continue
+ }
+ for (const [name, spec] of Object.entries(adds)) {
+ for (const existingField of NORMAL_DEP_FIELDS) {
+ if (next[existingField] && name in next[existingField]) {
+ throw err(
+ `packageExtensions["${key}"].${field}.${name} conflicts with the package's existing ${existingField}.${name}. Use overrides to change a dependency version; packageExtensions only adds missing dependencies.`,
+ 'EEXTENSIONDUPDEP', { selector: key, field, name, existingField })
+ }
+ }
+ next[field] = next[field] || {}
+ next[field][name] = spec
+ ;(applied[field] = applied[field] || []).push(name)
+ }
+ }
+
+ // peerDependencies shallow-merges by peer name, and the extension value replaces an existing range.
+ if (ext.peerDependencies) {
+ next.peerDependencies = next.peerDependencies || {}
+ for (const [name, spec] of Object.entries(ext.peerDependencies)) {
+ next.peerDependencies[name] = spec
+ ;(applied.peerDependencies = applied.peerDependencies || []).push(name)
+ }
+ }
+
+ // peerDependenciesMeta merges by peer name, then shallow-merges each meta object so an extension can add optional without dropping other meta keys.
+ if (ext.peerDependenciesMeta) {
+ next.peerDependenciesMeta = next.peerDependenciesMeta || {}
+ for (const [name, meta] of Object.entries(ext.peerDependenciesMeta)) {
+ next.peerDependenciesMeta[name] = { ...next.peerDependenciesMeta[name], ...meta }
+ ;(applied.peerDependenciesMeta = applied.peerDependenciesMeta || []).push(name)
+ // Every peerDependenciesMeta entry an extension adds must correspond to a peerDependencies entry present after extension application.
+ if (!next.peerDependencies || !(name in next.peerDependencies)) {
+ throw err(
+ `packageExtensions["${key}"].peerDependenciesMeta.${name} has no corresponding peerDependencies.${name} after extension application.`,
+ 'EEXTENSIONORPHANMETA', { selector: key, name })
+ }
+ }
+ }
+
+ return { pkg: next, applied }
+}
+
+// Deterministic JSON for hashing: keys sorted lexicographically at every level, string and number values preserved exactly, no insignificant whitespace.
+const canonicalStringify = val => {
+ if (Array.isArray(val)) {
+ return `[${val.map(canonicalStringify).join(',')}]`
+ }
+ if (val && typeof val === 'object') {
+ return `{${Object.keys(val).sort()
+ .map(k => `${JSON.stringify(k)}:${canonicalStringify(val[k])}`)
+ .join(',')}}`
+ }
+ return JSON.stringify(val)
+}
+
+// Hash the canonical form of the root packageExtensions object using npm's existing lockfile digest encoding.
+const canonicalHash = packageExtensions =>
+ ssri.fromData(canonicalStringify(packageExtensions), { algorithms: ['sha512'] }).toString()
+
+class PackageExtensions {
+ constructor (raw) {
+ this.raw = raw
+ this.present = raw !== undefined
+ this.selectors = []
+ this.hash = null
+
+ if (!this.present) {
+ return
+ }
+ if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {
+ throw err('packageExtensions must be an object', 'EEXTENSIONROOT')
+ }
+ for (const [key, ext] of Object.entries(raw)) {
+ const { name, range } = parseSelector(key)
+ validateExtensionObject(key, ext)
+ this.selectors.push({ key, name, range, ext })
+ }
+ this.hash = canonicalHash(raw)
+ }
+
+ // Non-throwing check used for warnings: whether any selector matches the candidate.
+ wouldMatch (name, version) {
+ return this.selectors.some(s => s.name === name && rangeMatches(s.range, version))
+ }
+
+ // Return the single selector matching a candidate manifest, or null.
+ // Throws EEXTENSIONCONFLICT when more than one selector matches the same candidate.
+ match (name, version) {
+ const matches = this.selectors.filter(s => s.name === name && rangeMatches(s.range, version))
+ if (matches.length > 1) {
+ const keys = matches.map(s => `"${s.key}"`).join(', ')
+ throw err(
+ `Multiple packageExtensions selectors match ${name}@${version}: ${keys}. Narrow or remove one of the overlapping rules.`,
+ 'EEXTENSIONCONFLICT', { name, version, selectors: matches.map(s => s.key) })
+ }
+ return matches[0] || null
+ }
+
+ // Apply the matching extension to a manifest copy, returning { pkg, applied } or null when no selector matches.
+ // Throws on selector conflict or invalid merge.
+ apply (pkg) {
+ if (!this.present || !this.selectors.length || !pkg || !pkg.name) {
+ return null
+ }
+ const sel = this.match(pkg.name, pkg.version)
+ return sel ? applyExtension(pkg, sel) : null
+ }
+}
+
+module.exports = PackageExtensions
+module.exports.PackageExtensions = PackageExtensions
+module.exports.parseSelector = parseSelector
+module.exports.rangeMatches = rangeMatches
+module.exports.canonicalHash = canonicalHash
+module.exports.canonicalStringify = canonicalStringify
+module.exports.EXTENSION_FIELDS = EXTENSION_FIELDS
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/patch.js b/deps/npm/node_modules/@npmcli/arborist/lib/patch.js
new file mode 100644
index 00000000000..51d3c187860
--- /dev/null
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/patch.js
@@ -0,0 +1,111 @@
+// Native dependency patching helpers shared across build-ideal-tree and reify.
+// Patches are plain unified diffs (git apply-compatible) applied with jsdiff using a fuzz factor of 0 so that any context drift fails loudly.
+const { applyPatch, parsePatch } = require('diff')
+const ssri = require('ssri')
+const fs = require('node:fs')
+const { promises: fsp } = fs
+const { resolve, relative, dirname, isAbsolute } = require('node:path')
+
+// Compute the SSRI integrity of a patch file's contents.
+// Accepts a string or Buffer and returns a sha512 SSRI string.
+const patchIntegrity = data =>
+ ssri.fromData(Buffer.isBuffer(data) ? data : Buffer.from(data, 'utf8'), {
+ algorithms: ['sha512'],
+ }).toString()
+
+// Strip a leading git-style "a/" or "b/" prefix from a diff path.
+const stripPrefix = file => file.replace(/^[ab]\//, '')
+
+// True when a diff path points at /dev/null, signalling a file add or delete.
+const isDevNull = file => !file || file === '/dev/null' || /(^|\/)\.dev\/null$/.test(file)
+
+const patchError = (message, code, file) =>
+ Object.assign(new Error(message), { code, file })
+
+// Resolve a diff path under cwd and refuse anything that escapes the package directory.
+const containedTarget = (cwd, file) => {
+ const target = resolve(cwd, file)
+ const rel = relative(cwd, target)
+ if (!rel || rel.startsWith('..') || isAbsolute(rel)) {
+ throw patchError(`patch path escapes the package directory: ${file}`, 'EPATCHUNSAFE', file)
+ }
+ return target
+}
+
+// Run a parsed file patch against a source string with fuzz 0.
+// Returns the patched text, or throws EPATCHFAILED on any context mismatch.
+const strictApply = (source, filePatch, file) => {
+ const patched = applyPatch(source, filePatch, { fuzzFactor: 0 })
+ if (patched === false) {
+ throw patchError(`patch could not be applied to ${file}`, 'EPATCHFAILED', file)
+ }
+ return patched
+}
+
+// Apply a single parsed file patch under cwd.
+// Handles modified, added (--- /dev/null) and deleted (+++ /dev/null) files.
+const applyFilePatch = async (filePatch, cwd) => {
+ const isAdd = isDevNull(filePatch.oldFileName)
+ const isDelete = isDevNull(filePatch.newFileName)
+
+ if (isDelete) {
+ const file = stripPrefix(filePatch.oldFileName)
+ const target = containedTarget(cwd, file)
+ // verify the file still matches the diff before removing it
+ const source = await fsp.readFile(target, 'utf8').catch(() => {
+ throw patchError(`patch target to delete is missing: ${file}`, 'EPATCHFAILED', file)
+ })
+ strictApply(source, filePatch, file)
+ await fsp.rm(target, { force: true })
+ return
+ }
+
+ const file = stripPrefix(filePatch.newFileName)
+ const target = containedTarget(cwd, file)
+
+ if (isAdd) {
+ // a new file must not already exist, otherwise the tarball drifted
+ if (fs.existsSync(target)) {
+ throw patchError(`patch adds a file that already exists: ${file}`, 'EPATCHFAILED', file)
+ }
+ const created = strictApply('', filePatch, file)
+ await fsp.mkdir(dirname(target), { recursive: true })
+ await fsp.writeFile(target, created)
+ return
+ }
+
+ const source = await fsp.readFile(target, 'utf8').catch(() => {
+ throw patchError(`patch target is missing: ${file}`, 'EPATCHFAILED', file)
+ })
+ const mode = (await fsp.stat(target)).mode
+ const patched = strictApply(source, filePatch, file)
+ await fsp.writeFile(target, patched)
+ await fsp.chmod(target, mode)
+}
+
+// Apply a unified diff to the package extracted at `cwd`.
+// `patch` is the raw diff contents (string or Buffer).
+// Throws with code EPATCHFAILED on any hunk or file that cannot be applied.
+const applyPatchToDir = async ({ patch, cwd }) => {
+ const filePatches = parsePatch(patch.toString('utf8'))
+ for (const filePatch of filePatches) {
+ // jsdiff emits an empty trailing patch for some inputs; skip those.
+ if (!filePatch.hunks.length && isDevNull(filePatch.oldFileName) && isDevNull(filePatch.newFileName)) {
+ continue
+ }
+ try {
+ await applyFilePatch(filePatch, cwd)
+ } catch (er) {
+ // re-code raw filesystem errors so a patch failure is never mistaken for an optional-install skip
+ if (typeof er?.code === 'string' && er.code.startsWith('EPATCH')) {
+ throw er
+ }
+ throw Object.assign(new Error(`failed to apply patch: ${er.message}`), { code: 'EPATCHFAILED', cause: er })
+ }
+ }
+}
+
+module.exports = {
+ applyPatchToDir,
+ patchIntegrity,
+}
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/patched-dependencies.js b/deps/npm/node_modules/@npmcli/arborist/lib/patched-dependencies.js
new file mode 100644
index 00000000000..411406f0df7
--- /dev/null
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/patched-dependencies.js
@@ -0,0 +1,168 @@
+// Resolve the root patchedDependencies map against an ideal tree.
+// Attaches node.patched = { path, integrity } to each matched node.
+// Enforces the failure modes (workspace-member entry, missing file, unused patch, non-registry target, ambiguous selectors) as hard errors.
+const semver = require('semver')
+const npa = require('npm-package-arg')
+const { log } = require('proc-log')
+const { resolve, relative, isAbsolute } = require('node:path')
+const { readFile } = require('node:fs/promises')
+const { patchIntegrity } = require('./patch.js')
+
+// Split a selector key into { name, spec }. spec is null for a name-only key.
+const parseSelector = key => {
+ const at = key.indexOf('@', 1)
+ return at === -1
+ ? { name: key, spec: null }
+ : { name: key.slice(0, at), spec: key.slice(at + 1) }
+}
+
+const err = (message, code, extra = {}) =>
+ Object.assign(new Error(message), { code, ...extra })
+
+// Pick the most specific range among several that all match a version.
+// Returns the strict subset, or throws when ordering is ambiguous.
+// semver.subset is transitive, so the running minimum is a subset of every range it did not throw on.
+const pickRange = (ranges, name, version) => {
+ let best = ranges[0]
+ for (const r of ranges.slice(1)) {
+ if (semver.subset(r.spec, best.spec, { loose: true })) {
+ best = r
+ } else if (!semver.subset(best.spec, r.spec, { loose: true })) {
+ throw err(
+ `Ambiguous patch selectors for ${name}@${version}: ` +
+ `"${name}@${best.spec}" and "${name}@${r.spec}" overlap but neither ` +
+ `is a subset. Add an exact "${name}@${version}" entry to disambiguate.`,
+ 'EPATCHAMBIGUOUS'
+ )
+ }
+ }
+ return best
+}
+
+// Choose the winning selector for a node: exact > range subset > name-only.
+const matchSelector = (selectors, node) => {
+ const { name, version } = node
+ const matches = selectors.filter(s => s.name === name)
+ if (!matches.length) {
+ return null
+ }
+
+ const exact = matches.find(s =>
+ s.spec && semver.valid(s.spec) && semver.eq(s.spec, version, { loose: true }))
+ if (exact) {
+ return exact
+ }
+
+ const ranges = matches.filter(s =>
+ s.spec && !semver.valid(s.spec) && semver.satisfies(version, s.spec, { loose: true }))
+ if (ranges.length) {
+ return pickRange(ranges, name, version)
+ }
+
+ return matches.find(s => s.spec === null) || null
+}
+
+const resolvePatchedDependencies = async (tree, { path, allowUnusedPatches, rm }) => {
+ const patchedDependencies = tree.package?.patchedDependencies || {}
+ const selectors = Object.entries(patchedDependencies)
+ .map(([key, patchPath]) => ({ ...parseSelector(key), key, patchPath }))
+
+ // cache patch file integrity by path so shared diffs are read once
+ const integrityCache = new Map()
+ const readPatch = async patchPath => {
+ if (integrityCache.has(patchPath)) {
+ return integrityCache.get(patchPath)
+ }
+ // patch files must live inside the project so the patch set stays auditable
+ const abs = resolve(path, patchPath)
+ const rel = relative(path, abs)
+ if (!rel || rel.startsWith('..') || isAbsolute(rel)) {
+ throw err(`patch path escapes the project: ${patchPath}`, 'EPATCHUNSAFE', { path: patchPath })
+ }
+ let contents
+ try {
+ contents = await readFile(abs)
+ } catch {
+ throw err(`patch file not found: ${patchPath}`, 'EPATCHNOTFOUND', { path: patchPath })
+ }
+ const integrity = patchIntegrity(contents)
+ integrityCache.set(patchPath, integrity)
+ return integrity
+ }
+
+ const usedKeys = new Set()
+ for (const node of tree.inventory.values()) {
+ // patchedDependencies is honoured only in the root manifest
+ if (node.isWorkspace) {
+ // Link.package already delegates to its target's package
+ const pkg = node.package
+ if (pkg?.patchedDependencies && Object.keys(pkg.patchedDependencies).length) {
+ throw err(
+ `patchedDependencies is only supported in the root package.json, ` +
+ `but was found in workspace "${node.name}". Move the entry to the root.`,
+ 'EPATCHWORKSPACE',
+ { workspace: node.name }
+ )
+ }
+ continue
+ }
+ if (node.isProjectRoot) {
+ continue
+ }
+
+ const selector = matchSelector(selectors, node)
+ if (!selector) {
+ // a node that was patched but no longer matches a selector must be re-extracted to revert its files
+ if (node.patched) {
+ node.patchRemoved = true
+ }
+ node.patched = null
+ continue
+ }
+
+ // a non-registry consumer edge (file:, git:, http(s)) means there is no registry tarball to patch; npm: aliases stay registry.
+ // checking edges (not isRegistryDependency) avoids rejecting an edgeless node, which is still a registry dep.
+ if ([...node.edgesIn].some(e => e.spec && !npa(e.spec).registry)) {
+ throw err(
+ `Cannot patch non-registry dependency ${node.name}@${node.version} ` +
+ `(selector "${selector.key}"). Only registry dependencies can be patched.`,
+ 'EPATCHNONREGISTRY',
+ { node: node.name }
+ )
+ }
+
+ const integrity = await readPatch(selector.patchPath)
+ node.patched = { path: selector.patchPath, integrity }
+ usedKeys.add(selector.key)
+ }
+
+ if (selectors.length) {
+ const unused = selectors.filter(s => !usedKeys.has(s.key))
+
+ // an explicit `npm uninstall <name>` orphans that package's patch entry, so drop it instead of failing
+ const removed = new Set(rm)
+ const dropped = unused.filter(s => removed.has(s.name))
+ if (dropped.length) {
+ const patched = { ...tree.package.patchedDependencies }
+ for (const s of dropped) {
+ delete patched[s.key]
+ log.notice('patch', `Removing patch entry "${s.key}" for uninstalled ${s.name}; left ${s.patchPath} in place.`)
+ }
+ // undefined drops the key entirely when reify writes package.json
+ tree.package.patchedDependencies = Object.keys(patched).length ? patched : undefined
+ }
+
+ const stillUnused = unused.filter(s => !removed.has(s.name))
+ if (stillUnused.length && !allowUnusedPatches) {
+ throw err(
+ `The following patches were registered but matched no installed ` +
+ `package:\n${stillUnused.map(s => ` ${s.key} -> ${s.patchPath}`).join('\n')}\n` +
+ `Use --allow-unused-patches to install anyway.`,
+ 'EPATCHUNUSED',
+ { unused: stillUnused.map(s => s.key) }
+ )
+ }
+ }
+}
+
+module.exports = { resolvePatchedDependencies, matchSelector, parseSelector }
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/place-dep.js b/deps/npm/node_modules/@npmcli/arborist/lib/place-dep.js
index bf21f01464d..34a62144e9b 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/place-dep.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/place-dep.js
@@ -248,6 +248,12 @@ class PlaceDep {
installLinks: this.installLinks,
legacyPeerDeps: this.legacyPeerDeps,
error: this.dep.errors[0],
+ ...(this.dep.packageExtensionsApplied
+ ? { packageExtensionsApplied: this.dep.packageExtensionsApplied }
+ : {}),
+ ...(this.dep.npmExtensionApplied
+ ? { npmExtensionApplied: this.dep.npmExtensionApplied }
+ : {}),
...(this.dep.overrides ? { overrides: this.dep.overrides } : {}),
...(this.dep.isLink ? { target: this.dep.target, realpath: this.dep.realpath } : {}),
})
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/printable.js b/deps/npm/node_modules/@npmcli/arborist/lib/printable.js
index 53c3f7a5756..9ade2c08136 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/printable.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/printable.js
@@ -52,11 +52,6 @@ class ArboristNode {
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)
}
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/script-allowed.js b/deps/npm/node_modules/@npmcli/arborist/lib/script-allowed.js
index 8c9b3fe118a..629625f8e4f 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/script-allowed.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/script-allowed.js
@@ -71,7 +71,7 @@ const isScriptAllowed = (node, policy) => {
const matches = (node, key, failClosed) => {
let parsed
try {
- parsed = npa(key)
+ parsed = npa(key, node?.root?.path)
} catch {
return false
}
@@ -328,8 +328,15 @@ const matchGit = (node, parsed) => {
}
const matchFileOrDir = (node, parsed) => {
+ // consistentResolve stores local sources as `file:` plus npa's absolute,
+ // platform-native fetchSpec.
+ const absoluteFileSpec = parsed.fetchSpec && `file:${parsed.fetchSpec}`
return resolvedSourceSpecs(node)
- .some(resolved => resolved === parsed.saveSpec || resolved === parsed.fetchSpec)
+ .some(resolved =>
+ resolved === parsed.saveSpec ||
+ resolved === parsed.fetchSpec ||
+ resolved === absoluteFileSpec
+ )
}
const matchRemote = (node, parsed) => {
@@ -381,4 +388,5 @@ module.exports.matches = matches
module.exports.isExactVersionDisjunction = isExactVersionDisjunction
module.exports.getTrustedRegistryIdentity = getTrustedRegistryIdentity
module.exports.resolvedSourceSpecs = resolvedSourceSpecs
+module.exports.matchFileOrDir = matchFileOrDir
module.exports.trustedDisplay = trustedDisplay
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/shrinkwrap.js b/deps/npm/node_modules/@npmcli/arborist/lib/shrinkwrap.js
index 03cc86edbd4..19c2c952dc7 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/shrinkwrap.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/shrinkwrap.js
@@ -1,5 +1,4 @@
-// a module that manages a shrinkwrap file (npm-shrinkwrap.json or
-// package-lock.json).
+// a module that manages a lockfile (package-lock.json).
// Increment whenever the lockfile version updates
// v1 - npm <=6
@@ -11,6 +10,12 @@
const localeCompare = require('@isaacs/string-locale-compare')('en')
const defaultLockfileVersion = 3
+// Bumped to 4 only when a node carries a patch record, so older clients abort.
+const patchedLockfileVersion = 4
+// packageExtensions provenance also forces lockfileVersion 4 so older clients abort rather than silently dropping the repaired graph.
+// Both features share version 4: they are root-owned graph repairs an old npm must not drop.
+const packageExtensionsLockfileVersion = 4
+const maxLockfileVersion = 4
// for comparing nodes to yarn.lock entries
const mismatch = (a, b) => a && b && a !== b
@@ -98,7 +103,6 @@ const pkgMetaKeys = [
'libc',
'_integrity',
'license',
- '_hasShrinkwrap',
'hasInstallScript',
'bin',
'deprecated',
@@ -108,8 +112,10 @@ const pkgMetaKeys = [
const nodeMetaKeys = [
'integrity',
'inBundle',
- 'hasShrinkwrap',
'hasInstallScript',
+ 'patched',
+ 'packageExtensionsApplied',
+ 'npmExtensionApplied',
]
const metaFieldFromPkg = (pkg, key) => {
@@ -228,17 +234,14 @@ class Shrinkwrap {
const s = new Shrinkwrap(options)
s.reset()
- const [sw, lock] = await s.resetFiles
+ const [lock] = await s.resetFiles
- // XXX this is duplicated in this.load(), but using loadFiles instead of resetFiles
if (s.hiddenLockfile) {
s.filename = resolve(s.path, 'node_modules/.package-lock.json')
- } else if (s.shrinkwrapOnly || sw) {
- s.filename = resolve(s.path, 'npm-shrinkwrap.json')
} else {
s.filename = resolve(s.path, 'package-lock.json')
}
- s.loadedFromDisk = !!(sw || lock)
+ s.loadedFromDisk = !!lock
// TODO what uses this?
s.type = basename(s.filename)
@@ -315,7 +318,6 @@ class Shrinkwrap {
path,
indent = 2,
newline = '\n',
- shrinkwrapOnly = false,
hiddenLockfile = false,
lockfileVersion,
resolveOptions = {},
@@ -341,8 +343,6 @@ class Shrinkwrap {
this.hiddenLockfile = hiddenLockfile
this.loadingError = null
this.resolveOptions = resolveOptions
- // only load npm-shrinkwrap.json in dep trees, not package-lock
- this.shrinkwrapOnly = shrinkwrapOnly
}
// check to see if a spec is present in the yarn.lock file, and if so,
@@ -385,6 +385,8 @@ class Shrinkwrap {
reset () {
this.tree = null
this.#awaitingUpdate = new Map()
+ this.packageExtensionsHash = null
+ this.npmExtensionHash = null
const lockfileVersion = this.lockfileVersion || defaultLockfileVersion
this.originalLockfileVersion = lockfileVersion
@@ -398,14 +400,10 @@ class Shrinkwrap {
// files to potentially read from and write to, in order of priority
get #filenameSet () {
- if (this.shrinkwrapOnly) {
- return [`${this.path}/npm-shrinkwrap.json`]
- }
if (this.hiddenLockfile) {
return [`${this.path}/node_modules/.package-lock.json`]
}
return [
- `${this.path}/npm-shrinkwrap.json`,
`${this.path}/package-lock.json`,
`${this.path}/yarn.lock`,
]
@@ -425,9 +423,9 @@ class Shrinkwrap {
}
get resetFiles () {
- // slice out yarn, we only care about lock or shrinkwrap when checking
+ // slice out yarn, we only care about the package-lock when checking
// this way, since we're not actually loading the full lock metadata
- return Promise.all(this.#filenameSet.slice(0, 2)
+ return Promise.all(this.#filenameSet.slice(0, 1)
.map(file => file && stat(file).then(st => st.isFile(), er => {
/* istanbul ignore else - can't test without breaking module itself */
if (er.code === 'ENOENT') {
@@ -454,25 +452,18 @@ class Shrinkwrap {
}
async load () {
- // we don't need to load package-lock.json except for top of tree nodes,
- // only npm-shrinkwrap.json.
let data
try {
- const [sw, lock, yarn] = await this.loadFiles
- data = sw || lock || '{}'
+ const [lock, yarn] = await this.loadFiles
+ data = lock || '{}'
- // use shrinkwrap only for deps; otherwise, prefer package-lock
- // and ignore npm-shrinkwrap if both are present.
- // TODO: emit a warning here or something if both are present.
if (this.hiddenLockfile) {
this.filename = resolve(this.path, 'node_modules/.package-lock.json')
- } else if (this.shrinkwrapOnly || sw) {
- this.filename = resolve(this.path, 'npm-shrinkwrap.json')
} else {
this.filename = resolve(this.path, 'package-lock.json')
}
this.type = basename(this.filename)
- this.loadedFromDisk = Boolean(sw || lock)
+ this.loadedFromDisk = Boolean(lock)
if (yarn) {
this.yarnLock = new YarnLock()
@@ -507,6 +498,13 @@ class Shrinkwrap {
this.ancientLockfile = false
data = {}
}
+ // refuse lockfiles newer than we understand so we never drop a patched or repaired graph we cannot read
+ if (data.lockfileVersion > maxLockfileVersion) {
+ throw Object.assign(
+ new Error(`Unsupported lockfileVersion ${data.lockfileVersion}. This npm only supports up to ${maxLockfileVersion}. Please upgrade npm.`),
+ { code: 'ELOCKFILEVERSION' }
+ )
+ }
// auto convert v1 lockfiles to v3
// leave v2 in place unless configured
// v3 by default
@@ -527,6 +525,11 @@ class Shrinkwrap {
this.originalLockfileVersion = data.lockfileVersion
+ // the canonical packageExtensions hash, if the lockfile recorded one on its root entry
+ this.packageExtensionsHash = data.packages?.['']?.packageExtensionsHash || null
+ // the .npm-extension file hash, if the lockfile recorded one on its root entry
+ this.npmExtensionHash = data.packages?.['']?.npmExtensionHash || null
+
// use default if it wasn't explicitly set, and the current file is
// less than our default. otherwise, keep whatever is in the file,
// unless we had an explicit setting already.
@@ -838,7 +841,6 @@ class Shrinkwrap {
const {
resolved,
integrity,
- hasShrinkwrap,
version,
} = this.get(node.path)
@@ -865,17 +867,14 @@ class Shrinkwrap {
if (allOk) {
node.resolved = node.resolved || pathFixed || null
node.integrity = node.integrity || integrity || null
- node.hasShrinkwrap = node.hasShrinkwrap || hasShrinkwrap || false
} else {
// try to read off the package or node itself
const {
resolved,
integrity,
- hasShrinkwrap,
} = Shrinkwrap.metaFromNode(node, this.path, this.resolveOptions)
node.resolved = node.resolved || resolved || null
node.integrity = node.integrity || integrity || null
- node.hasShrinkwrap = node.hasShrinkwrap || hasShrinkwrap || false
}
}
this.#awaitingUpdate.set(loc, node)
@@ -948,6 +947,14 @@ class Shrinkwrap {
this.tree.target,
this.path,
this.resolveOptions)
+ // record the canonical packageExtensions hash on the root entry so npm ci can detect stale extension state
+ if (this.packageExtensionsHash) {
+ root.packageExtensionsHash = this.packageExtensionsHash
+ }
+ // record the .npm-extension file hash on the root entry for the same reason
+ if (this.npmExtensionHash) {
+ root.npmExtensionHash = this.npmExtensionHash
+ }
this.data.packages = {}
if (Object.keys(root).length) {
this.data.packages[''] = root
@@ -993,6 +1000,22 @@ class Shrinkwrap {
if (!this.lockfileVersion) {
this.lockfileVersion = defaultLockfileVersion
}
+ // patched nodes force lockfileVersion 4 so older clients abort the install
+ // the hidden lockfile is an internal cache pinned to version 3, so it never drives this upgrade
+ const hasPatched = !this.hiddenLockfile &&
+ Object.values(this.data.packages).some(p => p.patched)
+ if (hasPatched && this.lockfileVersion < patchedLockfileVersion) {
+ log.warn('shrinkwrap', `patchedDependencies requires lockfileVersion ${patchedLockfileVersion}; upgrading the lockfile from version ${this.lockfileVersion}.`)
+ this.lockfileVersion = patchedLockfileVersion
+ }
+ // packageExtensions and .npm-extension state likewise force lockfileVersion 4 so older clients abort instead of dropping the repaired graph
+ const hasExtensionState = !this.hiddenLockfile &&
+ (this.packageExtensionsHash || this.npmExtensionHash ||
+ Object.values(this.data.packages).some(p => p.packageExtensionsApplied || p.npmExtensionApplied))
+ if (hasExtensionState && this.lockfileVersion < packageExtensionsLockfileVersion) {
+ log.warn('shrinkwrap', `manifest extensions require lockfileVersion ${packageExtensionsLockfileVersion}; upgrading the lockfile from version ${this.lockfileVersion}.`)
+ this.lockfileVersion = packageExtensionsLockfileVersion
+ }
this.data.lockfileVersion = this.lockfileVersion
// hidden lockfiles don't include legacy metadata or a root entry
diff --git a/deps/npm/node_modules/@npmcli/arborist/package.json b/deps/npm/node_modules/@npmcli/arborist/package.json
index 1b71dfa4f12..3a136df4f77 100644
--- a/deps/npm/node_modules/@npmcli/arborist/package.json
+++ b/deps/npm/node_modules/@npmcli/arborist/package.json
@@ -1,50 +1,52 @@
{
"name": "@npmcli/arborist",
- "version": "9.9.1",
+ "version": "10.0.3",
"description": "Manage node_modules trees",
"dependencies": {
"@gar/promise-retry": "^1.0.0",
"@isaacs/string-locale-compare": "^1.1.0",
- "@npmcli/fs": "^5.0.0",
- "@npmcli/installed-package-contents": "^4.0.0",
- "@npmcli/map-workspaces": "^5.0.0",
- "@npmcli/metavuln-calculator": "^9.0.2",
- "@npmcli/name-from-folder": "^4.0.0",
- "@npmcli/node-gyp": "^5.0.0",
- "@npmcli/package-json": "^7.0.0",
+ "@npmcli/fs": "^6.0.0",
+ "@npmcli/installed-package-contents": "^5.0.0",
+ "@npmcli/map-workspaces": "^6.0.0",
+ "@npmcli/metavuln-calculator": "^10.0.0",
+ "@npmcli/name-from-folder": "^5.0.0",
+ "@npmcli/node-gyp": "^6.0.0",
+ "@npmcli/package-json": "^8.0.0",
"@npmcli/query": "^5.0.0",
- "@npmcli/redact": "^4.0.0",
- "@npmcli/run-script": "^10.0.0",
- "bin-links": "^6.0.0",
- "cacache": "^20.0.1",
+ "@npmcli/redact": "^5.0.0",
+ "@npmcli/run-script": "^11.0.0",
+ "bin-links": "^7.0.0",
+ "cacache": "^21.0.1",
"common-ancestor-path": "^2.0.0",
- "hosted-git-info": "^9.0.0",
+ "diff": "^8.0.2",
+ "hosted-git-info": "^10.1.1",
"json-stringify-nice": "^1.1.4",
"lru-cache": "^11.2.1",
"minimatch": "^10.0.3",
- "nopt": "^9.0.0",
- "npm-install-checks": "^8.0.0",
- "npm-package-arg": "^13.0.0",
- "npm-pick-manifest": "^11.0.1",
- "npm-registry-fetch": "^19.0.0",
- "pacote": "^21.0.2",
- "parse-conflict-json": "^5.0.1",
- "proc-log": "^6.0.0",
+ "nopt": "^10.0.1",
+ "npm-install-checks": "^9.0.0",
+ "npm-package-arg": "^14.0.0",
+ "npm-pick-manifest": "^12.0.0",
+ "npm-registry-fetch": "^20.0.1",
+ "pacote": "^22.0.0",
+ "parse-conflict-json": "^6.0.0",
+ "proc-log": "^7.0.0",
"proggy": "^4.0.0",
"promise-all-reject-late": "^1.0.0",
"promise-call-limit": "^3.0.1",
"semver": "^7.3.7",
- "ssri": "^13.0.0",
+ "ssri": "^14.0.0",
"treeverse": "^3.0.0",
+ "validate-npm-package-name": "^8.0.0",
"walk-up-path": "^4.0.0"
},
"devDependencies": {
"@npmcli/eslint-config": "^5.0.1",
"@npmcli/mock-registry": "^1.0.0",
- "@npmcli/template-oss": "4.29.0",
+ "@npmcli/template-oss": "5.1.1",
"benchmark": "^2.1.4",
"minify-registry-metadata": "^4.0.0",
- "nock": "^13.3.3",
+ "nock": "^14.0.0",
"tap": "^16.3.8",
"tar-stream": "^3.0.0",
"tcompare": "^5.0.6"
@@ -82,6 +84,10 @@
"test-env": [
"LC_ALL=sk"
],
+ "node-arg": [
+ "--require",
+ "../../scripts/disable-agent-for-tests.js"
+ ],
"timeout": "720",
"nyc-arg": [
"--exclude",
@@ -89,11 +95,11 @@
]
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.29.0",
+ "version": "5.1.1",
"content": "../../scripts/template-oss/index.js"
}
}
diff --git a/deps/npm/node_modules/@npmcli/config/lib/definitions/definitions.js b/deps/npm/node_modules/@npmcli/config/lib/definitions/definitions.js
index 2bb1713458a..bd5c8236393 100644
--- a/deps/npm/node_modules/@npmcli/config/lib/definitions/definitions.js
+++ b/deps/npm/node_modules/@npmcli/config/lib/definitions/definitions.js
@@ -225,7 +225,7 @@ const definitions = {
flatten,
}),
'allow-git': new Definition('allow-git', {
- default: 'all',
+ default: 'none',
type: ['all', 'none', 'root'],
description: `
Limits the ability for npm to fetch dependencies from git references.
@@ -233,6 +233,11 @@ const definitions = {
Please note that this could leave your tree incomplete and some packages may not function as intended or designed.
Changing this setting will not remove dependencies that are already installed.
+ As of npm 12 the default is \`none\`. Git dependencies run \`git\`
+ against a remote repo and may install configuration the project does
+ not control. Opt in explicitly per project (in \`.npmrc\`) or per
+ command (on the CLI) when you need git deps.
+
\`all\` allows any git dependencies to be fetched and installed.
\`none\` prevents any git dependencies from being fetched and installed.
\`root\` only allows git dependencies defined in your project's package.json to be fetched and installed. Also allows git dependencies to be fetched for other commands like \`npm view\`
@@ -240,7 +245,7 @@ const definitions = {
flatten,
}),
'allow-remote': new Definition('allow-remote', {
- default: 'all',
+ default: 'none',
type: ['all', 'none', 'root'],
description: `
Limits the ability for npm to fetch dependencies from urls.
@@ -248,6 +253,14 @@ const definitions = {
Please note that this could leave your tree incomplete and some packages may not function as intended or designed.
Changing this setting will not remove dependencies that are already installed.
+ As of npm 12 the default is \`none\`. Tarballs that share a hostname
+ with the configured registry (the typical case for the npm registry,
+ GitHub Packages, and most private registries) are still installed
+ normally. If your registry serves tarballs from a different host,
+ set \`replace-registry-host\` or override this setting. Opt in
+ explicitly per project (in \`.npmrc\`) or per command (on the CLI)
+ when you intentionally install from a URL.
+
\`all\` allows any url to be installed.
\`none\` prevents any url from being installed.
\`root\` only allows urls defined in your project's package.json to be installed. Also allows url dependencies to be used for other commands like \`npm view\`
@@ -258,6 +271,7 @@ const definitions = {
default: '',
type: [String, Array],
hint: '<package-list>',
+ envExport: false,
description: `
Comma-separated list of packages whose install-time lifecycle scripts
(\`preinstall\`, \`install\`, \`postinstall\`, and \`prepare\` for
@@ -761,6 +775,18 @@ const definitions = {
`,
flatten,
}),
+ 'extension-file': new Definition('extension-file', {
+ default: null,
+ type: [null, path],
+ description: `
+ Path to a project-local npm extension file to load instead of
+ discovering \`.npm-extension.mjs\` / \`.npm-extension.cjs\` at the
+ project root. Must resolve inside the project root and use a \`.mjs\`
+ or \`.cjs\` extension. Only honored from project config or the command
+ line, never from user, global, or builtin config.
+ `,
+ flatten,
+ }),
'fetch-retries': new Definition('fetch-retries', {
default: 2,
type: Number,
@@ -874,7 +900,7 @@ const definitions = {
default: true,
type: Boolean,
description: `
- Format \`package-lock.json\` or \`npm-shrinkwrap.json\` as a human
+ Format \`package-lock.json\` as a human
readable file.
`,
flatten,
@@ -943,6 +969,29 @@ const definitions = {
`,
flatten,
}),
+ // the global-ignore-file has its default defined outside of this module
+ 'global-ignore-file': new Definition('global-ignore-file', {
+ type: path,
+ default: '',
+ defaultDescription: `
+ The global --prefix setting plus 'etc/npmignore'. For example,
+ '/usr/local/etc/npmignore'
+ `,
+ description: `
+ An additional ignore file applied during \`npm pack\` and \`npm
+ publish\`, owned by the current user rather than the package. Patterns
+ follow the same syntax as a package's local \`.npmignore\` file.
+ Useful for keeping editor metadata (such as \`.idea/\` or \`*.iml\`)
+ and scratch directories out of every package you publish, without
+ adding them to each package's own ignore rules.
+
+ The global rules apply in addition to a package's local \`.npmignore\`.
+ When a package uses a \`files\` field in its \`package.json\`, an entry
+ in \`files\` that contradicts a global rule (i.e., explicitly includes
+ a path the global rule would exclude) still wins.
+ `,
+ flatten,
+ }),
'global-style': new Definition('global-style', {
default: false,
type: Boolean,
@@ -994,6 +1043,17 @@ const definitions = {
`,
flatten,
}),
+ 'ignore-extension': new Definition('ignore-extension', {
+ default: false,
+ type: Boolean,
+ description: `
+ If true, npm does not import or execute a root \`.npm-extension.mjs\` /
+ \`.npm-extension.cjs\` file (or one selected via \`extension-file\`).
+ \`ignore-scripts\` implies \`ignore-extension\`, since both disable
+ root-owned install-time code.
+ `,
+ flatten,
+ }),
'ignore-scripts': new Definition('ignore-scripts', {
default: false,
type: Boolean,
@@ -1004,8 +1064,17 @@ const definitions = {
as \`npm start\`, \`npm stop\`, \`npm restart\`, \`npm test\`, and \`npm
run\` will still run their intended script if \`ignore-scripts\` is
set, but they will *not* run any pre- or post-scripts.
+
+ Setting \`ignore-scripts\` also disables \`.npm-extension\` execution,
+ as if \`ignore-extension\` were set.
`,
- flatten,
+ // ignore-scripts implies ignore-extension: both disable root install-time code
+ flatten (key, obj, flatOptions) {
+ flatOptions.ignoreScripts = obj['ignore-scripts']
+ if (obj['ignore-scripts']) {
+ flatOptions.ignoreExtension = true
+ }
+ },
}),
include: new Definition('include', {
default: [],
@@ -1085,11 +1154,12 @@ const definitions = {
`,
}),
'init-license': new Definition('init-license', {
- default: 'ISC',
+ default: '',
hint: '<license>',
type: String,
description: `
The value \`npm init\` should use by default for the package license.
+ If not set, the license field will be omitted from new packages.
`,
}),
'init-module': new Definition('init-module', {
@@ -1160,7 +1230,7 @@ const definitions = {
`,
}),
'init.license': new Definition('init.license', {
- default: 'ISC',
+ default: '',
type: String,
deprecated: `
Use \`--init-license\` instead.
@@ -1363,8 +1433,8 @@ const definitions = {
Version 3 if no lockfile, auto-converting v1 lockfiles to v3; otherwise,
maintain current lockfile version.`,
description: `
- Set the lockfile format version to be used in package-lock.json and
- npm-shrinkwrap-json files. Possible options are:
+ Set the lockfile format version to be used in package-lock.json files.
+ Possible options are:
1: The lockfile version used by npm versions 5 and 6. Lacks some data that
is used during the install, resulting in slower and possibly less
@@ -1610,7 +1680,7 @@ const definitions = {
Dependency types to omit from the installation tree on disk.
Note that these dependencies _are_ still resolved and added to the
- \`package-lock.json\` or \`npm-shrinkwrap.json\` file. They are just
+ \`package-lock.json\` file. They are just
not physically installed on disk.
If a package type appears in both the \`--include\` and \`--omit\`
@@ -1763,6 +1833,63 @@ const definitions = {
`,
flatten,
}),
+ 'patches-dir': new Definition('patches-dir', {
+ default: 'patches',
+ type: String,
+ description: `
+ The directory, relative to the project root, where \`npm patch commit\`
+ writes patch files for \`patchedDependencies\`.
+ `,
+ flatten,
+ }),
+ // CLI-only: deliberately no flatten, so a value in .npmrc/env never reaches the install pipeline.
+ // npm install reads it from the cli layer only, and npm ci rejects it.
+ 'allow-unused-patches': new Definition('allow-unused-patches', {
+ default: false,
+ type: Boolean,
+ description: `
+ Install even when a registered patch in \`patchedDependencies\` matches no
+ installed package. Does not silence patch apply failures.
+
+ This flag is only honored when passed on the command line; it is ignored
+ in \`.npmrc\` and environment variables, and rejected by \`npm ci\`.
+ `,
+ }),
+ 'ignore-patch-failures': new Definition('ignore-patch-failures', {
+ default: false,
+ type: Boolean,
+ description: `
+ Install even when a registered patch fails to apply, with a warning per
+ failure. Intended for incident response only.
+
+ This flag is only honored when passed on the command line; it is ignored
+ in \`.npmrc\` and environment variables, and rejected by \`npm ci\`.
+ `,
+ }),
+ 'edit-dir': new Definition('edit-dir', {
+ default: null,
+ type: [null, path],
+ description: `
+ Override the temporary directory used by \`npm patch add\` to prepare a
+ package for editing.
+ `,
+ }),
+ 'ignore-existing': new Definition('ignore-existing', {
+ default: false,
+ type: Boolean,
+ description: `
+ With \`npm patch add\`, discard a previous unfinished edit directory and
+ start fresh.
+ `,
+ }),
+ 'keep-edit-dir': new Definition('keep-edit-dir', {
+ default: false,
+ type: Boolean,
+ description: `
+ With \`npm patch commit\`, do not remove the edit directory after
+ committing the patch.
+ `,
+ }),
parseable: new Definition('parseable', {
default: false,
type: Boolean,
@@ -1880,6 +2007,10 @@ const definitions = {
description: `
When publishing from a supported cloud CI/CD system, the package will be
publicly linked to where it was built and published from.
+
+ When the \`provenance-file\` config is set, it takes precedence and
+ automatic provenance generation (including via trusted publishing/OIDC)
+ is skipped.
`,
flatten,
}),
@@ -1890,6 +2021,9 @@ const definitions = {
exclusive: ['provenance'],
description: `
When publishing, the provenance bundle at the given path will be used.
+
+ This takes precedence over automatic provenance generation in trusted
+ publishing flows.
`,
flatten,
}),
@@ -2208,11 +2342,13 @@ const definitions = {
}),
'packages-and-scopes-permission': new Definition('packages-and-scopes-permission', {
default: null,
- type: [null, 'read-only', 'read-write', 'no-access'],
+ type: [null, 'read-only', 'read-write', 'read-write-stage-only', 'no-access'],
description: `
When creating a Granular Access Token with \`npm token create\`,
sets the permission level for packages and scopes. Options are
- "read-only", "read-write", or "no-access".
+ "read-only", "read-write", "read-write-stage-only", or "no-access".
+ "read-write-stage-only" grants publish access that stages releases
+ instead of publishing them directly.
`,
flatten,
}),
@@ -2314,20 +2450,6 @@ const definitions = {
`,
flatten,
}),
- shrinkwrap: new Definition('shrinkwrap', {
- default: true,
- type: Boolean,
- deprecated: `
- Use the --package-lock setting instead.
- `,
- description: `
- Alias for --package-lock
- `,
- flatten (key, obj, flatOptions) {
- obj['package-lock'] = obj.shrinkwrap
- definitions['package-lock'].flatten('package-lock', obj, flatOptions)
- },
- }),
'sign-git-commit': new Definition('sign-git-commit', {
default: false,
type: Boolean,
@@ -2377,12 +2499,13 @@ const definitions = {
type: Boolean,
description: `
If \`true\`, turn the install-script policy from a warning into a hard
- error: any dependency with install scripts not covered by
- \`allowScripts\` will fail the install instead of running with a
- notice.
+ error: any dependency with install scripts that is not covered by
+ \`allowScripts\` will fail the install instead of being blocked with a
+ warning.
Dependencies explicitly denied with \`false\` in \`allowScripts\` are
- always silently skipped; this setting only affects unreviewed entries.
+ always silently skipped; this setting only affects unreviewed entries
+ (packages with install scripts that are neither approved nor denied).
\`--ignore-scripts\` and \`--dangerously-allow-all-scripts\` both
override this setting.
@@ -2392,6 +2515,18 @@ const definitions = {
`,
flatten,
}),
+ 'strict-npmrc': new Definition('strict-npmrc', {
+ default: false,
+ type: Boolean,
+ description: `
+ If set to \`true\`, unknown configuration keys found in \`.npmrc\` files
+ are treated as a hard error instead of a warning.
+
+ Unknown command line flags and abbreviated flags always error regardless
+ of this setting.
+ `,
+ flatten,
+ }),
'strict-ssl': new Definition('strict-ssl', {
default: true,
type: Boolean,
@@ -2453,6 +2588,16 @@ const definitions = {
while still writing the timing file, use \`--silent\`.
`,
}),
+ to: new Definition('to', {
+ default: null,
+ hint: '<version>',
+ type: [null, String],
+ description: `
+ Used by \`npm patch update\` to set the version to rebase a patch onto
+ when it cannot be read from \`package-lock.json\` — for example an
+ exact-version selector, or a version that has not been installed yet.
+ `,
+ }),
umask: new Definition('umask', {
default: 0,
type: Umask,
diff --git a/deps/npm/node_modules/@npmcli/config/lib/index.js b/deps/npm/node_modules/@npmcli/config/lib/index.js
index a1acb7969b2..4121c2a7a38 100644
--- a/deps/npm/node_modules/@npmcli/config/lib/index.js
+++ b/deps/npm/node_modules/@npmcli/config/lib/index.js
@@ -60,6 +60,10 @@ class Config {
// populated the first time we flatten the object
#flatOptions = null
#warnings = []
+ // Unknown configs collected during load(), aggregated and thrown by `BaseCommand.validateCli` once command-specific definitions are known.
+ // Entries: { where, key, baseKey, source }. `baseKey` is non-null only for scoped keys (e.g. `<nerfdart>:foo`) and holds the trailing segment.
+ // `env` and `publishConfig` entries warn instead of error.
+ #unknownConfigs = []
static get typeDefs () {
return typeDefs
@@ -313,6 +317,24 @@ class Config {
configurable: true,
enumerable: true,
})
+
+ // like globalconfig, the global-ignore-file default is computed from
+ // the current prefix. since prefix may be overridden after defaults
+ // load (via cli, env, or userconfig), expose a getter and only freeze
+ // to a value once explicitly set.
+ Object.defineProperty(data, 'global-ignore-file', {
+ get: () => resolve(this.#get('prefix'), 'etc/npmignore'),
+ set (value) {
+ Object.defineProperty(data, 'global-ignore-file', {
+ value,
+ configurable: true,
+ writable: true,
+ enumerable: true,
+ })
+ },
+ configurable: true,
+ enumerable: true,
+ })
}
loadHome () {
@@ -359,7 +381,10 @@ class Config {
loadCLI () {
for (const s of Object.keys(this.shorthands)) {
if (s.length > 1 && this.argv.includes(`-${s}`)) {
- log.warn(`-${s} is not a valid single-hyphen cli flag and will be removed in the future`)
+ throw Object.assign(
+ new Error(`-${s} is not a valid single-hyphen cli flag. Did you mean --${s}?`),
+ { code: 'EUNKNOWNCONFIG' }
+ )
}
}
nopt.invalidHandler = (k, val, type) =>
@@ -431,6 +456,32 @@ class Config {
}
}
}
+
+ // Top-level `email`, `certfile`, and `keyfile` must be in nerfdart form.
+ // certfile/keyfile are an mTLS pair: drop a lone one rather than migrating it.
+ if (this.get('email', entryWhere)) {
+ authProblems.push({
+ action: 'rename',
+ from: 'email',
+ to: `${nerfedReg}:email`,
+ where: entryWhere,
+ })
+ }
+ for (const key of ['certfile', 'keyfile']) {
+ if (this.get(key, entryWhere)) {
+ const pair = key === 'certfile' ? 'keyfile' : 'certfile'
+ if (!this.get(pair, entryWhere)) {
+ authProblems.push({ action: 'delete', key, where: entryWhere })
+ } else {
+ authProblems.push({
+ action: 'rename',
+ from: key,
+ to: `${nerfedReg}:${key}`,
+ where: entryWhere,
+ })
+ }
+ }
+ }
}
}
@@ -481,10 +532,15 @@ class Config {
if (problem.action === 'delete') {
this.delete(problem.key, problem.where)
} else if (problem.action === 'rename') {
- const raw = this.data.get(problem.where).raw?.[problem.from]
- const calculated = this.get(problem.from, problem.where)
- this.set(problem.to, raw || calculated, problem.where)
- this.delete(problem.from, problem.where)
+ // If the destination already exists, drop the source rather than clobber.
+ if (this.find(problem.to) !== null) {
+ this.delete(problem.from, problem.where)
+ } else {
+ const raw = this.data.get(problem.where).raw?.[problem.from]
+ const calculated = this.get(problem.from, problem.where)
+ this.set(problem.to, raw || calculated, problem.where)
+ this.delete(problem.from, problem.where)
+ }
}
}
}
@@ -535,7 +591,10 @@ class Config {
}
abbrevHandler (short, long) {
- log.warn(`Expanding --${short} to --${long}. This will stop working in the next major version of npm.`)
+ throw Object.assign(
+ new Error(`Invalid abbreviated flag "--${short}". Did you mean "--${long}"?`),
+ { code: 'EUNKNOWNCONFIG' }
+ )
}
unknownHandler (key, next) {
@@ -603,30 +662,64 @@ class Config {
}
}
if (where !== 'default' || key === 'npm-version') {
- this.checkUnknown(where, key)
+ this.checkUnknown(where, key, source)
}
conf.data[k] = v
}
}
}
- checkUnknown (where, key) {
- if (!this.definitions[key]) {
- if (internalEnv.includes(key)) {
- return
- }
- const hint = where !== 'cli'
- ? ' See `npm help npmrc` for supported config options.'
- : ''
- if (!key.includes(':')) {
- this.queueWarning(key, `Unknown ${where} config "${where === 'cli' ? '--' : ''}${key}". This will stop working in the next major version of npm.${hint}`)
+ checkUnknown (where, key, source = null) {
+ if (this.definitions[key]) {
+ return
+ }
+ if (internalEnv.includes(key)) {
+ return
+ }
+ const scoped = key.includes(':')
+ let baseKey = null
+ if (scoped) {
+ baseKey = key.split(':').pop()
+ if (this.definitions[baseKey] || this.nerfDarts.includes(baseKey)) {
return
}
- const baseKey = key.split(':').pop()
- if (!this.definitions[baseKey] && !this.nerfDarts.includes(baseKey)) {
- this.queueWarning(baseKey, `Unknown ${where} config "${baseKey}" (${key}). This will stop working in the next major version of npm.${hint}`)
- }
}
+
+ const entry = { where, key, baseKey, source: source ?? this.data.get(where)?.source ?? null }
+ this.#unknownConfigs.push(entry)
+
+ // publishConfig is handled by publish/unpublish/config commands and is out of scope for the npm 12 breaking change (tracked separately).
+ // Keep it as a queued warning so existing behavior is preserved.
+ if (where === 'publishConfig') {
+ const hint = ' See `npm help npmrc` for supported config options.'
+ const msg = scoped
+ ? `Unknown ${where} config "${baseKey}" (${key}). This will stop working in the next major version of npm.${hint}`
+ : `Unknown ${where} config "${key}". This will stop working in the next major version of npm.${hint}`
+ this.queueWarning(scoped ? baseKey : key, msg)
+ return
+ }
+
+ // env unknowns are an explicit carve-out for npm 12.
+ // setEnvs() exports npm_config_* for child processes and loadEnv() re-ingests them; erroring here would break npm-invoked-npm and many CI setups.
+ // Keep as warning. Planned to error in npm 13.
+ if (where === 'env') {
+ const hint = ' See `npm help npmrc` for supported config options.'
+ const msg = scoped
+ ? `Unknown ${where} config "${baseKey}" (${key}). This will error in a future major version of npm.${hint}`
+ : `Unknown ${where} config "${key}". This will error in a future major version of npm.${hint}`
+ this.queueWarning(scoped ? baseKey : key, msg)
+ }
+
+ // cli + file sources (builtin/project/user/global): collected only.
+ // Aggregated and thrown by `BaseCommand.validateCli` after subcommand flag resolution so command-specific flags can be allow-listed first.
+ }
+
+ // Returns unknown-config entries for a given source ('cli', 'builtin', 'project', 'user', 'global') or all entries except `env` and `publishConfig` when omitted.
+ getUnknownConfigs (where) {
+ if (where) {
+ return this.#unknownConfigs.filter(u => u.where === where)
+ }
+ return this.#unknownConfigs.filter(u => u.where !== 'env' && u.where !== 'publishConfig')
}
#checkDeprecated (key) {
@@ -782,13 +875,8 @@ class Config {
conf[_loadError] = null
if (where === 'user') {
- // if email is nerfed, then we want to de-nerf it
- const nerfed = nerfDart(this.get('registry'))
- const email = this.get(`${nerfed}:email`, 'user')
- if (email) {
- this.delete(`${nerfed}:email`, 'user')
- this.set('email', email, 'user')
- }
+ // Historically, save('user') would "de-nerf" email — move a scoped `<nerfdart>:email` into a top-level `email` key — because npm used to warn on nerfed email.
+ // In npm 12 the top-level `email` key is a hard error, so we keep email in its scoped form.
}
// We need the actual raw data before we called parseField so that we are
@@ -816,11 +904,7 @@ class Config {
this.delete(`_auth`, level)
this.delete(`_password`, level)
this.delete(`username`, level)
- // de-nerf email if it's nerfed to the default registry
- const email = this.get(`${nerfed}:email`, level)
- if (email) {
- this.set('email', email, level)
- }
+ // In npm 12, top-level `email` is a hard error — don't de-nerf it here either.
}
this.delete(`${nerfed}:_authToken`, level)
this.delete(`${nerfed}:_auth`, level)
@@ -839,7 +923,9 @@ class Config {
// send auth if we have it, only to the URIs under the nerf dart.
this.delete(`${nerfed}:always-auth`, 'user')
- this.delete(`${nerfed}:email`, 'user')
+ // NOTE: we intentionally do NOT delete `${nerfed}:email` here anymore.
+ // In npm 11 and earlier, top-level `email` was the canonical form (with getCredentialsByURI copying scoped email up to top-level on read), and setCredentialsByURI cleared the scoped copy to enforce that invariant.
+ // In npm 12 top-level `email` is a hard error and the scoped nerfdart form is canonical, so preserve any existing scoped email across login.
if (certfile && keyfile) {
this.set(`${nerfed}:certfile`, certfile, 'user')
this.set(`${nerfed}:keyfile`, keyfile, 'user')
@@ -870,17 +956,13 @@ class Config {
// this has to be a bit more complicated to support legacy data of all forms
getCredentialsByURI (uri) {
const nerfed = nerfDart(uri)
- const def = nerfDart(this.get('registry'))
const creds = {}
- // email is handled differently, it used to always be nerfed and now it never should be
- // if it's set nerfed to the default registry, then we copy it to the unnerfed key
+ // email is handled differently, it used to always be nerfed and now it never should be.
+ // In npm 12 the top-level `email` key is a hard error, so we stop copying scoped email back to the top-level here.
// TODO: evaluate removing 'email' from the credentials object returned here
const email = this.get(`${nerfed}:email`) || this.get('email')
if (email) {
- if (nerfed === def) {
- this.set('email', email, 'user')
- }
creds.email = email
}
diff --git a/deps/npm/node_modules/@npmcli/config/package.json b/deps/npm/node_modules/@npmcli/config/package.json
index 360b0ab128a..0380bd34800 100644
--- a/deps/npm/node_modules/@npmcli/config/package.json
+++ b/deps/npm/node_modules/@npmcli/config/package.json
@@ -1,6 +1,6 @@
{
"name": "@npmcli/config",
- "version": "10.12.0",
+ "version": "11.1.0",
"files": [
"bin/",
"lib/"
@@ -33,25 +33,25 @@
"devDependencies": {
"@npmcli/eslint-config": "^5.0.1",
"@npmcli/mock-globals": "^1.0.0",
- "@npmcli/template-oss": "4.29.0",
+ "@npmcli/template-oss": "5.1.1",
"tap": "^16.3.8"
},
"dependencies": {
- "@npmcli/map-workspaces": "^5.0.0",
- "@npmcli/package-json": "^7.0.0",
+ "@npmcli/map-workspaces": "^6.0.0",
+ "@npmcli/package-json": "^8.0.0",
"ci-info": "^4.0.0",
- "ini": "^6.0.0",
- "nopt": "^9.0.0",
- "proc-log": "^6.0.0",
+ "ini": "^7.0.0",
+ "nopt": "^10.0.1",
+ "proc-log": "^7.0.0",
"semver": "^7.3.5",
"walk-up-path": "^4.0.0"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.29.0",
+ "version": "5.1.1",
"content": "../../scripts/template-oss/index.js"
}
}
diff --git a/deps/npm/node_modules/@npmcli/fs/lib/move-file.js b/deps/npm/node_modules/@npmcli/fs/lib/move-file.js
index d56e06d3846..d7022eee4ab 100644
--- a/deps/npm/node_modules/@npmcli/fs/lib/move-file.js
+++ b/deps/npm/node_modules/@npmcli/fs/lib/move-file.js
@@ -56,19 +56,19 @@ const moveFile = async (source, destination, options = {}, root = true, symlinks
}
// try to determine what the actual file is so we can create the correct
// type of symlink in windows
- let targetStat = 'file'
+ let targetType = 'file'
try {
- targetStat = await fs.stat(resolve(dirname(symSource), target))
+ const targetStat = await fs.stat(resolve(dirname(symSource), target))
if (targetStat.isDirectory()) {
- targetStat = 'junction'
+ targetType = 'junction'
}
} catch {
- // targetStat remains 'file'
+ // targetType remains 'file'
}
await fs.symlink(
target,
symDestination,
- targetStat
+ targetType
)
}))
await fs.rm(source, { recursive: true, force: true })
diff --git a/deps/npm/node_modules/@npmcli/fs/package.json b/deps/npm/node_modules/@npmcli/fs/package.json
index 0b64301d657..4740d1144fb 100644
--- a/deps/npm/node_modules/@npmcli/fs/package.json
+++ b/deps/npm/node_modules/@npmcli/fs/package.json
@@ -1,6 +1,6 @@
{
"name": "@npmcli/fs",
- "version": "5.0.0",
+ "version": "6.0.0",
"description": "filesystem utilities for the npm cli",
"main": "lib/index.js",
"files": [
@@ -30,19 +30,19 @@
"author": "GitHub Inc.",
"license": "ISC",
"devDependencies": {
- "@npmcli/eslint-config": "^5.0.0",
- "@npmcli/template-oss": "4.27.1",
+ "@npmcli/eslint-config": "^6.0.0",
+ "@npmcli/template-oss": "5.1.0",
"tap": "^16.0.1"
},
"dependencies": {
"semver": "^7.3.5"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.27.1",
+ "version": "5.1.0",
"publish": true
},
"tap": {
diff --git a/deps/npm/node_modules/@npmcli/git/package.json b/deps/npm/node_modules/@npmcli/git/package.json
index 6a8083ba80d..a595184d915 100644
--- a/deps/npm/node_modules/@npmcli/git/package.json
+++ b/deps/npm/node_modules/@npmcli/git/package.json
@@ -1,6 +1,6 @@
{
"name": "@npmcli/git",
- "version": "7.0.2",
+ "version": "8.0.0",
"main": "lib/index.js",
"files": [
"bin/",
@@ -31,28 +31,29 @@
]
},
"devDependencies": {
- "@npmcli/eslint-config": "^5.0.0",
- "@npmcli/template-oss": "4.24.1",
- "npm-package-arg": "^13.0.0",
+ "@npmcli/eslint-config": "^7.0.0",
+ "@npmcli/template-oss": "5.1.0",
+ "npm-package-arg": "^14.0.0",
"slash": "^3.0.0",
"tap": "^16.0.1"
},
"dependencies": {
"@gar/promise-retry": "^1.0.0",
- "@npmcli/promise-spawn": "^9.0.0",
- "ini": "^6.0.0",
+ "@npmcli/promise-spawn": "^10.0.0",
+ "ini": "^7.0.0",
"lru-cache": "^11.2.1",
- "npm-pick-manifest": "^11.0.1",
- "proc-log": "^6.0.0",
+ "npm-pick-manifest": "^12.0.0",
+ "proc-log": "^7.0.0",
"semver": "^7.3.5",
- "which": "^6.0.0"
+ "which": "^7.0.0"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.24.1",
- "publish": true
+ "version": "5.1.0",
+ "publish": true,
+ "updateNpm": false
}
}
diff --git a/deps/npm/node_modules/cmd-shim/LICENSE b/deps/npm/node_modules/@npmcli/installed-package-contents/node_modules/npm-bundled/LICENSE
similarity index 100%
rename from deps/npm/node_modules/cmd-shim/LICENSE
rename to deps/npm/node_modules/@npmcli/installed-package-contents/node_modules/npm-bundled/LICENSE
diff --git a/deps/npm/node_modules/npm-bundled/lib/index.js b/deps/npm/node_modules/@npmcli/installed-package-contents/node_modules/npm-bundled/lib/index.js
similarity index 100%
rename from deps/npm/node_modules/npm-bundled/lib/index.js
rename to deps/npm/node_modules/@npmcli/installed-package-contents/node_modules/npm-bundled/lib/index.js
diff --git a/deps/npm/node_modules/npm-bundled/package.json b/deps/npm/node_modules/@npmcli/installed-package-contents/node_modules/npm-bundled/package.json
similarity index 82%
rename from deps/npm/node_modules/npm-bundled/package.json
rename to deps/npm/node_modules/@npmcli/installed-package-contents/node_modules/npm-bundled/package.json
index 1fa4bdc72c5..559c997a643 100644
--- a/deps/npm/node_modules/npm-bundled/package.json
+++ b/deps/npm/node_modules/@npmcli/installed-package-contents/node_modules/npm-bundled/package.json
@@ -1,6 +1,6 @@
{
"name": "npm-bundled",
- "version": "5.0.0",
+ "version": "6.0.0",
"description": "list things in node_modules that are bundledDependencies, or transitive dependencies thereof",
"main": "lib/index.js",
"repository": {
@@ -10,8 +10,8 @@
"author": "GitHub Inc.",
"license": "ISC",
"devDependencies": {
- "@npmcli/eslint-config": "^5.0.0",
- "@npmcli/template-oss": "4.27.1",
+ "@npmcli/eslint-config": "^6.0.0",
+ "@npmcli/template-oss": "5.1.0",
"mutate-fs": "^2.1.1",
"tap": "^16.3.0"
},
@@ -30,14 +30,14 @@
"lib/"
],
"dependencies": {
- "npm-normalize-package-bin": "^5.0.0"
+ "npm-normalize-package-bin": "^6.0.0"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.27.1",
+ "version": "5.1.0",
"publish": true
},
"tap": {
diff --git a/deps/npm/node_modules/npm-normalize-package-bin/LICENSE b/deps/npm/node_modules/@npmcli/installed-package-contents/node_modules/npm-normalize-package-bin/LICENSE
similarity index 100%
rename from deps/npm/node_modules/npm-normalize-package-bin/LICENSE
rename to deps/npm/node_modules/@npmcli/installed-package-contents/node_modules/npm-normalize-package-bin/LICENSE
diff --git a/deps/npm/node_modules/npm-normalize-package-bin/lib/index.js b/deps/npm/node_modules/@npmcli/installed-package-contents/node_modules/npm-normalize-package-bin/lib/index.js
similarity index 100%
rename from deps/npm/node_modules/npm-normalize-package-bin/lib/index.js
rename to deps/npm/node_modules/@npmcli/installed-package-contents/node_modules/npm-normalize-package-bin/lib/index.js
diff --git a/deps/npm/node_modules/npm-normalize-package-bin/package.json b/deps/npm/node_modules/@npmcli/installed-package-contents/node_modules/npm-normalize-package-bin/package.json
similarity index 54%
rename from deps/npm/node_modules/npm-normalize-package-bin/package.json
rename to deps/npm/node_modules/@npmcli/installed-package-contents/node_modules/npm-normalize-package-bin/package.json
index 55dc65ad5ee..1d0d821b7a2 100644
--- a/deps/npm/node_modules/npm-normalize-package-bin/package.json
+++ b/deps/npm/node_modules/@npmcli/installed-package-contents/node_modules/npm-normalize-package-bin/package.json
@@ -1,6 +1,6 @@
{
"name": "npm-normalize-package-bin",
- "version": "5.0.0",
+ "version": "6.0.0",
"description": "Turn any flavor of allowable package.json bin into a normalized object",
"main": "lib/index.js",
"repository": {
@@ -10,36 +10,33 @@
"author": "GitHub Inc.",
"license": "ISC",
"scripts": {
- "test": "tap",
- "snap": "tap",
+ "test": "node --test './test/**/*.js'",
+ "snap": "node --test --test-update-snapshots './test/**/*.js'",
"lint": "npm run eslint",
"postlint": "template-oss-check",
"template-oss-apply": "template-oss-apply --force",
"lintfix": "npm run eslint -- --fix",
"posttest": "npm run lint",
- "eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\""
+ "eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"",
+ "test:node20": "node --test test",
+ "test:cover": "node --test --experimental-test-coverage --test-timeout=3000 --test-coverage-lines=100 --test-coverage-functions=100 --test-coverage-branches=100 './test/**/*.js'"
},
"devDependencies": {
- "@npmcli/eslint-config": "^5.0.0",
- "@npmcli/template-oss": "4.27.1",
- "tap": "^16.3.0"
+ "@npmcli/eslint-config": "^6.0.0",
+ "@npmcli/template-oss": "5.0.0"
},
"files": [
"bin/",
"lib/"
],
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.27.1",
- "publish": "true"
- },
- "tap": {
- "nyc-arg": [
- "--exclude",
- "tap-snapshots/**"
- ]
+ "version": "5.0.0",
+ "publish": "true",
+ "testRunner": "node:test",
+ "latestCiVersion": 24
}
}
diff --git a/deps/npm/node_modules/@npmcli/installed-package-contents/package.json b/deps/npm/node_modules/@npmcli/installed-package-contents/package.json
index 599b285fb46..4111600f4cd 100644
--- a/deps/npm/node_modules/@npmcli/installed-package-contents/package.json
+++ b/deps/npm/node_modules/@npmcli/installed-package-contents/package.json
@@ -1,6 +1,6 @@
{
"name": "@npmcli/installed-package-contents",
- "version": "4.0.0",
+ "version": "5.0.0",
"description": "Get the list of files installed in a package in node_modules, including bundled dependencies",
"author": "GitHub Inc.",
"main": "lib/index.js",
@@ -19,13 +19,13 @@
"eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\""
},
"devDependencies": {
- "@npmcli/eslint-config": "^5.0.0",
- "@npmcli/template-oss": "4.27.1",
+ "@npmcli/eslint-config": "^6.0.0",
+ "@npmcli/template-oss": "5.1.0",
"tap": "^16.3.0"
},
"dependencies": {
- "npm-bundled": "^5.0.0",
- "npm-normalize-package-bin": "^5.0.0"
+ "npm-bundled": "^6.0.0",
+ "npm-normalize-package-bin": "^6.0.0"
},
"repository": {
"type": "git",
@@ -36,11 +36,11 @@
"lib/"
],
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.27.1",
+ "version": "5.1.0",
"publish": true
},
"tap": {
diff --git a/deps/npm/node_modules/@npmcli/map-workspaces/package.json b/deps/npm/node_modules/@npmcli/map-workspaces/package.json
index 84de7b989b4..f16e7f91722 100644
--- a/deps/npm/node_modules/@npmcli/map-workspaces/package.json
+++ b/deps/npm/node_modules/@npmcli/map-workspaces/package.json
@@ -1,13 +1,13 @@
{
"name": "@npmcli/map-workspaces",
- "version": "5.0.3",
+ "version": "6.0.0",
"main": "lib/index.js",
"files": [
"bin/",
"lib/"
],
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"description": "Retrieves a name:pathname Map for a given workspaces config",
"repository": {
@@ -43,19 +43,19 @@
]
},
"devDependencies": {
- "@npmcli/eslint-config": "^6.0.0",
- "@npmcli/template-oss": "4.28.0",
+ "@npmcli/eslint-config": "^7.0.0",
+ "@npmcli/template-oss": "5.1.0",
"tap": "^16.0.1"
},
"dependencies": {
- "@npmcli/name-from-folder": "^4.0.0",
- "@npmcli/package-json": "^7.0.0",
+ "@npmcli/name-from-folder": "^5.0.0",
+ "@npmcli/package-json": "^8.0.0",
"glob": "^13.0.0",
"minimatch": "^10.0.3"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.28.0",
+ "version": "5.1.0",
"publish": "true"
}
}
diff --git a/deps/npm/node_modules/@npmcli/metavuln-calculator/package.json b/deps/npm/node_modules/@npmcli/metavuln-calculator/package.json
index 02b13bc8e82..23f539fa95f 100644
--- a/deps/npm/node_modules/@npmcli/metavuln-calculator/package.json
+++ b/deps/npm/node_modules/@npmcli/metavuln-calculator/package.json
@@ -1,6 +1,6 @@
{
"name": "@npmcli/metavuln-calculator",
- "version": "9.0.3",
+ "version": "10.0.0",
"main": "lib/index.js",
"files": [
"bin/",
@@ -33,30 +33,24 @@
]
},
"devDependencies": {
- "@npmcli/eslint-config": "^5.0.0",
- "@npmcli/template-oss": "4.27.1",
+ "@npmcli/eslint-config": "^7.0.0",
+ "@npmcli/template-oss": "5.1.0",
"require-inject": "^1.4.4",
"tap": "^16.0.1"
},
"dependencies": {
- "cacache": "^20.0.0",
- "json-parse-even-better-errors": "^5.0.0",
- "pacote": "^21.0.0",
- "proc-log": "^6.0.0",
+ "cacache": "^21.0.1",
+ "json-parse-even-better-errors": "^6.0.0",
+ "pacote": "^22.0.0",
+ "proc-log": "^7.0.0",
"semver": "^7.3.5"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.27.1",
- "publish": "true",
- "ciVersions": [
- "16.14.0",
- "16.x",
- "18.0.0",
- "18.x"
- ]
+ "version": "5.1.0",
+ "publish": "true"
}
}
diff --git a/deps/npm/node_modules/@npmcli/name-from-folder/package.json b/deps/npm/node_modules/@npmcli/name-from-folder/package.json
index 50366752156..60fbc9949d1 100644
--- a/deps/npm/node_modules/@npmcli/name-from-folder/package.json
+++ b/deps/npm/node_modules/@npmcli/name-from-folder/package.json
@@ -1,6 +1,6 @@
{
"name": "@npmcli/name-from-folder",
- "version": "4.0.0",
+ "version": "5.0.0",
"files": [
"bin/",
"lib/"
@@ -14,32 +14,29 @@
"author": "GitHub Inc.",
"license": "ISC",
"scripts": {
- "test": "tap",
- "snap": "tap",
+ "test": "node --test './test/**/*.js'",
+ "snap": "node --test --test-update-snapshots './test/**/*.js'",
"lint": "npm run eslint",
"postlint": "template-oss-check",
"template-oss-apply": "template-oss-apply --force",
"lintfix": "npm run eslint -- --fix",
"posttest": "npm run lint",
- "eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\""
+ "eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"",
+ "test:node20": "node --test test",
+ "test:cover": "node --test --experimental-test-coverage --test-timeout=3000 --test-coverage-lines=100 --test-coverage-functions=100 --test-coverage-branches=100 './test/**/*.js'"
},
"devDependencies": {
- "@npmcli/eslint-config": "^5.0.0",
- "@npmcli/template-oss": "4.27.1",
- "tap": "^16.3.2"
+ "@npmcli/eslint-config": "^6.0.0",
+ "@npmcli/template-oss": "5.0.0"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.27.1",
- "publish": true
- },
- "tap": {
- "nyc-arg": [
- "--exclude",
- "tap-snapshots/**"
- ]
+ "version": "5.0.0",
+ "publish": true,
+ "testRunner": "node:test",
+ "latestCiVersion": 24
}
}
diff --git a/deps/npm/node_modules/@npmcli/node-gyp/package.json b/deps/npm/node_modules/@npmcli/node-gyp/package.json
index a34dc6be617..324024de266 100644
--- a/deps/npm/node_modules/@npmcli/node-gyp/package.json
+++ b/deps/npm/node_modules/@npmcli/node-gyp/package.json
@@ -1,6 +1,6 @@
{
"name": "@npmcli/node-gyp",
- "version": "5.0.0",
+ "version": "6.0.0",
"description": "Tools for dealing with node-gyp packages",
"scripts": {
"test": "tap",
@@ -29,16 +29,16 @@
"author": "GitHub Inc.",
"license": "ISC",
"devDependencies": {
- "@npmcli/eslint-config": "^5.0.0",
- "@npmcli/template-oss": "4.27.1",
+ "@npmcli/eslint-config": "^6.0.0",
+ "@npmcli/template-oss": "5.0.0",
"tap": "^16.0.1"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.27.1",
+ "version": "5.0.0",
"publish": true
},
"tap": {
diff --git a/deps/npm/node_modules/@npmcli/package-json/lib/index.js b/deps/npm/node_modules/@npmcli/package-json/lib/index.js
index adcbac67eab..39cc0980e46 100644
--- a/deps/npm/node_modules/@npmcli/package-json/lib/index.js
+++ b/deps/npm/node_modules/@npmcli/package-json/lib/index.js
@@ -42,6 +42,7 @@ class PackageJson {
'_attributes',
'bundledDependencies',
'bundleDependencies',
+ 'overrides',
'optionalDedupe',
'scripts',
'funding',
@@ -55,8 +56,8 @@ class PackageJson {
'bundledDependencies',
'bundleDependencies',
'bundleDependenciesDeleteFalse',
+ 'overrides',
'gypfile',
- 'serverjs',
'scriptpath',
'authors',
'readme',
diff --git a/deps/npm/node_modules/@npmcli/package-json/lib/normalize.js b/deps/npm/node_modules/@npmcli/package-json/lib/normalize.js
index 0388220ccef..2173b321e25 100644
--- a/deps/npm/node_modules/@npmcli/package-json/lib/normalize.js
+++ b/deps/npm/node_modules/@npmcli/package-json/lib/normalize.js
@@ -133,7 +133,7 @@ function secureAndUnixifyPath (ref) {
return secured.startsWith('./') ? '' : secured
}
-// Only steps that can be ran synchronously. There are some object constructors (i.e. Aborist Node) that need synchronous normalization so here we are.
+// Only steps that can be ran synchronously. There are some object constructors (i.e. Aborist Node) that need synchronous normalization so here we are.
function syncSteps (pkg, { strict, steps, changes, allowLegacyCase }) {
const data = pkg.content
const pkgId = `${data.name ?? ''}@${data.version ?? ''}`
@@ -237,10 +237,23 @@ function syncSteps (pkg, { strict, steps, changes, allowLegacyCase }) {
}
}
- // it was once common practice to list deps both in optionalDependencies and
- // in dependencies, to support npm versions that did not know about
- // optionalDependencies. This is no longer a relevant need, so duplicating
- // the deps in two places is unnecessary and excessive.
+ // normalize the shape of the top-level "overrides" field after this step it is either absent or a non-empty object, so consumers do not need to defensively check the type/size
+ if (steps.includes('overrides')) {
+ const ov = data.overrides
+ if (ov !== undefined) {
+ const isObject = ov && typeof ov === 'object' && !Array.isArray(ov)
+ if (!isObject) {
+ changes?.push(`"overrides" was removed (must be an object)`)
+ delete data.overrides
+ } else if (Object.keys(ov).length === 0) {
+ changes?.push(`Empty "overrides" was removed`)
+ delete data.overrides
+ }
+ }
+ }
+
+ // It was once common practice to list deps both in optionalDependencies and in dependencies, to support npm versions that did not know about optionalDependencies.
+ // This is no longer a relevant need, so duplicating the deps in two places is unnecessary and excessive.
if (steps.includes('optionalDedupe')) {
if (data.dependencies &&
data.optionalDependencies && typeof data.optionalDependencies === 'object') {
@@ -348,8 +361,7 @@ function syncSteps (pkg, { strict, steps, changes, allowLegacyCase }) {
}
}
}
- // normalize-package-data used to put optional dependencies BACK into
- // dependencies here, we no longer do this
+ // normalize-package-data used to put optional dependencies BACK into dependencies here, we no longer do this
for (const deps of ['dependencies', 'devDependencies']) {
if (deps in data) {
@@ -401,18 +413,6 @@ async function asyncSteps (pkg, { steps, root, changes }) {
}
}
- // add "start" attribute if "server.js" exists
- if (steps.includes('serverjs') && !scripts.start) {
- try {
- await fs.access(path.join(pkg.path, 'server.js'))
- scripts.start = 'node server.js'
- data.scripts = scripts
- changes?.push('"scripts.start" was set to "node server.js"')
- } catch {
- // do nothing
- }
- }
-
// populate "authors" attribute
if (steps.includes('authors') && !data.contributors) {
try {
@@ -583,8 +583,8 @@ async function asyncSteps (pkg, { steps, root, changes }) {
}
}
- // Warn if the bin references don't point to anything. This might be better
- // in normalize-package-data if it had access to the file path.
+ // Warn if the bin references don't point to anything.
+ // This might be better in normalize-package-data if it had access to the file path.
if (steps.includes('binRefs') && data.bin instanceof Object) {
for (const key in data.bin) {
try {
@@ -597,7 +597,8 @@ async function asyncSteps (pkg, { steps, root, changes }) {
}
}
-// We don't want the `changes` array in here by default because this is a hot path for parsing packuments during install. The calling method passes it in if it wants to track changes.
+// We don't want the `changes` array in here by default because this is a hot path for parsing packuments during install.
+// The calling method passes it in if it wants to track changes.
async function normalize (pkg, opts) {
if (!pkg.content) {
throw new Error('Can not normalize without content')
diff --git a/deps/npm/node_modules/@npmcli/package-json/package.json b/deps/npm/node_modules/@npmcli/package-json/package.json
index fe46d77edcb..2dd41a3a75a 100644
--- a/deps/npm/node_modules/@npmcli/package-json/package.json
+++ b/deps/npm/node_modules/@npmcli/package-json/package.json
@@ -1,6 +1,6 @@
{
"name": "@npmcli/package-json",
- "version": "7.0.5",
+ "version": "8.0.0",
"description": "Programmatic API to update package.json",
"keywords": [
"npm",
@@ -29,26 +29,27 @@
"eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\""
},
"dependencies": {
- "@npmcli/git": "^7.0.0",
+ "@npmcli/git": "^8.0.0",
"glob": "^13.0.0",
- "hosted-git-info": "^9.0.0",
- "json-parse-even-better-errors": "^5.0.0",
- "proc-log": "^6.0.0",
+ "hosted-git-info": "^10.1.1",
+ "json-parse-even-better-errors": "^6.0.0",
+ "proc-log": "^7.0.0",
"semver": "^7.5.3",
"spdx-expression-parse": "^4.0.0"
},
"devDependencies": {
- "@npmcli/eslint-config": "^6.0.0",
- "@npmcli/template-oss": "4.28.1",
+ "@npmcli/eslint-config": "^7.0.0",
+ "@npmcli/template-oss": "5.1.0",
"tap": "^16.0.1"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.28.1",
- "publish": "true"
+ "version": "5.1.0",
+ "publish": "true",
+ "updateNpm": false
},
"tap": {
"nyc-arg": [
diff --git a/deps/npm/node_modules/@npmcli/promise-spawn/package.json b/deps/npm/node_modules/@npmcli/promise-spawn/package.json
index f00ee324355..b227171eebd 100644
--- a/deps/npm/node_modules/@npmcli/promise-spawn/package.json
+++ b/deps/npm/node_modules/@npmcli/promise-spawn/package.json
@@ -1,6 +1,6 @@
{
"name": "@npmcli/promise-spawn",
- "version": "9.0.1",
+ "version": "10.0.0",
"files": [
"bin/",
"lib/"
@@ -33,19 +33,19 @@
},
"devDependencies": {
"@npmcli/eslint-config": "^6.0.0",
- "@npmcli/template-oss": "4.28.0",
+ "@npmcli/template-oss": "5.1.0",
"spawk": "^1.7.1",
"tap": "^16.0.1"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.28.0",
+ "version": "5.1.0",
"publish": true
},
"dependencies": {
- "which": "^6.0.0"
+ "which": "^7.0.0"
}
}
diff --git a/deps/npm/node_modules/@npmcli/redact/package.json b/deps/npm/node_modules/@npmcli/redact/package.json
index 53d0edf50b7..e781e09b167 100644
--- a/deps/npm/node_modules/@npmcli/redact/package.json
+++ b/deps/npm/node_modules/@npmcli/redact/package.json
@@ -1,6 +1,6 @@
{
"name": "@npmcli/redact",
- "version": "4.0.0",
+ "version": "5.0.0",
"description": "Redact sensitive npm information from output",
"main": "lib/index.js",
"exports": {
@@ -31,7 +31,7 @@
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.27.1",
+ "version": "5.0.0",
"publish": true
},
"tap": {
@@ -43,10 +43,10 @@
},
"devDependencies": {
"@npmcli/eslint-config": "^5.0.0",
- "@npmcli/template-oss": "4.27.1",
+ "@npmcli/template-oss": "5.0.0",
"tap": "^16.3.10"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
}
}
diff --git a/deps/npm/node_modules/@npmcli/run-script/lib/is-server-package.js b/deps/npm/node_modules/@npmcli/run-script/lib/is-server-package.js
deleted file mode 100644
index c36c40d4898..00000000000
--- a/deps/npm/node_modules/@npmcli/run-script/lib/is-server-package.js
+++ /dev/null
@@ -1,11 +0,0 @@
-const { stat } = require('node:fs/promises')
-const { resolve } = require('node:path')
-
-module.exports = async path => {
- try {
- const st = await stat(resolve(path, 'server.js'))
- return st.isFile()
- } catch (er) {
- return false
- }
-}
diff --git a/deps/npm/node_modules/@npmcli/run-script/lib/make-spawn-args.js b/deps/npm/node_modules/@npmcli/run-script/lib/make-spawn-args.js
index 1c9f02c062f..e9bc2f08937 100644
--- a/deps/npm/node_modules/@npmcli/run-script/lib/make-spawn-args.js
+++ b/deps/npm/node_modules/@npmcli/run-script/lib/make-spawn-args.js
@@ -1,8 +1,7 @@
-/* eslint camelcase: "off" */
const setPATH = require('./set-path.js')
const { resolve } = require('path')
-let npm_config_node_gyp
+let npmConfigNodeGyp
const makeSpawnArgs = options => {
const {
@@ -20,13 +19,13 @@ const makeSpawnArgs = options => {
if (nodeGyp) {
// npm already pulled this from env and passes it in to options
- npm_config_node_gyp = nodeGyp
+ npmConfigNodeGyp = nodeGyp
} else if (env.npm_config_node_gyp) {
// legacy mode for standalone user
- npm_config_node_gyp = env.npm_config_node_gyp
+ npmConfigNodeGyp = env.npm_config_node_gyp
} else {
// default
- npm_config_node_gyp = require.resolve('node-gyp/bin/node-gyp.js')
+ npmConfigNodeGyp = require.resolve('node-gyp/bin/node-gyp.js')
}
const spawnEnv = setPATH(path, binPaths, {
@@ -36,7 +35,7 @@ const makeSpawnArgs = options => {
npm_package_json: resolve(path, 'package.json'),
npm_lifecycle_event: event,
npm_lifecycle_script: cmd,
- npm_config_node_gyp,
+ npm_config_node_gyp: npmConfigNodeGyp,
})
const spawnOpts = {
diff --git a/deps/npm/node_modules/@npmcli/run-script/lib/run-script-pkg.js b/deps/npm/node_modules/@npmcli/run-script/lib/run-script-pkg.js
index 161caebb98d..e81396cdd28 100644
--- a/deps/npm/node_modules/@npmcli/run-script/lib/run-script-pkg.js
+++ b/deps/npm/node_modules/@npmcli/run-script/lib/run-script-pkg.js
@@ -3,7 +3,6 @@ const promiseSpawn = require('@npmcli/promise-spawn')
const packageEnvs = require('./package-envs.js')
const { isNodeGypPackage, defaultGypInstallScript } = require('@npmcli/node-gyp')
const signalManager = require('./signal-manager.js')
-const isServerPackage = require('./is-server-package.js')
const runScriptPkg = async options => {
const {
@@ -37,8 +36,6 @@ const runScriptPkg = async options => {
await isNodeGypPackage(path)
) {
cmd = defaultGypInstallScript
- } else if (event === 'start' && await isServerPackage(path)) {
- cmd = 'node server.js'
}
if (!cmd) {
@@ -47,19 +44,13 @@ const runScriptPkg = async options => {
let inputEnd = () => {}
if (stdio === 'inherit') {
- let banner
+ const { log, input } = require('proc-log')
if (pkg._id) {
- banner = `\n> ${pkg._id} ${event}\n`
+ log.notice('run', `${pkg._id} ${event}`)
} else {
- banner = `\n> ${event}\n`
+ log.notice('run', event)
}
- banner += `> ${cmd.trim().replace(/\n/g, '\n> ')}`
- if (args.length) {
- banner += ` ${args.join(' ')}`
- }
- banner += '\n'
- const { output, input } = require('proc-log')
- output.standard(banner)
+ log.notice('run', `${cmd.trim()} ${args?.join(' ')}`.trim())
inputEnd = input.start()
}
diff --git a/deps/npm/node_modules/@npmcli/run-script/lib/run-script.js b/deps/npm/node_modules/@npmcli/run-script/lib/run-script.js
index b00304c8d6e..625f2e452ed 100644
--- a/deps/npm/node_modules/@npmcli/run-script/lib/run-script.js
+++ b/deps/npm/node_modules/@npmcli/run-script/lib/run-script.js
@@ -1,7 +1,6 @@
const PackageJson = require('@npmcli/package-json')
const runScriptPkg = require('./run-script-pkg.js')
const validateOptions = require('./validate-options.js')
-const isServerPackage = require('./is-server-package.js')
const runScript = async options => {
validateOptions(options)
@@ -12,4 +11,4 @@ const runScript = async options => {
return runScriptPkg({ ...options, pkg })
}
-module.exports = Object.assign(runScript, { isServerPackage })
+module.exports = runScript
diff --git a/deps/npm/node_modules/@npmcli/run-script/package.json b/deps/npm/node_modules/@npmcli/run-script/package.json
index 6f782661de3..6dd815a8046 100644
--- a/deps/npm/node_modules/@npmcli/run-script/package.json
+++ b/deps/npm/node_modules/@npmcli/run-script/package.json
@@ -1,6 +1,6 @@
{
"name": "@npmcli/run-script",
- "version": "10.0.4",
+ "version": "11.0.0",
"description": "Run a lifecycle script for a package (descendant of npm-lifecycle)",
"author": "GitHub Inc.",
"license": "ISC",
@@ -15,17 +15,17 @@
"template-oss-apply": "template-oss-apply --force"
},
"devDependencies": {
- "@npmcli/eslint-config": "^6.0.0",
- "@npmcli/template-oss": "4.29.0",
+ "@npmcli/eslint-config": "^7.0.0",
+ "@npmcli/template-oss": "5.1.0",
"spawk": "^1.8.1",
"tap": "^16.0.1"
},
"dependencies": {
- "@npmcli/node-gyp": "^5.0.0",
- "@npmcli/package-json": "^7.0.0",
- "@npmcli/promise-spawn": "^9.0.0",
- "node-gyp": "^12.1.0",
- "proc-log": "^6.0.0"
+ "@npmcli/node-gyp": "^6.0.0",
+ "@npmcli/package-json": "^8.0.0",
+ "@npmcli/promise-spawn": "^10.0.0",
+ "node-gyp": "^13.0.0",
+ "proc-log": "^7.0.0"
},
"files": [
"bin/",
@@ -37,12 +37,13 @@
"url": "git+https://github.com/npm/run-script.git"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.29.0",
- "publish": "true"
+ "version": "5.1.0",
+ "publish": "true",
+ "updateNpm": false
},
"tap": {
"nyc-arg": [
diff --git a/deps/npm/node_modules/@sigstore/bundle/dist/error.js b/deps/npm/node_modules/@sigstore/bundle/dist/error.js
index f84295323b8..c02ff06fc55 100644
--- a/deps/npm/node_modules/@sigstore/bundle/dist/error.js
+++ b/deps/npm/node_modules/@sigstore/bundle/dist/error.js
@@ -17,6 +17,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
class ValidationError extends Error {
+ fields;
constructor(message, fields) {
super(message);
this.fields = fields;
diff --git a/deps/npm/node_modules/@sigstore/bundle/package.json b/deps/npm/node_modules/@sigstore/bundle/package.json
index 03291b2159b..cb7650a8bab 100644
--- a/deps/npm/node_modules/@sigstore/bundle/package.json
+++ b/deps/npm/node_modules/@sigstore/bundle/package.json
@@ -1,6 +1,6 @@
{
"name": "@sigstore/bundle",
- "version": "4.0.0",
+ "version": "5.0.0",
"description": "Sigstore bundle type",
"main": "dist/index.js",
"types": "dist/index.d.ts",
@@ -30,6 +30,6 @@
"@sigstore/protobuf-specs": "^0.5.0"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
}
}
diff --git a/deps/npm/node_modules/@sigstore/core/dist/asn1/length.js b/deps/npm/node_modules/@sigstore/core/dist/asn1/length.js
index cb7ebf09dbe..f4bfd9a06a8 100644
--- a/deps/npm/node_modules/@sigstore/core/dist/asn1/length.js
+++ b/deps/npm/node_modules/@sigstore/core/dist/asn1/length.js
@@ -37,12 +37,23 @@ function decodeLength(stream) {
// Iterate over the bytes that encode the length.
let len = 0;
for (let i = 0; i < byteCount; i++) {
- len = len * 256 + stream.getUint8();
+ const byte = stream.getUint8();
+ // The first byte of a multi-byte length must not be zero; a leading zero
+ // means the length could have been encoded in fewer bytes (non-minimal).
+ if (i === 0 && byte === 0x00) {
+ throw new error_1.ASN1ParseError('non-minimal length encoding');
+ }
+ len = len * 256 + byte;
}
// This is a valid ASN.1 length encoding, but we don't support it.
if (len === 0) {
throw new error_1.ASN1ParseError('indefinite length encoding not supported');
}
+ // Lengths less than 128 must use the short form; rejecting them here ensures
+ // the encoding is minimal (strict DER).
+ if (len < 128) {
+ throw new error_1.ASN1ParseError('non-minimal length encoding');
+ }
return len;
}
// Translates the supplied value to a DER-encoded length.
diff --git a/deps/npm/node_modules/@sigstore/core/dist/asn1/obj.js b/deps/npm/node_modules/@sigstore/core/dist/asn1/obj.js
index 2dc90d6ac9b..1b8558a3510 100644
--- a/deps/npm/node_modules/@sigstore/core/dist/asn1/obj.js
+++ b/deps/npm/node_modules/@sigstore/core/dist/asn1/obj.js
@@ -32,7 +32,14 @@ class ASN1Obj {
}
// Constructs an ASN.1 object from a Buffer of DER-encoded bytes.
static parseBuffer(buf) {
- return parseStream(new stream_1.ByteStream(buf));
+ const stream = new stream_1.ByteStream(buf);
+ const obj = parseStream(stream);
+ // Ensure the entire buffer was consumed; trailing data after the top-level
+ // object indicates a malformed (or maliciously padded) encoding.
+ if (stream.position !== stream.length) {
+ throw new error_1.ASN1ParseError('invalid trailing data');
+ }
+ return obj;
}
toDER() {
const valueStream = new stream_1.ByteStream();
@@ -103,7 +110,14 @@ class ASN1Obj {
exports.ASN1Obj = ASN1Obj;
/////////////////////////////////////////////////////////////////////////////
// Internal stream parsing functions
-function parseStream(stream) {
+// Maximum nesting depth for parsed ASN.1 objects. Bounds the mutual recursion
+// between parseStream and collectSubs so that deeply nested DER cannot exhaust
+// the call stack (denial of service).
+const MAX_DEPTH = 100;
+function parseStream(stream, depth = 0) {
+ if (depth > MAX_DEPTH) {
+ throw new error_1.ASN1ParseError('maximum nesting depth exceeded');
+ }
// Parse tag, length, and value from stream
const tag = new tag_1.ASN1Tag(stream.getUint8());
const len = (0, length_1.decodeLength)(stream);
@@ -114,13 +128,17 @@ function parseStream(stream) {
// are embedded in OCTESTRING objects, so we need to check those
// for children as well.
if (tag.constructed) {
- subs = collectSubs(stream, len);
+ subs = collectSubs(stream, len, depth);
}
else if (tag.isOctetString()) {
// Attempt to parse children of OCTETSTRING objects. If anything fails,
- // assume the object is not constructed and treat as primitive.
+ // assume the object is not constructed and treat as primitive. This is
+ // intentional: it transparently unwraps DER content embedded in an OCTET
+ // STRING (e.g. X.509 extnValue, CMS eContent). The error is swallowed
+ // because a parse failure simply means the bytes are an opaque primitive
+ // value rather than a nested structure.
try {
- subs = collectSubs(stream, len);
+ subs = collectSubs(stream, len, depth);
}
catch (e) {
// Fail silently and treat as primitive
@@ -132,7 +150,7 @@ function parseStream(stream) {
}
return new ASN1Obj(tag, value, subs);
}
-function collectSubs(stream, len) {
+function collectSubs(stream, len, depth) {
// Calculate end of object content
const end = stream.position + len;
// Make sure there are enough bytes left in the stream. This should never
@@ -145,7 +163,7 @@ function collectSubs(stream, len) {
// Parse all children
const subs = [];
while (stream.position < end) {
- subs.push(parseStream(stream));
+ subs.push(parseStream(stream, depth + 1));
}
// When we're done parsing children, we should be at the end of the object
if (stream.position !== end) {
diff --git a/deps/npm/node_modules/@sigstore/core/dist/asn1/parse.js b/deps/npm/node_modules/@sigstore/core/dist/asn1/parse.js
index 7fbb42632c6..09acc8ccab5 100644
--- a/deps/npm/node_modules/@sigstore/core/dist/asn1/parse.js
+++ b/deps/npm/node_modules/@sigstore/core/dist/asn1/parse.js
@@ -21,6 +21,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
+const error_1 = require("./error");
const RE_TIME_SHORT_YEAR = /^(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\.\d{3})?Z$/;
const RE_TIME_LONG_YEAR = /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\.\d{3})?Z$/;
// Parse a BigInt from the DER-encoded buffer
@@ -83,16 +84,18 @@ function parseOID(buf) {
const first = Math.floor(n / 40);
const second = n % 40;
let oid = `${first}.${second}`;
- // Consume remaining bytes
- let val = 0;
+ // Consume remaining bytes. Use a BigInt accumulator so that arcs which
+ // exceed 32 bits are not silently truncated (a truncated arc could be made
+ // to collide with a trusted OID).
+ let val = 0n;
for (; pos < end; ++pos) {
n = buf[pos];
- val = (val << 7) + (n & 0x7f);
+ val = (val << 7n) + BigInt(n & 0x7f);
// If the left-most bit is NOT set, then this is the last byte in the
// sequence and we can add the value to the OID and reset the accumulator
if ((n & 0x80) === 0) {
oid += `.${val}`;
- val = 0;
+ val = 0n;
}
}
return oid;
@@ -100,13 +103,29 @@ function parseOID(buf) {
// Parse a boolean from the DER-encoded buffer
// https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-basic-types#boolean
function parseBoolean(buf) {
- return buf[0] !== 0;
+ // DER requires a BOOLEAN to be a single byte that is either 0x00 (false) or
+ // 0xff (true). Reject any other (non-canonical) encoding.
+ if (buf.length !== 1) {
+ throw new error_1.ASN1ParseError('invalid boolean');
+ }
+ switch (buf[0]) {
+ case 0x00:
+ return false;
+ case 0xff:
+ return true;
+ default:
+ throw new error_1.ASN1ParseError('invalid boolean');
+ }
}
// Parse a bit string from the DER-encoded buffer
// https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-bit-string
function parseBitString(buf) {
// First byte tell us how many unused bits are in the last byte
const unused = buf[0];
+ // The number of unused bits must be in the range 0-7.
+ if (unused > 7) {
+ throw new error_1.ASN1ParseError('invalid bit string');
+ }
const start = 1;
const end = buf.length;
const bits = [];
diff --git a/deps/npm/node_modules/@sigstore/core/package.json b/deps/npm/node_modules/@sigstore/core/package.json
index 82cab44654a..7bafeb09ac2 100644
--- a/deps/npm/node_modules/@sigstore/core/package.json
+++ b/deps/npm/node_modules/@sigstore/core/package.json
@@ -1,6 +1,6 @@
{
"name": "@sigstore/core",
- "version": "3.2.1",
+ "version": "4.0.1",
"description": "Base library for Sigstore",
"main": "dist/index.js",
"types": "dist/index.d.ts",
@@ -26,6 +26,6 @@
"provenance": true
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
}
}
diff --git a/deps/npm/node_modules/@sigstore/sign/dist/signer/fulcio/ephemeral.js b/deps/npm/node_modules/@sigstore/sign/dist/signer/fulcio/ephemeral.js
index 24b92d9f1f3..fe63d310718 100644
--- a/deps/npm/node_modules/@sigstore/sign/dist/signer/fulcio/ephemeral.js
+++ b/deps/npm/node_modules/@sigstore/sign/dist/signer/fulcio/ephemeral.js
@@ -33,7 +33,7 @@ class EphemeralSigner {
const signature = (0, crypto_1.sign)('sha256', data, this.keypair.privateKey);
const publicKey = this.keypair.publicKey
.export({ format: 'pem', type: 'spki' })
- .toString('ascii');
+ .toString();
return {
signature: signature,
key: { $case: 'publicKey', publicKey },
diff --git a/deps/npm/node_modules/@sigstore/sign/package.json b/deps/npm/node_modules/@sigstore/sign/package.json
index c6b3f184a7b..353f2e9c9ac 100644
--- a/deps/npm/node_modules/@sigstore/sign/package.json
+++ b/deps/npm/node_modules/@sigstore/sign/package.json
@@ -1,6 +1,6 @@
{
"name": "@sigstore/sign",
- "version": "4.1.1",
+ "version": "5.0.0",
"description": "Sigstore signing library",
"main": "dist/index.js",
"types": "dist/index.d.ts",
@@ -27,19 +27,19 @@
},
"devDependencies": {
"@sigstore/jest": "^0.0.0",
- "@sigstore/mock": "^0.12.0",
- "@sigstore/rekor-types": "^4.0.0",
+ "@sigstore/mock": "^0.13.0",
+ "@sigstore/rekor-types": "^5.0.0",
"@types/make-fetch-happen": "^10.0.4"
},
"dependencies": {
- "@sigstore/bundle": "^4.0.0",
- "@sigstore/core": "^3.2.0",
+ "@gar/promise-retry": "^1.0.2",
+ "@sigstore/bundle": "^5.0.0",
+ "@sigstore/core": "^4.0.0",
"@sigstore/protobuf-specs": "^0.5.0",
- "make-fetch-happen": "^15.0.4",
- "proc-log": "^6.1.0",
- "@gar/promise-retry": "^1.0.2"
+ "make-fetch-happen": "^16.0.0",
+ "proc-log": "^7.0.0"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
}
}
diff --git a/deps/npm/node_modules/@sigstore/tuf/package.json b/deps/npm/node_modules/@sigstore/tuf/package.json
index b1fd9bebe13..16bf7f75a01 100644
--- a/deps/npm/node_modules/@sigstore/tuf/package.json
+++ b/deps/npm/node_modules/@sigstore/tuf/package.json
@@ -1,6 +1,6 @@
{
"name": "@sigstore/tuf",
- "version": "4.0.2",
+ "version": "5.0.0",
"description": "Client for the Sigstore TUF repository",
"main": "dist/index.js",
"types": "dist/index.d.ts",
@@ -28,14 +28,14 @@
},
"devDependencies": {
"@sigstore/jest": "^0.0.0",
- "@tufjs/repo-mock": "^4.0.1",
+ "@tufjs/repo-mock": "^5.0.0",
"@types/make-fetch-happen": "^10.0.4"
},
"dependencies": {
"@sigstore/protobuf-specs": "^0.5.0",
- "tuf-js": "^4.1.0"
+ "tuf-js": "^6.0.0"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
}
}
diff --git a/deps/npm/node_modules/@sigstore/tuf/seeds.json b/deps/npm/node_modules/@sigstore/tuf/seeds.json
index 2bd03b34f7d..47c66e04c77 100644
--- a/deps/npm/node_modules/@sigstore/tuf/seeds.json
+++ b/deps/npm/node_modules/@sigstore/tuf/seeds.json
@@ -1 +1 @@
-{"https://tuf-repo-cdn.sigstore.dev":{"root.json":"ewogInNpZ25hdHVyZXMiOiBbCiAgewogICAia2V5aWQiOiAiZTcxYTU0ZDU0MzgzNWJhODZhZGFkOTQ2MDM3OWM3NjQxZmI4NzI2ZDE2NGVhNzY2ODAxYTFjNTIyYWJhN2VhMiIsCiAgICJzaWciOiAiMzA0NjAyMjEwMGUwNGM5NzA2Mjk5YmU1ZDhjMmIxNGZiNTBiY2Q1YjljMjQxZjEwNTk3MTUzZGZlMjJmOTQzZWZlODk2YjUxNTAwMjIxMDBjZmQ3YjlmMDZhNTkwMDc4NGUzMTJkMDJiOGUzMzZlZGJiM2IyZmFiNjFhYzE0NTUwYjMxMTJiNGY5ZTMzZGY0IgogIH0sCiAgewogICAia2V5aWQiOiAiMjJmNGNhZWM2ZDhlNmY5NTU1YWY2NmIzZDRjM2NiMDZhM2JiMjNmZGM3ZTM5YzkxNmM2MWY0NjJlNmY1MmIwNiIsCiAgICJzaWciOiAiIgogIH0sCiAgewogICAia2V5aWQiOiAiNjE2NDM4MzgxMjViNDQwYjQwZGI2OTQyZjVjYjVhMzFjMGRjMDQzNjgzMTZlYjJhYWE1OGI5NTkwNGE1ODIyMiIsCiAgICJzaWciOiAiMzA0NTAyMjEwMGNjMzA4YWU3ZDM5MGZhNzgyZWUzMzc2ZGRmYWE5Mjk4MzUwMTZlODZkYWQ4MWY2OWUyZGU3ZWMxZTE3NDQzMmUwMjIwNWZiMTk5MDZhMzFjY2UxNDZjMjk2MjQ0NDNjMGQwYzJmMzNlZTgwZGFjMzlkNzIxMTRmOTM5NjA3Y2MyMjkzNyIKICB9LAogIHsKICAgImtleWlkIjogImE2ODdlNWJmNGZhYjgyYjBlZTU4ZDQ2ZTA1Yzk1MzUxNDVhMmM5YWZiNDU4ZjQzZDQyYjQ1Y2EwZmRjZTJhNzAiLAogICAic2lnIjogIjMwNDUwMjIwM2Y4YWZmN2EzMGUwNWE4YzNkOTA0YjY3MWFiMWE2ZTRlOGE2ZjUwOGI3Y2ZhMGM3ODBlNzI5NzZiZWU3YTIyNzAyMjEwMGY2NGM5Yjc2NTUyNmYzNGQ5ZWExNjMzOWNmMjM4ODkzZTFjMzM2OGI0ZjA5MTBhNjFhMWFmMjdkZGEwMWViYjkiCiAgfSwKICB7CiAgICJrZXlpZCI6ICIxODNlNjRmMzc2NzBkYzEzY2EwZDI4OTk1YTMwNTNmMzc0MDk1NGRkY2U0NDMyMWE0MWU0NjUzNGNmNDRlNjMyIiwKICAgInNpZyI6ICIzMDQ1MDIyMDIzNjNjYTI0OWFlZmE2ZDVmNjFjNDA4YTMyY2RkMDc5YjAzNGE3ODg4ZGRmMjEzNmRjNDUxNWVkNGE3Mjg0MTgwMjIxMDBiMDRlY2E0MmJjNTEwY2NiYmY1ZDMwNzgzYWFhOTM2YjFmMTM3Y2E3YTAxN2VlOWQ5MGQzNzEwNDMyZGEwNDI3IgogIH0KIF0sCiAic2lnbmVkIjogewogICJfdHlwZSI6ICJyb290IiwKICAiY29uc2lzdGVudF9zbmFwc2hvdCI6IHRydWUsCiAgImV4cGlyZXMiOiAiMjAyNi0wNi0yMlQxMzoyNzowMVoiLAogICJrZXlzIjogewogICAiMGM4NzQzMmMzYmYwOWZkOTkxODlmZGMzMmZhNWVhZWRmNGU0YTVmYWM3YmFiNzNmYTA0YTJlMGZjNjRhZjZmNSI6IHsKICAgICJrZXlpZF9oYXNoX2FsZ29yaXRobXMiOiBbCiAgICAgInNoYTI1NiIsCiAgICAgInNoYTUxMiIKICAgIF0sCiAgICAia2V5dHlwZSI6ICJlY2RzYSIsCiAgICAia2V5dmFsIjogewogICAgICJwdWJsaWMiOiAiLS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS1cbk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRVdSaUdyNStqKzNKNVNzSCtadHI1bkUySDJ3TzdcbkJWK25PM3M5M2dMY2ExOHFUT3pIWTFvV3lBR0R5a01Tc0dUVUJTdDlEK0FuMEtmS3NEMm1mU000MlE9PVxuLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tXG4iCiAgICB9LAogICAgInNjaGVtZSI6ICJlY2RzYS1zaGEyLW5pc3RwMjU2IiwKICAgICJ4LXR1Zi1vbi1jaS1vbmxpbmUtdXJpIjogImdjcGttczpwcm9qZWN0cy9zaWdzdG9yZS1yb290LXNpZ25pbmcvbG9jYXRpb25zL2dsb2JhbC9rZXlSaW5ncy9yb290L2NyeXB0b0tleXMvdGltZXN0YW1wL2NyeXB0b0tleVZlcnNpb25zLzEiCiAgIH0sCiAgICIxODNlNjRmMzc2NzBkYzEzY2EwZDI4OTk1YTMwNTNmMzc0MDk1NGRkY2U0NDMyMWE0MWU0NjUzNGNmNDRlNjMyIjogewogICAgImtleXR5cGUiOiAiZWNkc2EiLAogICAgImtleXZhbCI6IHsKICAgICAicHVibGljIjogIi0tLS0tQkVHSU4gUFVCTElDIEtFWS0tLS0tXG5NRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVNeHBQT0pDSVo1b3RHNDEwNmZHSnNlRVFpM1Y5XG5wa01ZUTR1eVY5VGoxTTdXSFhJeUxHK2prZnZ1RzBnbFExSlpiUlpaQlYzZ0FSNHNvamRHSElTZW93PT1cbi0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLVxuIgogICAgfSwKICAgICJzY2hlbWUiOiAiZWNkc2Etc2hhMi1uaXN0cDI1NiIsCiAgICAieC10dWYtb24tY2kta2V5b3duZXIiOiAiQGxhbmNlIgogICB9LAogICAiMjJmNGNhZWM2ZDhlNmY5NTU1YWY2NmIzZDRjM2NiMDZhM2JiMjNmZGM3ZTM5YzkxNmM2MWY0NjJlNmY1MmIwNiI6IHsKICAgICJrZXlpZF9oYXNoX2FsZ29yaXRobXMiOiBbCiAgICAgInNoYTI1NiIsCiAgICAgInNoYTUxMiIKICAgIF0sCiAgICAia2V5dHlwZSI6ICJlY2RzYSIsCiAgICAia2V5dmFsIjogewogICAgICJwdWJsaWMiOiAiLS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS1cbk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRXpCelZPbUhDUG9qTVZMU0kzNjRXaWlWOE5QckRcbjZJZ1J4Vmxpc2t6L3YreTNKRVI1bWNWR2NPTmxpRGNXTUM1SjJsZkhtalBOUGhiNEg3eG04THpmU0E9PVxuLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tXG4iCiAgICB9LAogICAgInNjaGVtZSI6ICJlY2RzYS1zaGEyLW5pc3RwMjU2IiwKICAgICJ4LXR1Zi1vbi1jaS1rZXlvd25lciI6ICJAc2FudGlhZ290b3JyZXMiCiAgIH0sCiAgICI2MTY0MzgzODEyNWI0NDBiNDBkYjY5NDJmNWNiNWEzMWMwZGMwNDM2ODMxNmViMmFhYTU4Yjk1OTA0YTU4MjIyIjogewogICAgImtleWlkX2hhc2hfYWxnb3JpdGhtcyI6IFsKICAgICAic2hhMjU2IiwKICAgICAic2hhNTEyIgogICAgXSwKICAgICJrZXl0eXBlIjogImVjZHNhIiwKICAgICJrZXl2YWwiOiB7CiAgICAgInB1YmxpYyI6ICItLS0tLUJFR0lOIFBVQkxJQyBLRVktLS0tLVxuTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFaW5pa1NzQVFtWWtOZUg1ZVlxL0NuSXpMYWFjT1xueGxTYWF3UURPd3FLeS90Q3F4cTV4eFBTSmMyMUs0V0loczlHeU9rS2Z6dWVZM0dJTHpjTUpaNGNXdz09XG4tLS0tLUVORCBQVUJMSUMgS0VZLS0tLS1cbiIKICAgIH0sCiAgICAic2NoZW1lIjogImVjZHNhLXNoYTItbmlzdHAyNTYiLAogICAgIngtdHVmLW9uLWNpLWtleW93bmVyIjogIkBib2JjYWxsYXdheSIKICAgfSwKICAgImE2ODdlNWJmNGZhYjgyYjBlZTU4ZDQ2ZTA1Yzk1MzUxNDVhMmM5YWZiNDU4ZjQzZDQyYjQ1Y2EwZmRjZTJhNzAiOiB7CiAgICAia2V5aWRfaGFzaF9hbGdvcml0aG1zIjogWwogICAgICJzaGEyNTYiLAogICAgICJzaGE1MTIiCiAgICBdLAogICAgImtleXR5cGUiOiAiZWNkc2EiLAogICAgImtleXZhbCI6IHsKICAgICAicHVibGljIjogIi0tLS0tQkVHSU4gUFVCTElDIEtFWS0tLS0tXG5NRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUUwZ2hyaDkyTHcxWXIzaWRHVjVXcUN0TURCOEN4XG4rRDhoZEM0dzJaTE5JcGxWUm9WR0xza1lhM2doZU15T2ppSjhrUGkxNWFRMi8vN1Arb2o3VXZKUEd3PT1cbi0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLVxuIgogICAgfSwKICAgICJzY2hlbWUiOiAiZWNkc2Etc2hhMi1uaXN0cDI1NiIsCiAgICAieC10dWYtb24tY2kta2V5b3duZXIiOiAiQGpvc2h1YWdsIgogICB9LAogICAiZTcxYTU0ZDU0MzgzNWJhODZhZGFkOTQ2MDM3OWM3NjQxZmI4NzI2ZDE2NGVhNzY2ODAxYTFjNTIyYWJhN2VhMiI6IHsKICAgICJrZXlpZF9oYXNoX2FsZ29yaXRobXMiOiBbCiAgICAgInNoYTI1NiIsCiAgICAgInNoYTUxMiIKICAgIF0sCiAgICAia2V5dHlwZSI6ICJlY2RzYSIsCiAgICAia2V5dmFsIjogewogICAgICJwdWJsaWMiOiAiLS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS1cbk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRUVYc3ozU1pYRmI4ak1WNDJqNnBKbHlqYmpSOEtcbk4zQndvY2V4cTZMTUliNXFzV0tPUXZMTjE2TlVlZkxjNEhzd09vdW1Sc1ZWYWFqU3BRUzZmb2JrUnc9PVxuLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tXG4iCiAgICB9LAogICAgInNjaGVtZSI6ICJlY2RzYS1zaGEyLW5pc3RwMjU2IiwKICAgICJ4LXR1Zi1vbi1jaS1rZXlvd25lciI6ICJAbW5tNjc4IgogICB9CiAgfSwKICAicm9sZXMiOiB7CiAgICJyb290IjogewogICAgImtleWlkcyI6IFsKICAgICAiZTcxYTU0ZDU0MzgzNWJhODZhZGFkOTQ2MDM3OWM3NjQxZmI4NzI2ZDE2NGVhNzY2ODAxYTFjNTIyYWJhN2VhMiIsCiAgICAgIjIyZjRjYWVjNmQ4ZTZmOTU1NWFmNjZiM2Q0YzNjYjA2YTNiYjIzZmRjN2UzOWM5MTZjNjFmNDYyZTZmNTJiMDYiLAogICAgICI2MTY0MzgzODEyNWI0NDBiNDBkYjY5NDJmNWNiNWEzMWMwZGMwNDM2ODMxNmViMmFhYTU4Yjk1OTA0YTU4MjIyIiwKICAgICAiYTY4N2U1YmY0ZmFiODJiMGVlNThkNDZlMDVjOTUzNTE0NWEyYzlhZmI0NThmNDNkNDJiNDVjYTBmZGNlMmE3MCIsCiAgICAgIjE4M2U2NGYzNzY3MGRjMTNjYTBkMjg5OTVhMzA1M2YzNzQwOTU0ZGRjZTQ0MzIxYTQxZTQ2NTM0Y2Y0NGU2MzIiCiAgICBdLAogICAgInRocmVzaG9sZCI6IDMKICAgfSwKICAgInNuYXBzaG90IjogewogICAgImtleWlkcyI6IFsKICAgICAiMGM4NzQzMmMzYmYwOWZkOTkxODlmZGMzMmZhNWVhZWRmNGU0YTVmYWM3YmFiNzNmYTA0YTJlMGZjNjRhZjZmNSIKICAgIF0sCiAgICAidGhyZXNob2xkIjogMSwKICAgICJ4LXR1Zi1vbi1jaS1leHBpcnktcGVyaW9kIjogMzY1MCwKICAgICJ4LXR1Zi1vbi1jaS1zaWduaW5nLXBlcmlvZCI6IDM2NQogICB9LAogICAidGFyZ2V0cyI6IHsKICAgICJrZXlpZHMiOiBbCiAgICAgImU3MWE1NGQ1NDM4MzViYTg2YWRhZDk0NjAzNzljNzY0MWZiODcyNmQxNjRlYTc2NjgwMWExYzUyMmFiYTdlYTIiLAogICAgICIyMmY0Y2FlYzZkOGU2Zjk1NTVhZjY2YjNkNGMzY2IwNmEzYmIyM2ZkYzdlMzljOTE2YzYxZjQ2MmU2ZjUyYjA2IiwKICAgICAiNjE2NDM4MzgxMjViNDQwYjQwZGI2OTQyZjVjYjVhMzFjMGRjMDQzNjgzMTZlYjJhYWE1OGI5NTkwNGE1ODIyMiIsCiAgICAgImE2ODdlNWJmNGZhYjgyYjBlZTU4ZDQ2ZTA1Yzk1MzUxNDVhMmM5YWZiNDU4ZjQzZDQyYjQ1Y2EwZmRjZTJhNzAiLAogICAgICIxODNlNjRmMzc2NzBkYzEzY2EwZDI4OTk1YTMwNTNmMzc0MDk1NGRkY2U0NDMyMWE0MWU0NjUzNGNmNDRlNjMyIgogICAgXSwKICAgICJ0aHJlc2hvbGQiOiAzCiAgIH0sCiAgICJ0aW1lc3RhbXAiOiB7CiAgICAia2V5aWRzIjogWwogICAgICIwYzg3NDMyYzNiZjA5ZmQ5OTE4OWZkYzMyZmE1ZWFlZGY0ZTRhNWZhYzdiYWI3M2ZhMDRhMmUwZmM2NGFmNmY1IgogICAgXSwKICAgICJ0aHJlc2hvbGQiOiAxLAogICAgIngtdHVmLW9uLWNpLWV4cGlyeS1wZXJpb2QiOiA3LAogICAgIngtdHVmLW9uLWNpLXNpZ25pbmctcGVyaW9kIjogNgogICB9CiAgfSwKICAic3BlY192ZXJzaW9uIjogIjEuMCIsCiAgInZlcnNpb24iOiAxNCwKICAieC10dWYtb24tY2ktZXhwaXJ5LXBlcmlvZCI6IDE5NywKICAieC10dWYtb24tY2ktc2lnbmluZy1wZXJpb2QiOiA0NgogfQp9","targets":{"trusted_root.json":"ewogICJtZWRpYVR5cGUiOiAiYXBwbGljYXRpb24vdm5kLmRldi5zaWdzdG9yZS50cnVzdGVkcm9vdCtqc29uO3ZlcnNpb249MC4xIiwKICAidGxvZ3MiOiBbCiAgICB7CiAgICAgICJiYXNlVXJsIjogImh0dHBzOi8vcmVrb3Iuc2lnc3RvcmUuZGV2IiwKICAgICAgImhhc2hBbGdvcml0aG0iOiAiU0hBMl8yNTYiLAogICAgICAicHVibGljS2V5IjogewogICAgICAgICJyYXdCeXRlcyI6ICJNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUUyRzJZKzJ0YWJkVFY1QmNHaUJJeDBhOWZBRndya0JibUxTR3RrczRMM3FYNnlZWTB6dWZCbmhDOFVyL2l5NTVHaFdQLzlBL2JZMkxoQzMwTTkrUll0dz09IiwKICAgICAgICAia2V5RGV0YWlscyI6ICJQS0lYX0VDRFNBX1AyNTZfU0hBXzI1NiIsCiAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgInN0YXJ0IjogIjIwMjEtMDEtMTJUMTE6NTM6MjdaIgogICAgICAgIH0KICAgICAgfSwKICAgICAgImxvZ0lkIjogewogICAgICAgICJrZXlJZCI6ICJ3Tkk5YXRRR2x6K1ZXZk82TFJ5Z0g0UVVmWS84VzRSRndpVDVpNVdSZ0IwPSIKICAgICAgfQogICAgfSwKICAgIHsKICAgICAgImJhc2VVcmwiOiAiaHR0cHM6Ly9sb2cyMDI1LTEucmVrb3Iuc2lnc3RvcmUuZGV2IiwKICAgICAgImhhc2hBbGdvcml0aG0iOiAiU0hBMl8yNTYiLAogICAgICAicHVibGljS2V5IjogewogICAgICAgICJyYXdCeXRlcyI6ICJNQ293QlFZREsyVndBeUVBdDhybHAxa25Hd2pmYmNYQVlQWUFrbjBYaUx6MXg4TzR0MFlrRWhpZTI0ND0iLAogICAgICAgICJrZXlEZXRhaWxzIjogIlBLSVhfRUQyNTUxOSIsCiAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgInN0YXJ0IjogIjIwMjUtMDktMjNUMDA6MDA6MDBaIgogICAgICAgIH0KICAgICAgfSwKICAgICAgImxvZ0lkIjogewogICAgICAgICJrZXlJZCI6ICJ6eEdaRlZ2ZDBGRW1qUjhXckZ3TWRjQUo5dnRhWS9RWGY0NFkxd1VlUDZBPSIKICAgICAgfQogICAgfQogIF0sCiAgImNlcnRpZmljYXRlQXV0aG9yaXRpZXMiOiBbCiAgICB7CiAgICAgICJzdWJqZWN0IjogewogICAgICAgICJvcmdhbml6YXRpb24iOiAic2lnc3RvcmUuZGV2IiwKICAgICAgICAiY29tbW9uTmFtZSI6ICJzaWdzdG9yZSIKICAgICAgfSwKICAgICAgInVyaSI6ICJodHRwczovL2Z1bGNpby5zaWdzdG9yZS5kZXYiLAogICAgICAiY2VydENoYWluIjogewogICAgICAgICJjZXJ0aWZpY2F0ZXMiOiBbCiAgICAgICAgICB7CiAgICAgICAgICAgICJyYXdCeXRlcyI6ICJNSUlCK0RDQ0FYNmdBd0lCQWdJVE5Wa0Rab0Npb2ZQRHN5N2RmbTZnZUxidWh6QUtCZ2dxaGtqT1BRUURBekFxTVJVd0V3WURWUVFLRXd4emFXZHpkRzl5WlM1a1pYWXhFVEFQQmdOVkJBTVRDSE5wWjNOMGIzSmxNQjRYRFRJeE1ETXdOekF6TWpBeU9Wb1hEVE14TURJeU16QXpNakF5T1Zvd0tqRVZNQk1HQTFVRUNoTU1jMmxuYzNSdmNtVXVaR1YyTVJFd0R3WURWUVFERXdoemFXZHpkRzl5WlRCMk1CQUdCeXFHU000OUFnRUdCU3VCQkFBaUEySUFCTFN5QTdJaTVrK3BOTzhaRVdZMHlsZW1XRG93T2tOYTNrTCtHWkU1WjVHV2VoTDkvQTliUk5BM1JicnNaNWkwSmNhc3RhUkw3U3A1ZnAvakQ1ZHhxYy9VZFRWbmx2UzE2YW4rMllmc3dlL1F1TG9sUlVDcmNPRTIrMmlBNSt0emQ2Tm1NR1F3RGdZRFZSMFBBUUgvQkFRREFnRUdNQklHQTFVZEV3RUIvd1FJTUFZQkFmOENBUUV3SFFZRFZSME9CQllFRk1qRkhRQkJtaVFwTWxFazZ3MnVTdTFLQnRQc01COEdBMVVkSXdRWU1CYUFGTWpGSFFCQm1pUXBNbEVrNncydVN1MUtCdFBzTUFvR0NDcUdTTTQ5QkFNREEyZ0FNR1VDTUg4bGlXSmZNdWk2dlhYQmhqRGdZNE13c2xtTi9USnhWZS84M1dyRm9td21OZjA1NnkxWDQ4RjljNG0zYTNvelhBSXhBS2pSYXk1L2FqL2pzS0tHSWttUWF0akk4dXVwSHIvK0N4RnZhSldtcFlxTmtMREdSVSs5b3J6aDVoSTJScmN1YVE9PSIKICAgICAgICAgIH0KICAgICAgICBdCiAgICAgIH0sCiAgICAgICJ2YWxpZEZvciI6IHsKICAgICAgICAic3RhcnQiOiAiMjAyMS0wMy0wN1QwMzoyMDoyOVoiLAogICAgICAgICJlbmQiOiAiMjAyMi0xMi0zMVQyMzo1OTo1OS45OTlaIgogICAgICB9CiAgICB9LAogICAgewogICAgICAic3ViamVjdCI6IHsKICAgICAgICAib3JnYW5pemF0aW9uIjogInNpZ3N0b3JlLmRldiIsCiAgICAgICAgImNvbW1vbk5hbWUiOiAic2lnc3RvcmUiCiAgICAgIH0sCiAgICAgICJ1cmkiOiAiaHR0cHM6Ly9mdWxjaW8uc2lnc3RvcmUuZGV2IiwKICAgICAgImNlcnRDaGFpbiI6IHsKICAgICAgICAiY2VydGlmaWNhdGVzIjogWwogICAgICAgICAgewogICAgICAgICAgICAicmF3Qnl0ZXMiOiAiTUlJQ0dqQ0NBYUdnQXdJQkFnSVVBTG5WaVZmblUwYnJKYXNtUmtIcm4vVW5mYVF3Q2dZSUtvWkl6ajBFQXdNd0tqRVZNQk1HQTFVRUNoTU1jMmxuYzNSdmNtVXVaR1YyTVJFd0R3WURWUVFERXdoemFXZHpkRzl5WlRBZUZ3MHlNakEwTVRNeU1EQTJNVFZhRncwek1URXdNRFV4TXpVMk5UaGFNRGN4RlRBVEJnTlZCQW9UREhOcFozTjBiM0psTG1SbGRqRWVNQndHQTFVRUF4TVZjMmxuYzNSdmNtVXRhVzUwWlhKdFpXUnBZWFJsTUhZd0VBWUhLb1pJemowQ0FRWUZLNEVFQUNJRFlnQUU4UlZTL3lzSCtOT3Z1RFp5UEladGlsZ1VGOU5sYXJZcEFkOUhQMXZCQkgxVTVDVjc3TFNTN3MwWmlING5FN0h2N3B0UzZMdnZSL1NUazc5OExWZ016TGxKNEhlSWZGM3RIU2FleExjWXBTQVNyMWtTME4vUmdCSnovOWpXQ2lYbm8zc3dlVEFPQmdOVkhROEJBZjhFQkFNQ0FRWXdFd1lEVlIwbEJBd3dDZ1lJS3dZQkJRVUhBd013RWdZRFZSMFRBUUgvQkFnd0JnRUIvd0lCQURBZEJnTlZIUTRFRmdRVTM5UHB6MVlrRVpiNXFOanBLRldpeGk0WVpEOHdId1lEVlIwakJCZ3dGb0FVV01BZVg1RkZwV2FwZXN5UW9aTWkwQ3JGeGZvd0NnWUlLb1pJemowRUF3TURad0F3WkFJd1BDc1FLNERZaVpZRFBJYURpNUhGS25meFh4NkFTU1ZtRVJmc3luWUJpWDJYNlNKUm5aVTg0LzlEWmRuRnZ2eG1BakJPdDZRcEJsYzRKLzBEeHZrVENxcGNsdnppTDZCQ0NQbmpkbElCM1B1M0J4c1BteWdVWTdJaTJ6YmRDZGxpaW93PSIKICAgICAgICAgIH0sCiAgICAgICAgICB7CiAgICAgICAgICAgICJyYXdCeXRlcyI6ICJNSUlCOXpDQ0FYeWdBd0lCQWdJVUFMWk5BUEZkeEhQd2plRGxvRHd5WUNoQU8vNHdDZ1lJS29aSXpqMEVBd013S2pFVk1CTUdBMVVFQ2hNTWMybG5jM1J2Y21VdVpHVjJNUkV3RHdZRFZRUURFd2h6YVdkemRHOXlaVEFlRncweU1URXdNRGN4TXpVMk5UbGFGdzB6TVRFd01EVXhNelUyTlRoYU1Db3hGVEFUQmdOVkJBb1RESE5wWjNOMGIzSmxMbVJsZGpFUk1BOEdBMVVFQXhNSWMybG5jM1J2Y21Vd2RqQVFCZ2NxaGtqT1BRSUJCZ1VyZ1FRQUlnTmlBQVQ3WGVGVDRyYjNQUUd3UzRJYWp0TGszL09sbnBnYW5nYUJjbFlwc1lCcjVpKzR5bkIwN2NlYjNMUDBPSU9aZHhleFg2OWM1aVZ1eUpSUStIejA1eWkrVUYzdUJXQWxIcGlTNXNoMCtIMkdIRTdTWHJrMUVDNW0xVHIxOUw5Z2c5MmpZekJoTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlJZd0I1ZmtVV2xacWw2ekpDaGt5TFFLc1hGK2pBZkJnTlZIU01FR0RBV2dCUll3QjVma1VXbFpxbDZ6SkNoa3lMUUtzWEYrakFLQmdncWhrak9QUVFEQXdOcEFEQm1BakVBajFuSGVYWnArMTNOV0JOYStFRHNEUDhHMVdXZzF0Q01XUC9XSFBxcGFWbzBqaHN3ZU5GWmdTczBlRTd3WUk0cUFqRUEyV0I5b3Q5OHNJa29GM3ZaWWRkMy9WdFdCNWI5VE5NZWE3SXgvc3RKNVRmY0xMZUFCTEU0Qk5KT3NRNHZuQkhKIgogICAgICAgICAgfQogICAgICAgIF0KICAgICAgfSwKICAgICAgInZhbGlkRm9yIjogewogICAgICAgICJzdGFydCI6ICIyMDIyLTA0LTEzVDIwOjA2OjE1WiIKICAgICAgfQogICAgfQogIF0sCiAgImN0bG9ncyI6IFsKICAgIHsKICAgICAgImJhc2VVcmwiOiAiaHR0cHM6Ly9jdGZlLnNpZ3N0b3JlLmRldi90ZXN0IiwKICAgICAgImhhc2hBbGdvcml0aG0iOiAiU0hBMl8yNTYiLAogICAgICAicHVibGljS2V5IjogewogICAgICAgICJyYXdCeXRlcyI6ICJNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUViZndSK1JKdWRYc2NnUkJScEtYMVhGRHkzUHl1ZER4ei9TZm5SaTFmVDhla3BmQmQyTzF1b3o3anIzWjhuS3p4QTY5RVVRK2VGQ0ZJM3pldWJQV1U3dz09IiwKICAgICAgICAia2V5RGV0YWlscyI6ICJQS0lYX0VDRFNBX1AyNTZfU0hBXzI1NiIsCiAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgInN0YXJ0IjogIjIwMjEtMDMtMTRUMDA6MDA6MDBaIiwKICAgICAgICAgICJlbmQiOiAiMjAyMi0xMC0zMVQyMzo1OTo1OS45OTlaIgogICAgICAgIH0KICAgICAgfSwKICAgICAgImxvZ0lkIjogewogICAgICAgICJrZXlJZCI6ICJDR0NTOENoUy8yaEYwZEZySjRTY1JXY1lyQlk5d3pqU2JlYThJZ1kyYjNJPSIKICAgICAgfQogICAgfSwKICAgIHsKICAgICAgImJhc2VVcmwiOiAiaHR0cHM6Ly9jdGZlLnNpZ3N0b3JlLmRldi8yMDIyIiwKICAgICAgImhhc2hBbGdvcml0aG0iOiAiU0hBMl8yNTYiLAogICAgICAicHVibGljS2V5IjogewogICAgICAgICJyYXdCeXRlcyI6ICJNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVpUFNsRmkwQ21GVGZFakNVcUY5SHVDRWNZWE5LQWFZYWxJSm1CWjh5eWV6UGpUcWh4cktCcE1uYW9jVnRMSkJJMWVNM3VYblF6UUdBSmRKNGdzOUZ5dz09IiwKICAgICAgICAia2V5RGV0YWlscyI6ICJQS0lYX0VDRFNBX1AyNTZfU0hBXzI1NiIsCiAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgInN0YXJ0IjogIjIwMjItMTAtMjBUMDA6MDA6MDBaIgogICAgICAgIH0KICAgICAgfSwKICAgICAgImxvZ0lkIjogewogICAgICAgICJrZXlJZCI6ICIzVDB3YXNiSEVUSmpHUjRjbVdjM0FxSktYcmplUEszL2g0cHlnQzhwN280PSIKICAgICAgfQogICAgfQogIF0sCiAgInRpbWVzdGFtcEF1dGhvcml0aWVzIjogWwogICAgewogICAgICAic3ViamVjdCI6IHsKICAgICAgICAib3JnYW5pemF0aW9uIjogInNpZ3N0b3JlLmRldiIsCiAgICAgICAgImNvbW1vbk5hbWUiOiAic2lnc3RvcmUtdHNhLXNlbGZzaWduZWQiCiAgICAgIH0sCiAgICAgICJ1cmkiOiAiaHR0cHM6Ly90aW1lc3RhbXAuc2lnc3RvcmUuZGV2L2FwaS92MS90aW1lc3RhbXAiLAogICAgICAiY2VydENoYWluIjogewogICAgICAgICJjZXJ0aWZpY2F0ZXMiOiBbCiAgICAgICAgICB7CiAgICAgICAgICAgICJyYXdCeXRlcyI6ICJNSUlDRURDQ0FaYWdBd0lCQWdJVU9oTlVMd3lRWWU2OHdVTXZ5NHFPaXlvaml3d3dDZ1lJS29aSXpqMEVBd013T1RFVk1CTUdBMVVFQ2hNTWMybG5jM1J2Y21VdVpHVjJNU0F3SGdZRFZRUURFeGR6YVdkemRHOXlaUzEwYzJFdGMyVnNabk5wWjI1bFpEQWVGdzB5TlRBME1EZ3dOalU1TkROYUZ3MHpOVEEwTURZd05qVTVORE5hTUM0eEZUQVRCZ05WQkFvVERITnBaM04wYjNKbExtUmxkakVWTUJNR0ExVUVBeE1NYzJsbmMzUnZjbVV0ZEhOaE1IWXdFQVlIS29aSXpqMENBUVlGSzRFRUFDSURZZ0FFNHJhMlo4aEtOaWcyVDlrRmpDQVRvR0czMGpreStXUXYzQnpMK21LdmgxU0tOUi9Vd3V3c2ZOQ2c0c3J5b1lBZDhFNmlzb3ZWQTNNNGFvTmRtOVFEaTUwWjhuVEV5dnFnZkRQdFRJd1hJdGZpVy9BRmYxVjd1d2tia0FvajB4eGNvMm93YURBT0JnTlZIUThCQWY4RUJBTUNCNEF3SFFZRFZSME9CQllFRkluOWVVT0h6OUJsUnNNQ1JzY3NjMXQ5dE9zRE1COEdBMVVkSXdRWU1CYUFGSmpzQWU5L3UxSC8xSlVlYjRxSW1GTUhpYzYvTUJZR0ExVWRKUUVCL3dRTU1Bb0dDQ3NHQVFVRkJ3TUlNQW9HQ0NxR1NNNDlCQU1EQTJnQU1HVUNNRHRwc1YvNkthTzBxeUYvVU1zWDJhU1VYS1FGZG9HVHB0UUdjMGZ0cTFjc3VsSFBHRzZkc215TU5kM0pCK0czRVFJeEFPYWp2QmNqcEptS2I0TnYrMlRhb2o4VWM1K2I2aWg2RlhDQ0tyYVNxdXBlMDd6cXN3TWNYSlRlMWNFeHZIdnZsdz09IgogICAgICAgICAgfSwKICAgICAgICAgIHsKICAgICAgICAgICAgInJhd0J5dGVzIjogIk1JSUI5ekNDQVh5Z0F3SUJBZ0lVVjdmMEdMRE9vRXpJaDhMWFNXODBPSmlVcDE0d0NnWUlLb1pJemowRUF3TXdPVEVWTUJNR0ExVUVDaE1NYzJsbmMzUnZjbVV1WkdWMk1TQXdIZ1lEVlFRREV4ZHphV2R6ZEc5eVpTMTBjMkV0YzJWc1puTnBaMjVsWkRBZUZ3MHlOVEEwTURnd05qVTVORE5hRncwek5UQTBNRFl3TmpVNU5ETmFNRGt4RlRBVEJnTlZCQW9UREhOcFozTjBiM0psTG1SbGRqRWdNQjRHQTFVRUF4TVhjMmxuYzNSdmNtVXRkSE5oTFhObGJHWnphV2R1WldRd2RqQVFCZ2NxaGtqT1BRSUJCZ1VyZ1FRQUlnTmlBQVFVUU50ZlJUL291M1lBVGE2d0Iva0tUZTcwY2ZKd3lSSUJvdk1udDhSY0pwaC9DT0U4MnV5UzZGbXBwTExMMVZCUEdjUGZwUVBZSk5Yeld3aThpY3doS1E2Vy9RZTJoM29lYkJiMkZIcHdOSkRxbytUTWFDL3RkZmt2L0VsSkI3MmpSVEJETUE0R0ExVWREd0VCL3dRRUF3SUJCakFTQmdOVkhSTUJBZjhFQ0RBR0FRSC9BZ0VBTUIwR0ExVWREZ1FXQkJTWTdBSHZmN3RSLzlTVkhtK0tpSmhUQjRuT3Z6QUtCZ2dxaGtqT1BRUURBd05wQURCbUFqRUF3R0VHcmZHWlIxY2VuMVI4L0RUVk1JOTQzTHNzWm1KUnREcC9pN1NmR0htR1JQNmdSYnVqOXZPSzNiNjdaMFFRQWpFQXVUMkg2NzNMUUVhSFRjeVFTWnJrcDRtWDdXd2ttRitzVmJrWVk1bVhOK1JNSDEzS1VFSEhPcUFTYWVtWVdLL0UiCiAgICAgICAgICB9CiAgICAgICAgXQogICAgICB9LAogICAgICAidmFsaWRGb3IiOiB7CiAgICAgICAgInN0YXJ0IjogIjIwMjUtMDctMDRUMDA6MDA6MDBaIgogICAgICB9CiAgICB9CiAgXQp9Cg==","registry.npmjs.org%2Fkeys.json":"ewogICAgImtleXMiOiBbCiAgICAgICAgewogICAgICAgICAgICAia2V5SWQiOiAiU0hBMjU2OmpsM2J3c3d1ODBQampva0NnaDBvMnc1YzJVNExoUUFFNTdnajljejFrekEiLAogICAgICAgICAgICAia2V5VXNhZ2UiOiAibnBtOnNpZ25hdHVyZXMiLAogICAgICAgICAgICAicHVibGljS2V5IjogewogICAgICAgICAgICAgICAgInJhd0J5dGVzIjogIk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRTFPbGIzek1BRkZ4WEtIaUlrUU81Y0ozWWhsNWk2VVBwK0lodXRlQkpidUhjQTVVb2dLbzBFV3RsV3dXNktTYUtvVE5FWUw3SmxDUWlWbmtoQmt0VWdnPT0iLAogICAgICAgICAgICAgICAgImtleURldGFpbHMiOiAiUEtJWF9FQ0RTQV9QMjU2X1NIQV8yNTYiLAogICAgICAgICAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgICAgICAgICAgICJzdGFydCI6ICIxOTk5LTAxLTAxVDAwOjAwOjAwLjAwMFoiLAogICAgICAgICAgICAgICAgICAgICJlbmQiOiAiMjAyNS0wMS0yOVQwMDowMDowMC4wMDBaIgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICB7CiAgICAgICAgICAgICJrZXlJZCI6ICJTSEEyNTY6amwzYndzd3U4MFBqam9rQ2doMG8ydzVjMlU0TGhRQUU1N2dqOWN6MWt6QSIsCiAgICAgICAgICAgICJrZXlVc2FnZSI6ICJucG06YXR0ZXN0YXRpb25zIiwKICAgICAgICAgICAgInB1YmxpY0tleSI6IHsKICAgICAgICAgICAgICAgICJyYXdCeXRlcyI6ICJNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUUxT2xiM3pNQUZGeFhLSGlJa1FPNWNKM1lobDVpNlVQcCtJaHV0ZUJKYnVIY0E1VW9nS28wRVd0bFd3VzZLU2FLb1RORVlMN0psQ1FpVm5raEJrdFVnZz09IiwKICAgICAgICAgICAgICAgICJrZXlEZXRhaWxzIjogIlBLSVhfRUNEU0FfUDI1Nl9TSEFfMjU2IiwKICAgICAgICAgICAgICAgICJ2YWxpZEZvciI6IHsKICAgICAgICAgICAgICAgICAgICAic3RhcnQiOiAiMjAyMi0xMi0wMVQwMDowMDowMC4wMDBaIiwKICAgICAgICAgICAgICAgICAgICAiZW5kIjogIjIwMjUtMDEtMjlUMDA6MDA6MDAuMDAwWiIKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgewogICAgICAgICAgICAia2V5SWQiOiAiU0hBMjU2OkRoUTh3UjVBUEJ2RkhMRi8rVGMrQVl2UE9kVHBjSURxT2h4c0JIUndDN1UiLAogICAgICAgICAgICAia2V5VXNhZ2UiOiAibnBtOnNpZ25hdHVyZXMiLAogICAgICAgICAgICAicHVibGljS2V5IjogewogICAgICAgICAgICAgICAgInJhd0J5dGVzIjogIk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRVk2WWE3VysrN2FVUHp2TVRyZXpINlljeDNjK0hPS1lDY05HeWJKWlNDSnEvZmQ3UWE4dXVBS3RkSWtVUXRRaUVLRVJoQW1FNWxNTUpoUDhPa0RPYTJnPT0iLAogICAgICAgICAgICAgICAgImtleURldGFpbHMiOiAiUEtJWF9FQ0RTQV9QMjU2X1NIQV8yNTYiLAogICAgICAgICAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgICAgICAgICAgICJzdGFydCI6ICIyMDI1LTAxLTEzVDAwOjAwOjAwLjAwMFoiCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIHsKICAgICAgICAgICAgImtleUlkIjogIlNIQTI1NjpEaFE4d1I1QVBCdkZITEYvK1RjK0FZdlBPZFRwY0lEcU9oeHNCSFJ3QzdVIiwKICAgICAgICAgICAgImtleVVzYWdlIjogIm5wbTphdHRlc3RhdGlvbnMiLAogICAgICAgICAgICAicHVibGljS2V5IjogewogICAgICAgICAgICAgICAgInJhd0J5dGVzIjogIk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRVk2WWE3VysrN2FVUHp2TVRyZXpINlljeDNjK0hPS1lDY05HeWJKWlNDSnEvZmQ3UWE4dXVBS3RkSWtVUXRRaUVLRVJoQW1FNWxNTUpoUDhPa0RPYTJnPT0iLAogICAgICAgICAgICAgICAgImtleURldGFpbHMiOiAiUEtJWF9FQ0RTQV9QMjU2X1NIQV8yNTYiLAogICAgICAgICAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgICAgICAgICAgICJzdGFydCI6ICIyMDI1LTAxLTEzVDAwOjAwOjAwLjAwMFoiCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICBdCn0K"}}}
+{"https://tuf-repo-cdn.sigstore.dev":{"root.json":"ewogInNpZ25hdHVyZXMiOiBbCiAgewogICAia2V5aWQiOiAiZTcxYTU0ZDU0MzgzNWJhODZhZGFkOTQ2MDM3OWM3NjQxZmI4NzI2ZDE2NGVhNzY2ODAxYTFjNTIyYWJhN2VhMiIsCiAgICJzaWciOiAiMzA0NTAyMjEwMGVhMmYzNzRmNDA5ODEwZTJkYjk1MDc0OWQ5Y2ZlZDA5YTE1YjZhNWUyNWYzZDVmZmQwNzk5NDU5ZDdiZWUxNjcwMjIwMjhkM2FjZGRlNmRiZDUwMzRjZmFkMjIyZDMxYjQxMDkwZWUyMTg5NGUyYzQ2Y2I4OTc0MTk4YWIwMzc3ZGI0NCIKICB9LAogIHsKICAgImtleWlkIjogIjIyZjRjYWVjNmQ4ZTZmOTU1NWFmNjZiM2Q0YzNjYjA2YTNiYjIzZmRjN2UzOWM5MTZjNjFmNDYyZTZmNTJiMDYiLAogICAic2lnIjogIjMwNDQwMjIwN2ViYjI0ZTMyMzdlNDcwNjkxZDc4NzU5MDNhNzc1NGQwZWYyYWU3ZTdiNTAyNGE3ODg4YzlhMzhhNTJkZWVjZDAyMjA2ZWQ1YWQxYzZmNGZhYjQ2OTk1ODQzYWI2YjIzZjk0MjBjNWE0Y2Y2Y2UxY2IyY2IyYTZmYzJlODdlMmVmM2UxIgogIH0sCiAgewogICAia2V5aWQiOiAiNjE2NDM4MzgxMjViNDQwYjQwZGI2OTQyZjVjYjVhMzFjMGRjMDQzNjgzMTZlYjJhYWE1OGI5NTkwNGE1ODIyMiIsCiAgICJzaWciOiAiMzA0NjAyMjEwMDg5ZDlkZmQ4ZTEwNmNjOTU4MDg4YTRkYTNjOGNmNzI1NGFiNmY2NWE5NjQ3ZDM3YWRhNzMwZWY0NzYzYzUxNjMwMjIxMDBkODgyZWU3NDQ2MTViZTc5ODYxZTIxNGUxZWViOWUxZWRkZjZhMWUyMDNhMjAxYjRjNWQwM2Y1MjI0ZDcxZDE2IgogIH0sCiAgewogICAia2V5aWQiOiAiYTY4N2U1YmY0ZmFiODJiMGVlNThkNDZlMDVjOTUzNTE0NWEyYzlhZmI0NThmNDNkNDJiNDVjYTBmZGNlMmE3MCIsCiAgICJzaWciOiAiMzA0NTAyMjEwMDg4YmQ0Yjg4ZTgzZjU4NmNlNTY4ZDI3ZDA0MjE0YzRhYjNmZDE4OTQxNzhlZjAxNTMwM2Q1NmFmYTkzOTIwNTMwMjIwNTUzOGViYWI5Mzg3NmFiYjkwNzVhZDc3MTE0YmZmMjhhMGQ3OWE3Y2MyMjliNTM0YTBjNWNlZDU1MjZiNDhlNyIKICB9LAogIHsKICAgImtleWlkIjogIjE4M2U2NGYzNzY3MGRjMTNjYTBkMjg5OTVhMzA1M2YzNzQwOTU0ZGRjZTQ0MzIxYTQxZTQ2NTM0Y2Y0NGU2MzIiLAogICAic2lnIjogIjMwNDUwMjIxMDBmMzViMDdlOTM4ZDQ5NDljYWY4MmU2OWU4NmNjOWRiM2I2OWI2ZGJjNjc0MGMxZjM0M2QwNjg5M2Y5OTZmYmViMDIyMDAxZTg0N2Q4MTYyNTlhOTZhNDllNDI3NzlhMjM1MGRhYjk3YjcxYzhhZTdlMjZiMjM4MGM2ZmE3ZjU4MTMxYjMiCiAgfQogXSwKICJzaWduZWQiOiB7CiAgIl90eXBlIjogInJvb3QiLAogICJjb25zaXN0ZW50X3NuYXBzaG90IjogdHJ1ZSwKICAiZXhwaXJlcyI6ICIyMDI2LTExLTIwVDEzOjU4OjE4WiIsCiAgImtleXMiOiB7CiAgICIwYzg3NDMyYzNiZjA5ZmQ5OTE4OWZkYzMyZmE1ZWFlZGY0ZTRhNWZhYzdiYWI3M2ZhMDRhMmUwZmM2NGFmNmY1IjogewogICAgImtleWlkX2hhc2hfYWxnb3JpdGhtcyI6IFsKICAgICAic2hhMjU2IiwKICAgICAic2hhNTEyIgogICAgXSwKICAgICJrZXl0eXBlIjogImVjZHNhIiwKICAgICJrZXl2YWwiOiB7CiAgICAgInB1YmxpYyI6ICItLS0tLUJFR0lOIFBVQkxJQyBLRVktLS0tLVxuTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFV1JpR3I1K2orM0o1U3NIK1p0cjVuRTJIMndPN1xuQlYrbk8zczkzZ0xjYTE4cVRPekhZMW9XeUFHRHlrTVNzR1RVQlN0OUQrQW4wS2ZLc0QybWZTTTQyUT09XG4tLS0tLUVORCBQVUJMSUMgS0VZLS0tLS1cbiIKICAgIH0sCiAgICAic2NoZW1lIjogImVjZHNhLXNoYTItbmlzdHAyNTYiLAogICAgIngtdHVmLW9uLWNpLW9ubGluZS11cmkiOiAiZ2Nwa21zOnByb2plY3RzL3NpZ3N0b3JlLXJvb3Qtc2lnbmluZy9sb2NhdGlvbnMvZ2xvYmFsL2tleVJpbmdzL3Jvb3QvY3J5cHRvS2V5cy90aW1lc3RhbXAvY3J5cHRvS2V5VmVyc2lvbnMvMSIKICAgfSwKICAgIjE4M2U2NGYzNzY3MGRjMTNjYTBkMjg5OTVhMzA1M2YzNzQwOTU0ZGRjZTQ0MzIxYTQxZTQ2NTM0Y2Y0NGU2MzIiOiB7CiAgICAia2V5dHlwZSI6ICJlY2RzYSIsCiAgICAia2V5dmFsIjogewogICAgICJwdWJsaWMiOiAiLS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS1cbk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRU14cFBPSkNJWjVvdEc0MTA2ZkdKc2VFUWkzVjlcbnBrTVlRNHV5VjlUajFNN1dIWEl5TEcramtmdnVHMGdsUTFKWmJSWlpCVjNnQVI0c29qZEdISVNlb3c9PVxuLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tXG4iCiAgICB9LAogICAgInNjaGVtZSI6ICJlY2RzYS1zaGEyLW5pc3RwMjU2IiwKICAgICJ4LXR1Zi1vbi1jaS1rZXlvd25lciI6ICJAbGFuY2UiCiAgIH0sCiAgICIyMmY0Y2FlYzZkOGU2Zjk1NTVhZjY2YjNkNGMzY2IwNmEzYmIyM2ZkYzdlMzljOTE2YzYxZjQ2MmU2ZjUyYjA2IjogewogICAgImtleWlkX2hhc2hfYWxnb3JpdGhtcyI6IFsKICAgICAic2hhMjU2IiwKICAgICAic2hhNTEyIgogICAgXSwKICAgICJrZXl0eXBlIjogImVjZHNhIiwKICAgICJrZXl2YWwiOiB7CiAgICAgInB1YmxpYyI6ICItLS0tLUJFR0lOIFBVQkxJQyBLRVktLS0tLVxuTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFekJ6Vk9tSENQb2pNVkxTSTM2NFdpaVY4TlByRFxuNklnUnhWbGlza3ovdit5M0pFUjVtY1ZHY09ObGlEY1dNQzVKMmxmSG1qUE5QaGI0SDd4bThMemZTQT09XG4tLS0tLUVORCBQVUJMSUMgS0VZLS0tLS1cbiIKICAgIH0sCiAgICAic2NoZW1lIjogImVjZHNhLXNoYTItbmlzdHAyNTYiLAogICAgIngtdHVmLW9uLWNpLWtleW93bmVyIjogIkBzYW50aWFnb3RvcnJlcyIKICAgfSwKICAgIjYxNjQzODM4MTI1YjQ0MGI0MGRiNjk0MmY1Y2I1YTMxYzBkYzA0MzY4MzE2ZWIyYWFhNThiOTU5MDRhNTgyMjIiOiB7CiAgICAia2V5aWRfaGFzaF9hbGdvcml0aG1zIjogWwogICAgICJzaGEyNTYiLAogICAgICJzaGE1MTIiCiAgICBdLAogICAgImtleXR5cGUiOiAiZWNkc2EiLAogICAgImtleXZhbCI6IHsKICAgICAicHVibGljIjogIi0tLS0tQkVHSU4gUFVCTElDIEtFWS0tLS0tXG5NRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVpbmlrU3NBUW1Za05lSDVlWXEvQ25JekxhYWNPXG54bFNhYXdRRE93cUt5L3RDcXhxNXh4UFNKYzIxSzRXSWhzOUd5T2tLZnp1ZVkzR0lMemNNSlo0Y1d3PT1cbi0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLVxuIgogICAgfSwKICAgICJzY2hlbWUiOiAiZWNkc2Etc2hhMi1uaXN0cDI1NiIsCiAgICAieC10dWYtb24tY2kta2V5b3duZXIiOiAiQGJvYmNhbGxhd2F5IgogICB9LAogICAiYTY4N2U1YmY0ZmFiODJiMGVlNThkNDZlMDVjOTUzNTE0NWEyYzlhZmI0NThmNDNkNDJiNDVjYTBmZGNlMmE3MCI6IHsKICAgICJrZXlpZF9oYXNoX2FsZ29yaXRobXMiOiBbCiAgICAgInNoYTI1NiIsCiAgICAgInNoYTUxMiIKICAgIF0sCiAgICAia2V5dHlwZSI6ICJlY2RzYSIsCiAgICAia2V5dmFsIjogewogICAgICJwdWJsaWMiOiAiLS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS1cbk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRTBnaHJoOTJMdzFZcjNpZEdWNVdxQ3RNREI4Q3hcbitEOGhkQzR3MlpMTklwbFZSb1ZHTHNrWWEzZ2hlTXlPamlKOGtQaTE1YVEyLy83UCtvajdVdkpQR3c9PVxuLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tXG4iCiAgICB9LAogICAgInNjaGVtZSI6ICJlY2RzYS1zaGEyLW5pc3RwMjU2IiwKICAgICJ4LXR1Zi1vbi1jaS1rZXlvd25lciI6ICJAam9zaHVhZ2wiCiAgIH0sCiAgICJlNzFhNTRkNTQzODM1YmE4NmFkYWQ5NDYwMzc5Yzc2NDFmYjg3MjZkMTY0ZWE3NjY4MDFhMWM1MjJhYmE3ZWEyIjogewogICAgImtleWlkX2hhc2hfYWxnb3JpdGhtcyI6IFsKICAgICAic2hhMjU2IiwKICAgICAic2hhNTEyIgogICAgXSwKICAgICJrZXl0eXBlIjogImVjZHNhIiwKICAgICJrZXl2YWwiOiB7CiAgICAgInB1YmxpYyI6ICItLS0tLUJFR0lOIFBVQkxJQyBLRVktLS0tLVxuTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFRVhzejNTWlhGYjhqTVY0Mmo2cEpseWpialI4S1xuTjNCd29jZXhxNkxNSWI1cXNXS09RdkxOMTZOVWVmTGM0SHN3T291bVJzVlZhYWpTcFFTNmZvYmtSdz09XG4tLS0tLUVORCBQVUJMSUMgS0VZLS0tLS1cbiIKICAgIH0sCiAgICAic2NoZW1lIjogImVjZHNhLXNoYTItbmlzdHAyNTYiLAogICAgIngtdHVmLW9uLWNpLWtleW93bmVyIjogIkBtbm02NzgiCiAgIH0KICB9LAogICJyb2xlcyI6IHsKICAgInJvb3QiOiB7CiAgICAia2V5aWRzIjogWwogICAgICJlNzFhNTRkNTQzODM1YmE4NmFkYWQ5NDYwMzc5Yzc2NDFmYjg3MjZkMTY0ZWE3NjY4MDFhMWM1MjJhYmE3ZWEyIiwKICAgICAiMjJmNGNhZWM2ZDhlNmY5NTU1YWY2NmIzZDRjM2NiMDZhM2JiMjNmZGM3ZTM5YzkxNmM2MWY0NjJlNmY1MmIwNiIsCiAgICAgIjYxNjQzODM4MTI1YjQ0MGI0MGRiNjk0MmY1Y2I1YTMxYzBkYzA0MzY4MzE2ZWIyYWFhNThiOTU5MDRhNTgyMjIiLAogICAgICJhNjg3ZTViZjRmYWI4MmIwZWU1OGQ0NmUwNWM5NTM1MTQ1YTJjOWFmYjQ1OGY0M2Q0MmI0NWNhMGZkY2UyYTcwIiwKICAgICAiMTgzZTY0ZjM3NjcwZGMxM2NhMGQyODk5NWEzMDUzZjM3NDA5NTRkZGNlNDQzMjFhNDFlNDY1MzRjZjQ0ZTYzMiIKICAgIF0sCiAgICAidGhyZXNob2xkIjogMwogICB9LAogICAic25hcHNob3QiOiB7CiAgICAia2V5aWRzIjogWwogICAgICIwYzg3NDMyYzNiZjA5ZmQ5OTE4OWZkYzMyZmE1ZWFlZGY0ZTRhNWZhYzdiYWI3M2ZhMDRhMmUwZmM2NGFmNmY1IgogICAgXSwKICAgICJ0aHJlc2hvbGQiOiAxLAogICAgIngtdHVmLW9uLWNpLWV4cGlyeS1wZXJpb2QiOiAzNjUwLAogICAgIngtdHVmLW9uLWNpLXNpZ25pbmctcGVyaW9kIjogMzY1CiAgIH0sCiAgICJ0YXJnZXRzIjogewogICAgImtleWlkcyI6IFsKICAgICAiZTcxYTU0ZDU0MzgzNWJhODZhZGFkOTQ2MDM3OWM3NjQxZmI4NzI2ZDE2NGVhNzY2ODAxYTFjNTIyYWJhN2VhMiIsCiAgICAgIjIyZjRjYWVjNmQ4ZTZmOTU1NWFmNjZiM2Q0YzNjYjA2YTNiYjIzZmRjN2UzOWM5MTZjNjFmNDYyZTZmNTJiMDYiLAogICAgICI2MTY0MzgzODEyNWI0NDBiNDBkYjY5NDJmNWNiNWEzMWMwZGMwNDM2ODMxNmViMmFhYTU4Yjk1OTA0YTU4MjIyIiwKICAgICAiYTY4N2U1YmY0ZmFiODJiMGVlNThkNDZlMDVjOTUzNTE0NWEyYzlhZmI0NThmNDNkNDJiNDVjYTBmZGNlMmE3MCIsCiAgICAgIjE4M2U2NGYzNzY3MGRjMTNjYTBkMjg5OTVhMzA1M2YzNzQwOTU0ZGRjZTQ0MzIxYTQxZTQ2NTM0Y2Y0NGU2MzIiCiAgICBdLAogICAgInRocmVzaG9sZCI6IDMKICAgfSwKICAgInRpbWVzdGFtcCI6IHsKICAgICJrZXlpZHMiOiBbCiAgICAgIjBjODc0MzJjM2JmMDlmZDk5MTg5ZmRjMzJmYTVlYWVkZjRlNGE1ZmFjN2JhYjczZmEwNGEyZTBmYzY0YWY2ZjUiCiAgICBdLAogICAgInRocmVzaG9sZCI6IDEsCiAgICAieC10dWYtb24tY2ktZXhwaXJ5LXBlcmlvZCI6IDcsCiAgICAieC10dWYtb24tY2ktc2lnbmluZy1wZXJpb2QiOiA2CiAgIH0KICB9LAogICJzcGVjX3ZlcnNpb24iOiAiMS4wIiwKICAidmVyc2lvbiI6IDE1LAogICJ4LXR1Zi1vbi1jaS1leHBpcnktcGVyaW9kIjogMTk3LAogICJ4LXR1Zi1vbi1jaS1zaWduaW5nLXBlcmlvZCI6IDQ2CiB9Cn0=","targets":{"trusted_root.json":"ewogICJtZWRpYVR5cGUiOiAiYXBwbGljYXRpb24vdm5kLmRldi5zaWdzdG9yZS50cnVzdGVkcm9vdCtqc29uO3ZlcnNpb249MC4xIiwKICAidGxvZ3MiOiBbCiAgICB7CiAgICAgICJiYXNlVXJsIjogImh0dHBzOi8vcmVrb3Iuc2lnc3RvcmUuZGV2IiwKICAgICAgImhhc2hBbGdvcml0aG0iOiAiU0hBMl8yNTYiLAogICAgICAicHVibGljS2V5IjogewogICAgICAgICJyYXdCeXRlcyI6ICJNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUUyRzJZKzJ0YWJkVFY1QmNHaUJJeDBhOWZBRndya0JibUxTR3RrczRMM3FYNnlZWTB6dWZCbmhDOFVyL2l5NTVHaFdQLzlBL2JZMkxoQzMwTTkrUll0dz09IiwKICAgICAgICAia2V5RGV0YWlscyI6ICJQS0lYX0VDRFNBX1AyNTZfU0hBXzI1NiIsCiAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgInN0YXJ0IjogIjIwMjEtMDEtMTJUMTE6NTM6MjdaIgogICAgICAgIH0KICAgICAgfSwKICAgICAgImxvZ0lkIjogewogICAgICAgICJrZXlJZCI6ICJ3Tkk5YXRRR2x6K1ZXZk82TFJ5Z0g0UVVmWS84VzRSRndpVDVpNVdSZ0IwPSIKICAgICAgfQogICAgfSwKICAgIHsKICAgICAgImJhc2VVcmwiOiAiaHR0cHM6Ly9sb2cyMDI1LTEucmVrb3Iuc2lnc3RvcmUuZGV2IiwKICAgICAgImhhc2hBbGdvcml0aG0iOiAiU0hBMl8yNTYiLAogICAgICAicHVibGljS2V5IjogewogICAgICAgICJyYXdCeXRlcyI6ICJNQ293QlFZREsyVndBeUVBdDhybHAxa25Hd2pmYmNYQVlQWUFrbjBYaUx6MXg4TzR0MFlrRWhpZTI0ND0iLAogICAgICAgICJrZXlEZXRhaWxzIjogIlBLSVhfRUQyNTUxOSIsCiAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgInN0YXJ0IjogIjIwMjUtMDktMjNUMDA6MDA6MDBaIgogICAgICAgIH0KICAgICAgfSwKICAgICAgImxvZ0lkIjogewogICAgICAgICJrZXlJZCI6ICJ6eEdaRlZ2ZDBGRW1qUjhXckZ3TWRjQUo5dnRhWS9RWGY0NFkxd1VlUDZBPSIKICAgICAgfQogICAgfQogIF0sCiAgImNlcnRpZmljYXRlQXV0aG9yaXRpZXMiOiBbCiAgICB7CiAgICAgICJzdWJqZWN0IjogewogICAgICAgICJvcmdhbml6YXRpb24iOiAic2lnc3RvcmUuZGV2IiwKICAgICAgICAiY29tbW9uTmFtZSI6ICJzaWdzdG9yZSIKICAgICAgfSwKICAgICAgInVyaSI6ICJodHRwczovL2Z1bGNpby5zaWdzdG9yZS5kZXYiLAogICAgICAiY2VydENoYWluIjogewogICAgICAgICJjZXJ0aWZpY2F0ZXMiOiBbCiAgICAgICAgICB7CiAgICAgICAgICAgICJyYXdCeXRlcyI6ICJNSUlCK0RDQ0FYNmdBd0lCQWdJVE5Wa0Rab0Npb2ZQRHN5N2RmbTZnZUxidWh6QUtCZ2dxaGtqT1BRUURBekFxTVJVd0V3WURWUVFLRXd4emFXZHpkRzl5WlM1a1pYWXhFVEFQQmdOVkJBTVRDSE5wWjNOMGIzSmxNQjRYRFRJeE1ETXdOekF6TWpBeU9Wb1hEVE14TURJeU16QXpNakF5T1Zvd0tqRVZNQk1HQTFVRUNoTU1jMmxuYzNSdmNtVXVaR1YyTVJFd0R3WURWUVFERXdoemFXZHpkRzl5WlRCMk1CQUdCeXFHU000OUFnRUdCU3VCQkFBaUEySUFCTFN5QTdJaTVrK3BOTzhaRVdZMHlsZW1XRG93T2tOYTNrTCtHWkU1WjVHV2VoTDkvQTliUk5BM1JicnNaNWkwSmNhc3RhUkw3U3A1ZnAvakQ1ZHhxYy9VZFRWbmx2UzE2YW4rMllmc3dlL1F1TG9sUlVDcmNPRTIrMmlBNSt0emQ2Tm1NR1F3RGdZRFZSMFBBUUgvQkFRREFnRUdNQklHQTFVZEV3RUIvd1FJTUFZQkFmOENBUUV3SFFZRFZSME9CQllFRk1qRkhRQkJtaVFwTWxFazZ3MnVTdTFLQnRQc01COEdBMVVkSXdRWU1CYUFGTWpGSFFCQm1pUXBNbEVrNncydVN1MUtCdFBzTUFvR0NDcUdTTTQ5QkFNREEyZ0FNR1VDTUg4bGlXSmZNdWk2dlhYQmhqRGdZNE13c2xtTi9USnhWZS84M1dyRm9td21OZjA1NnkxWDQ4RjljNG0zYTNvelhBSXhBS2pSYXk1L2FqL2pzS0tHSWttUWF0akk4dXVwSHIvK0N4RnZhSldtcFlxTmtMREdSVSs5b3J6aDVoSTJScmN1YVE9PSIKICAgICAgICAgIH0KICAgICAgICBdCiAgICAgIH0sCiAgICAgICJ2YWxpZEZvciI6IHsKICAgICAgICAic3RhcnQiOiAiMjAyMS0wMy0wN1QwMzoyMDoyOVoiLAogICAgICAgICJlbmQiOiAiMjAyMi0xMi0zMVQyMzo1OTo1OS45OTlaIgogICAgICB9CiAgICB9LAogICAgewogICAgICAic3ViamVjdCI6IHsKICAgICAgICAib3JnYW5pemF0aW9uIjogInNpZ3N0b3JlLmRldiIsCiAgICAgICAgImNvbW1vbk5hbWUiOiAic2lnc3RvcmUiCiAgICAgIH0sCiAgICAgICJ1cmkiOiAiaHR0cHM6Ly9mdWxjaW8uc2lnc3RvcmUuZGV2IiwKICAgICAgImNlcnRDaGFpbiI6IHsKICAgICAgICAiY2VydGlmaWNhdGVzIjogWwogICAgICAgICAgewogICAgICAgICAgICAicmF3Qnl0ZXMiOiAiTUlJQ0dqQ0NBYUdnQXdJQkFnSVVBTG5WaVZmblUwYnJKYXNtUmtIcm4vVW5mYVF3Q2dZSUtvWkl6ajBFQXdNd0tqRVZNQk1HQTFVRUNoTU1jMmxuYzNSdmNtVXVaR1YyTVJFd0R3WURWUVFERXdoemFXZHpkRzl5WlRBZUZ3MHlNakEwTVRNeU1EQTJNVFZhRncwek1URXdNRFV4TXpVMk5UaGFNRGN4RlRBVEJnTlZCQW9UREhOcFozTjBiM0psTG1SbGRqRWVNQndHQTFVRUF4TVZjMmxuYzNSdmNtVXRhVzUwWlhKdFpXUnBZWFJsTUhZd0VBWUhLb1pJemowQ0FRWUZLNEVFQUNJRFlnQUU4UlZTL3lzSCtOT3Z1RFp5UEladGlsZ1VGOU5sYXJZcEFkOUhQMXZCQkgxVTVDVjc3TFNTN3MwWmlING5FN0h2N3B0UzZMdnZSL1NUazc5OExWZ016TGxKNEhlSWZGM3RIU2FleExjWXBTQVNyMWtTME4vUmdCSnovOWpXQ2lYbm8zc3dlVEFPQmdOVkhROEJBZjhFQkFNQ0FRWXdFd1lEVlIwbEJBd3dDZ1lJS3dZQkJRVUhBd013RWdZRFZSMFRBUUgvQkFnd0JnRUIvd0lCQURBZEJnTlZIUTRFRmdRVTM5UHB6MVlrRVpiNXFOanBLRldpeGk0WVpEOHdId1lEVlIwakJCZ3dGb0FVV01BZVg1RkZwV2FwZXN5UW9aTWkwQ3JGeGZvd0NnWUlLb1pJemowRUF3TURad0F3WkFJd1BDc1FLNERZaVpZRFBJYURpNUhGS25meFh4NkFTU1ZtRVJmc3luWUJpWDJYNlNKUm5aVTg0LzlEWmRuRnZ2eG1BakJPdDZRcEJsYzRKLzBEeHZrVENxcGNsdnppTDZCQ0NQbmpkbElCM1B1M0J4c1BteWdVWTdJaTJ6YmRDZGxpaW93PSIKICAgICAgICAgIH0sCiAgICAgICAgICB7CiAgICAgICAgICAgICJyYXdCeXRlcyI6ICJNSUlCOXpDQ0FYeWdBd0lCQWdJVUFMWk5BUEZkeEhQd2plRGxvRHd5WUNoQU8vNHdDZ1lJS29aSXpqMEVBd013S2pFVk1CTUdBMVVFQ2hNTWMybG5jM1J2Y21VdVpHVjJNUkV3RHdZRFZRUURFd2h6YVdkemRHOXlaVEFlRncweU1URXdNRGN4TXpVMk5UbGFGdzB6TVRFd01EVXhNelUyTlRoYU1Db3hGVEFUQmdOVkJBb1RESE5wWjNOMGIzSmxMbVJsZGpFUk1BOEdBMVVFQXhNSWMybG5jM1J2Y21Vd2RqQVFCZ2NxaGtqT1BRSUJCZ1VyZ1FRQUlnTmlBQVQ3WGVGVDRyYjNQUUd3UzRJYWp0TGszL09sbnBnYW5nYUJjbFlwc1lCcjVpKzR5bkIwN2NlYjNMUDBPSU9aZHhleFg2OWM1aVZ1eUpSUStIejA1eWkrVUYzdUJXQWxIcGlTNXNoMCtIMkdIRTdTWHJrMUVDNW0xVHIxOUw5Z2c5MmpZekJoTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlJZd0I1ZmtVV2xacWw2ekpDaGt5TFFLc1hGK2pBZkJnTlZIU01FR0RBV2dCUll3QjVma1VXbFpxbDZ6SkNoa3lMUUtzWEYrakFLQmdncWhrak9QUVFEQXdOcEFEQm1BakVBajFuSGVYWnArMTNOV0JOYStFRHNEUDhHMVdXZzF0Q01XUC9XSFBxcGFWbzBqaHN3ZU5GWmdTczBlRTd3WUk0cUFqRUEyV0I5b3Q5OHNJa29GM3ZaWWRkMy9WdFdCNWI5VE5NZWE3SXgvc3RKNVRmY0xMZUFCTEU0Qk5KT3NRNHZuQkhKIgogICAgICAgICAgfQogICAgICAgIF0KICAgICAgfSwKICAgICAgInZhbGlkRm9yIjogewogICAgICAgICJzdGFydCI6ICIyMDIyLTA0LTEzVDIwOjA2OjE1WiIKICAgICAgfQogICAgfQogIF0sCiAgImN0bG9ncyI6IFsKICAgIHsKICAgICAgImJhc2VVcmwiOiAiaHR0cHM6Ly9jdGZlLnNpZ3N0b3JlLmRldi90ZXN0IiwKICAgICAgImhhc2hBbGdvcml0aG0iOiAiU0hBMl8yNTYiLAogICAgICAicHVibGljS2V5IjogewogICAgICAgICJyYXdCeXRlcyI6ICJNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUViZndSK1JKdWRYc2NnUkJScEtYMVhGRHkzUHl1ZER4ei9TZm5SaTFmVDhla3BmQmQyTzF1b3o3anIzWjhuS3p4QTY5RVVRK2VGQ0ZJM3pldWJQV1U3dz09IiwKICAgICAgICAia2V5RGV0YWlscyI6ICJQS0lYX0VDRFNBX1AyNTZfU0hBXzI1NiIsCiAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgInN0YXJ0IjogIjIwMjEtMDMtMTRUMDA6MDA6MDBaIiwKICAgICAgICAgICJlbmQiOiAiMjAyMi0xMC0zMVQyMzo1OTo1OS45OTlaIgogICAgICAgIH0KICAgICAgfSwKICAgICAgImxvZ0lkIjogewogICAgICAgICJrZXlJZCI6ICJDR0NTOENoUy8yaEYwZEZySjRTY1JXY1lyQlk5d3pqU2JlYThJZ1kyYjNJPSIKICAgICAgfQogICAgfSwKICAgIHsKICAgICAgImJhc2VVcmwiOiAiaHR0cHM6Ly9jdGZlLnNpZ3N0b3JlLmRldi8yMDIyIiwKICAgICAgImhhc2hBbGdvcml0aG0iOiAiU0hBMl8yNTYiLAogICAgICAicHVibGljS2V5IjogewogICAgICAgICJyYXdCeXRlcyI6ICJNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVpUFNsRmkwQ21GVGZFakNVcUY5SHVDRWNZWE5LQWFZYWxJSm1CWjh5eWV6UGpUcWh4cktCcE1uYW9jVnRMSkJJMWVNM3VYblF6UUdBSmRKNGdzOUZ5dz09IiwKICAgICAgICAia2V5RGV0YWlscyI6ICJQS0lYX0VDRFNBX1AyNTZfU0hBXzI1NiIsCiAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgInN0YXJ0IjogIjIwMjItMTAtMjBUMDA6MDA6MDBaIgogICAgICAgIH0KICAgICAgfSwKICAgICAgImxvZ0lkIjogewogICAgICAgICJrZXlJZCI6ICIzVDB3YXNiSEVUSmpHUjRjbVdjM0FxSktYcmplUEszL2g0cHlnQzhwN280PSIKICAgICAgfQogICAgfQogIF0sCiAgInRpbWVzdGFtcEF1dGhvcml0aWVzIjogWwogICAgewogICAgICAic3ViamVjdCI6IHsKICAgICAgICAib3JnYW5pemF0aW9uIjogInNpZ3N0b3JlLmRldiIsCiAgICAgICAgImNvbW1vbk5hbWUiOiAic2lnc3RvcmUtdHNhLXNlbGZzaWduZWQiCiAgICAgIH0sCiAgICAgICJ1cmkiOiAiaHR0cHM6Ly90aW1lc3RhbXAuc2lnc3RvcmUuZGV2L2FwaS92MS90aW1lc3RhbXAiLAogICAgICAiY2VydENoYWluIjogewogICAgICAgICJjZXJ0aWZpY2F0ZXMiOiBbCiAgICAgICAgICB7CiAgICAgICAgICAgICJyYXdCeXRlcyI6ICJNSUlDRURDQ0FaYWdBd0lCQWdJVU9oTlVMd3lRWWU2OHdVTXZ5NHFPaXlvaml3d3dDZ1lJS29aSXpqMEVBd013T1RFVk1CTUdBMVVFQ2hNTWMybG5jM1J2Y21VdVpHVjJNU0F3SGdZRFZRUURFeGR6YVdkemRHOXlaUzEwYzJFdGMyVnNabk5wWjI1bFpEQWVGdzB5TlRBME1EZ3dOalU1TkROYUZ3MHpOVEEwTURZd05qVTVORE5hTUM0eEZUQVRCZ05WQkFvVERITnBaM04wYjNKbExtUmxkakVWTUJNR0ExVUVBeE1NYzJsbmMzUnZjbVV0ZEhOaE1IWXdFQVlIS29aSXpqMENBUVlGSzRFRUFDSURZZ0FFNHJhMlo4aEtOaWcyVDlrRmpDQVRvR0czMGpreStXUXYzQnpMK21LdmgxU0tOUi9Vd3V3c2ZOQ2c0c3J5b1lBZDhFNmlzb3ZWQTNNNGFvTmRtOVFEaTUwWjhuVEV5dnFnZkRQdFRJd1hJdGZpVy9BRmYxVjd1d2tia0FvajB4eGNvMm93YURBT0JnTlZIUThCQWY4RUJBTUNCNEF3SFFZRFZSME9CQllFRkluOWVVT0h6OUJsUnNNQ1JzY3NjMXQ5dE9zRE1COEdBMVVkSXdRWU1CYUFGSmpzQWU5L3UxSC8xSlVlYjRxSW1GTUhpYzYvTUJZR0ExVWRKUUVCL3dRTU1Bb0dDQ3NHQVFVRkJ3TUlNQW9HQ0NxR1NNNDlCQU1EQTJnQU1HVUNNRHRwc1YvNkthTzBxeUYvVU1zWDJhU1VYS1FGZG9HVHB0UUdjMGZ0cTFjc3VsSFBHRzZkc215TU5kM0pCK0czRVFJeEFPYWp2QmNqcEptS2I0TnYrMlRhb2o4VWM1K2I2aWg2RlhDQ0tyYVNxdXBlMDd6cXN3TWNYSlRlMWNFeHZIdnZsdz09IgogICAgICAgICAgfSwKICAgICAgICAgIHsKICAgICAgICAgICAgInJhd0J5dGVzIjogIk1JSUI5ekNDQVh5Z0F3SUJBZ0lVVjdmMEdMRE9vRXpJaDhMWFNXODBPSmlVcDE0d0NnWUlLb1pJemowRUF3TXdPVEVWTUJNR0ExVUVDaE1NYzJsbmMzUnZjbVV1WkdWMk1TQXdIZ1lEVlFRREV4ZHphV2R6ZEc5eVpTMTBjMkV0YzJWc1puTnBaMjVsWkRBZUZ3MHlOVEEwTURnd05qVTVORE5hRncwek5UQTBNRFl3TmpVNU5ETmFNRGt4RlRBVEJnTlZCQW9UREhOcFozTjBiM0psTG1SbGRqRWdNQjRHQTFVRUF4TVhjMmxuYzNSdmNtVXRkSE5oTFhObGJHWnphV2R1WldRd2RqQVFCZ2NxaGtqT1BRSUJCZ1VyZ1FRQUlnTmlBQVFVUU50ZlJUL291M1lBVGE2d0Iva0tUZTcwY2ZKd3lSSUJvdk1udDhSY0pwaC9DT0U4MnV5UzZGbXBwTExMMVZCUEdjUGZwUVBZSk5Yeld3aThpY3doS1E2Vy9RZTJoM29lYkJiMkZIcHdOSkRxbytUTWFDL3RkZmt2L0VsSkI3MmpSVEJETUE0R0ExVWREd0VCL3dRRUF3SUJCakFTQmdOVkhSTUJBZjhFQ0RBR0FRSC9BZ0VBTUIwR0ExVWREZ1FXQkJTWTdBSHZmN3RSLzlTVkhtK0tpSmhUQjRuT3Z6QUtCZ2dxaGtqT1BRUURBd05wQURCbUFqRUF3R0VHcmZHWlIxY2VuMVI4L0RUVk1JOTQzTHNzWm1KUnREcC9pN1NmR0htR1JQNmdSYnVqOXZPSzNiNjdaMFFRQWpFQXVUMkg2NzNMUUVhSFRjeVFTWnJrcDRtWDdXd2ttRitzVmJrWVk1bVhOK1JNSDEzS1VFSEhPcUFTYWVtWVdLL0UiCiAgICAgICAgICB9CiAgICAgICAgXQogICAgICB9LAogICAgICAidmFsaWRGb3IiOiB7CiAgICAgICAgInN0YXJ0IjogIjIwMjUtMDctMDRUMDA6MDA6MDBaIgogICAgICB9CiAgICB9CiAgXQp9Cg==","registry.npmjs.org%2Fkeys.json":"ewogICAgImtleXMiOiBbCiAgICAgICAgewogICAgICAgICAgICAia2V5SWQiOiAiU0hBMjU2OmpsM2J3c3d1ODBQampva0NnaDBvMnc1YzJVNExoUUFFNTdnajljejFrekEiLAogICAgICAgICAgICAia2V5VXNhZ2UiOiAibnBtOnNpZ25hdHVyZXMiLAogICAgICAgICAgICAicHVibGljS2V5IjogewogICAgICAgICAgICAgICAgInJhd0J5dGVzIjogIk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRTFPbGIzek1BRkZ4WEtIaUlrUU81Y0ozWWhsNWk2VVBwK0lodXRlQkpidUhjQTVVb2dLbzBFV3RsV3dXNktTYUtvVE5FWUw3SmxDUWlWbmtoQmt0VWdnPT0iLAogICAgICAgICAgICAgICAgImtleURldGFpbHMiOiAiUEtJWF9FQ0RTQV9QMjU2X1NIQV8yNTYiLAogICAgICAgICAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgICAgICAgICAgICJzdGFydCI6ICIxOTk5LTAxLTAxVDAwOjAwOjAwLjAwMFoiLAogICAgICAgICAgICAgICAgICAgICJlbmQiOiAiMjAyNS0wMS0yOVQwMDowMDowMC4wMDBaIgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICB7CiAgICAgICAgICAgICJrZXlJZCI6ICJTSEEyNTY6amwzYndzd3U4MFBqam9rQ2doMG8ydzVjMlU0TGhRQUU1N2dqOWN6MWt6QSIsCiAgICAgICAgICAgICJrZXlVc2FnZSI6ICJucG06YXR0ZXN0YXRpb25zIiwKICAgICAgICAgICAgInB1YmxpY0tleSI6IHsKICAgICAgICAgICAgICAgICJyYXdCeXRlcyI6ICJNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUUxT2xiM3pNQUZGeFhLSGlJa1FPNWNKM1lobDVpNlVQcCtJaHV0ZUJKYnVIY0E1VW9nS28wRVd0bFd3VzZLU2FLb1RORVlMN0psQ1FpVm5raEJrdFVnZz09IiwKICAgICAgICAgICAgICAgICJrZXlEZXRhaWxzIjogIlBLSVhfRUNEU0FfUDI1Nl9TSEFfMjU2IiwKICAgICAgICAgICAgICAgICJ2YWxpZEZvciI6IHsKICAgICAgICAgICAgICAgICAgICAic3RhcnQiOiAiMjAyMi0xMi0wMVQwMDowMDowMC4wMDBaIiwKICAgICAgICAgICAgICAgICAgICAiZW5kIjogIjIwMjUtMDEtMjlUMDA6MDA6MDAuMDAwWiIKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgewogICAgICAgICAgICAia2V5SWQiOiAiU0hBMjU2OkRoUTh3UjVBUEJ2RkhMRi8rVGMrQVl2UE9kVHBjSURxT2h4c0JIUndDN1UiLAogICAgICAgICAgICAia2V5VXNhZ2UiOiAibnBtOnNpZ25hdHVyZXMiLAogICAgICAgICAgICAicHVibGljS2V5IjogewogICAgICAgICAgICAgICAgInJhd0J5dGVzIjogIk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRVk2WWE3VysrN2FVUHp2TVRyZXpINlljeDNjK0hPS1lDY05HeWJKWlNDSnEvZmQ3UWE4dXVBS3RkSWtVUXRRaUVLRVJoQW1FNWxNTUpoUDhPa0RPYTJnPT0iLAogICAgICAgICAgICAgICAgImtleURldGFpbHMiOiAiUEtJWF9FQ0RTQV9QMjU2X1NIQV8yNTYiLAogICAgICAgICAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgICAgICAgICAgICJzdGFydCI6ICIyMDI1LTAxLTEzVDAwOjAwOjAwLjAwMFoiCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIHsKICAgICAgICAgICAgImtleUlkIjogIlNIQTI1NjpEaFE4d1I1QVBCdkZITEYvK1RjK0FZdlBPZFRwY0lEcU9oeHNCSFJ3QzdVIiwKICAgICAgICAgICAgImtleVVzYWdlIjogIm5wbTphdHRlc3RhdGlvbnMiLAogICAgICAgICAgICAicHVibGljS2V5IjogewogICAgICAgICAgICAgICAgInJhd0J5dGVzIjogIk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRVk2WWE3VysrN2FVUHp2TVRyZXpINlljeDNjK0hPS1lDY05HeWJKWlNDSnEvZmQ3UWE4dXVBS3RkSWtVUXRRaUVLRVJoQW1FNWxNTUpoUDhPa0RPYTJnPT0iLAogICAgICAgICAgICAgICAgImtleURldGFpbHMiOiAiUEtJWF9FQ0RTQV9QMjU2X1NIQV8yNTYiLAogICAgICAgICAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgICAgICAgICAgICJzdGFydCI6ICIyMDI1LTAxLTEzVDAwOjAwOjAwLjAwMFoiCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICBdCn0K"}}}
diff --git a/deps/npm/node_modules/@sigstore/verify/dist/bundle/dsse.js b/deps/npm/node_modules/@sigstore/verify/dist/bundle/dsse.js
index 7ee255401b1..dcfcd95e494 100644
--- a/deps/npm/node_modules/@sigstore/verify/dist/bundle/dsse.js
+++ b/deps/npm/node_modules/@sigstore/verify/dist/bundle/dsse.js
@@ -25,6 +25,12 @@ class DSSESignatureContent {
compareDigest(digest) {
return core_1.crypto.bufferEqual(digest, core_1.crypto.digest('sha256', this.env.payload));
}
+ // For a DSSE envelope the signature is computed over the pre-authentication
+ // encoding (PAE), so the digest of the signed bytes is the digest of the PAE.
+ // This is what a Rekor v2 hashedrekord entry records for a DSSE envelope.
+ compareSignedDigest(digest) {
+ return core_1.crypto.bufferEqual(digest, core_1.crypto.digest('sha256', this.preAuthEncoding));
+ }
compareSignature(signature) {
return core_1.crypto.bufferEqual(signature, this.signature);
}
diff --git a/deps/npm/node_modules/@sigstore/verify/dist/bundle/message.js b/deps/npm/node_modules/@sigstore/verify/dist/bundle/message.js
index 13cb5c27a02..b9048399fb9 100644
--- a/deps/npm/node_modules/@sigstore/verify/dist/bundle/message.js
+++ b/deps/npm/node_modules/@sigstore/verify/dist/bundle/message.js
@@ -47,6 +47,11 @@ class MessageSignatureContent {
compareDigest(digest) {
return core_1.crypto.bufferEqual(digest, this.messageDigest);
}
+ // For a message signature the signature is computed over the artifact, so the
+ // digest of the signed bytes is the artifact's message digest.
+ compareSignedDigest(digest) {
+ return this.compareDigest(digest);
+ }
verifySignature(key) {
return core_1.crypto.verify(this.artifact, key, this.signature, this.hashAlgorithm);
}
diff --git a/deps/npm/node_modules/@sigstore/verify/dist/policy.js b/deps/npm/node_modules/@sigstore/verify/dist/policy.js
index b08d083a296..a50d013ab47 100644
--- a/deps/npm/node_modules/@sigstore/verify/dist/policy.js
+++ b/deps/npm/node_modules/@sigstore/verify/dist/policy.js
@@ -32,7 +32,6 @@ function verifyOIDs(policyOIDs, signerOIDs = []) {
const match = signerOIDs.find((signerOID) => oidEquals(policyOID.oid?.id, signerOID.oid?.id) &&
policyOID.value.equals(signerOID.value));
if (!match) {
- /* istanbul ignore next */
const oid = policyOID.oid?.id.join('.') ?? '<unknown>';
throw new error_1.PolicyError({
code: 'UNTRUSTED_SIGNER_ERROR',
@@ -42,7 +41,6 @@ function verifyOIDs(policyOIDs, signerOIDs = []) {
}
}
function oidEquals(a, b) {
- /* istanbul ignore if */
if (a === undefined || b === undefined) {
return false;
}
diff --git a/deps/npm/node_modules/@sigstore/verify/dist/tlog/hashedrekord.js b/deps/npm/node_modules/@sigstore/verify/dist/tlog/hashedrekord.js
index 97dfcc9edc3..be34ca66954 100644
--- a/deps/npm/node_modules/@sigstore/verify/dist/tlog/hashedrekord.js
+++ b/deps/npm/node_modules/@sigstore/verify/dist/tlog/hashedrekord.js
@@ -63,9 +63,9 @@ function verifyHashedrekord001TLogBody(tlogEntry, content) {
message: 'signature mismatch',
});
}
- // Ensure that the bundle's message digest matches the tlog entry
+ // Ensure that the bundle's signed digest matches the tlog entry
const tlogDigest = tlogEntry.spec.data.hash?.value || '';
- if (!content.compareDigest(Buffer.from(tlogDigest, 'hex'))) {
+ if (!content.compareSignedDigest(Buffer.from(tlogDigest, 'hex'))) {
throw new error_1.VerificationError({
code: 'TLOG_BODY_ERROR',
message: 'digest mismatch',
@@ -83,9 +83,9 @@ function verifyHashedrekord002TLogBody(spec, content) {
message: 'signature mismatch',
});
}
- // Ensure that the bundle's message digest matches the tlog entry
+ // Ensure that the bundle's signed digest matches the tlog entry
const tlogHash = spec.data?.digest || Buffer.from('');
- if (!content.compareDigest(tlogHash)) {
+ if (!content.compareSignedDigest(tlogHash)) {
throw new error_1.VerificationError({
code: 'TLOG_BODY_ERROR',
message: 'digest mismatch',
diff --git a/deps/npm/node_modules/@sigstore/verify/dist/verifier.js b/deps/npm/node_modules/@sigstore/verify/dist/verifier.js
index eeba4128fab..06b16ac0ca8 100644
--- a/deps/npm/node_modules/@sigstore/verify/dist/verifier.js
+++ b/deps/npm/node_modules/@sigstore/verify/dist/verifier.js
@@ -54,7 +54,6 @@ class Verifier {
break;
case 'transparency-log': {
const result = (0, timestamp_1.getTLogTimestamp)(timestamp.tlogEntry);
- /* istanbul ignore else */
if (result) {
timestamps.push(result);
}
diff --git a/deps/npm/node_modules/@sigstore/verify/package.json b/deps/npm/node_modules/@sigstore/verify/package.json
index 9c4e5dc7a72..0e5480e3d7b 100644
--- a/deps/npm/node_modules/@sigstore/verify/package.json
+++ b/deps/npm/node_modules/@sigstore/verify/package.json
@@ -1,6 +1,6 @@
{
"name": "@sigstore/verify",
- "version": "3.1.1",
+ "version": "4.1.0",
"description": "Verification of Sigstore signatures",
"main": "dist/index.js",
"types": "dist/index.d.ts",
@@ -26,11 +26,11 @@
"provenance": true
},
"dependencies": {
- "@sigstore/protobuf-specs": "^0.5.0",
- "@sigstore/bundle": "^4.0.0",
- "@sigstore/core": "^3.2.1"
+ "@sigstore/bundle": "^5.0.0",
+ "@sigstore/core": "^4.0.1",
+ "@sigstore/protobuf-specs": "^0.5.0"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
}
}
diff --git a/deps/npm/node_modules/@tufjs/models/package.json b/deps/npm/node_modules/@tufjs/models/package.json
index cf4410577d0..de54f517e7e 100644
--- a/deps/npm/node_modules/@tufjs/models/package.json
+++ b/deps/npm/node_modules/@tufjs/models/package.json
@@ -1,6 +1,6 @@
{
"name": "@tufjs/models",
- "version": "4.1.0",
+ "version": "5.0.0",
"description": "TUF metadata models",
"main": "dist/index.js",
"types": "dist/index.d.ts",
@@ -29,9 +29,9 @@
"homepage": "https://github.com/theupdateframework/tuf-js/tree/main/packages/models#readme",
"dependencies": {
"@tufjs/canonical-json": "2.0.0",
- "minimatch": "^10.1.1"
+ "minimatch": "^10.2.1"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
}
}
diff --git a/deps/npm/node_modules/abbrev/package.json b/deps/npm/node_modules/abbrev/package.json
index f17aaccfa56..47798d9a32f 100644
--- a/deps/npm/node_modules/abbrev/package.json
+++ b/deps/npm/node_modules/abbrev/package.json
@@ -1,19 +1,20 @@
{
"name": "abbrev",
- "version": "4.0.0",
+ "version": "5.0.0",
"description": "Like ruby's abbrev module, but in js",
"author": "GitHub Inc.",
"main": "lib/index.js",
"scripts": {
- "test": "node --test",
+ "test": "node --test './test/**/*.js'",
"lint": "npm run eslint",
"postlint": "template-oss-check",
"template-oss-apply": "template-oss-apply --force",
"lintfix": "npm run eslint -- --fix",
- "snap": "node --test --test-update-snapshots",
+ "snap": "node --test --test-update-snapshots './test/**/*.js'",
"posttest": "npm run lint",
"eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"",
- "test:cover": "node --test --experimental-test-coverage --test-timeout=3000 --test-coverage-lines=100 --test-coverage-functions=100 --test-coverage-branches=100"
+ "test:cover": "node --test --experimental-test-coverage --test-timeout=3000 --test-coverage-lines=100 --test-coverage-functions=100 --test-coverage-branches=100 './test/**/*.js'",
+ "test:node20": "node --test test"
},
"repository": {
"type": "git",
@@ -21,19 +22,19 @@
},
"license": "ISC",
"devDependencies": {
- "@npmcli/eslint-config": "^5.0.0",
- "@npmcli/template-oss": "4.26.1"
+ "@npmcli/eslint-config": "^6.0.0",
+ "@npmcli/template-oss": "5.0.0"
},
"files": [
"bin/",
"lib/"
],
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.26.1",
+ "version": "5.0.0",
"publish": true,
"testRunner": "node:test",
"latestCiVersion": 24
diff --git a/deps/npm/node_modules/agent-base/dist/helpers.js b/deps/npm/node_modules/agent-base/dist/helpers.js
deleted file mode 100644
index ef3f92022d4..00000000000
--- a/deps/npm/node_modules/agent-base/dist/helpers.js
+++ /dev/null
@@ -1,66 +0,0 @@
-"use strict";
-var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
- if (k2 === undefined) k2 = k;
- var desc = Object.getOwnPropertyDescriptor(m, k);
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
- desc = { enumerable: true, get: function() { return m[k]; } };
- }
- Object.defineProperty(o, k2, desc);
-}) : (function(o, m, k, k2) {
- if (k2 === undefined) k2 = k;
- o[k2] = m[k];
-}));
-var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
- Object.defineProperty(o, "default", { enumerable: true, value: v });
-}) : function(o, v) {
- o["default"] = v;
-});
-var __importStar = (this && this.__importStar) || function (mod) {
- if (mod && mod.__esModule) return mod;
- var result = {};
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
- __setModuleDefault(result, mod);
- return result;
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.req = exports.json = exports.toBuffer = void 0;
-const http = __importStar(require("http"));
-const https = __importStar(require("https"));
-async function toBuffer(stream) {
- let length = 0;
- const chunks = [];
- for await (const chunk of stream) {
- length += chunk.length;
- chunks.push(chunk);
- }
- return Buffer.concat(chunks, length);
-}
-exports.toBuffer = toBuffer;
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-async function json(stream) {
- const buf = await toBuffer(stream);
- const str = buf.toString('utf8');
- try {
- return JSON.parse(str);
- }
- catch (_err) {
- const err = _err;
- err.message += ` (input: ${str})`;
- throw err;
- }
-}
-exports.json = json;
-function req(url, opts = {}) {
- const href = typeof url === 'string' ? url : url.href;
- const req = (href.startsWith('https:') ? https : http).request(url, opts);
- const promise = new Promise((resolve, reject) => {
- req
- .once('response', resolve)
- .once('error', reject)
- .end();
- });
- req.then = promise.then.bind(promise);
- return req;
-}
-exports.req = req;
-//# sourceMappingURL=helpers.js.map
\ No newline at end of file
diff --git a/deps/npm/node_modules/bin-links/lib/fix-bin.js b/deps/npm/node_modules/bin-links/lib/fix-bin.js
index 453bd4f3e95..cb54e2fda19 100644
--- a/deps/npm/node_modules/bin-links/lib/fix-bin.js
+++ b/deps/npm/node_modules/bin-links/lib/fix-bin.js
@@ -4,6 +4,7 @@ const {
chmod,
open,
readFile,
+ stat,
} = require('fs/promises')
const execMode = 0o777 & (~process.umask())
@@ -35,7 +36,8 @@ const dos2Unix = file =>
readFile(file, 'utf8').then(content =>
writeFileAtomic(file, content.replace(/^(#![^\n]+)\r\n/, '$1\n')))
-const fixBin = (file, mode = execMode) => chmod(file, mode)
+const fixBin = (file, mode = execMode) => stat(file)
+ .then(st => (st.mode & mode) === mode ? null : chmod(file, mode))
.then(() => isWindowsHashbangFile(file))
.then(isWHB => isWHB ? dos2Unix(file) : null)
diff --git a/deps/npm/node_modules/bin-links/lib/index.js b/deps/npm/node_modules/bin-links/lib/index.js
index ab3bd13c0be..b9b03422d2d 100644
--- a/deps/npm/node_modules/bin-links/lib/index.js
+++ b/deps/npm/node_modules/bin-links/lib/index.js
@@ -1,30 +1,22 @@
const linkBins = require('./link-bins.js')
-const linkMans = require('./link-mans.js')
const binLinks = opts => {
const { path, pkg, force, global, top } = opts
- // global top pkgs on windows get bins installed in {prefix}, and no mans
+ // global top pkgs on windows get bins installed in {prefix}.
//
- // unix global top pkgs get their bins installed in {prefix}/bin,
- // and mans in {prefix}/share/man
+ // unix global top pkgs get their bins installed in {prefix}/bin.
//
- // non-top pkgs get their bins installed in {prefix}/node_modules/.bin,
- // and do not install mans
+ // non-top pkgs get their bins installed in {prefix}/node_modules/.bin.
//
- // non-global top pkgs don't have any bins or mans linked. From here on
- // out, if it's top, we know that it's global, so no need to pass that
- // option further down the stack.
+ // non-global top pkgs don't have any bins linked. From here on out, if it's top, we know that it's global, so no need to pass that option further down the stack.
+ //
+ // As of v7, bin-links no longer installs man pages into the system man path for any package. `getPaths` still returns legacy man paths so pre-existing installs can be cleaned up on uninstall.
if (top && !global) {
return Promise.resolve()
}
- return Promise.all([
- // allow clobbering within the local node_modules/.bin folder.
- // only global bins are protected in this way, or else it is
- // yet another vector for excessive dependency conflicts.
- linkBins({ path, pkg, top, force: force || !top }),
- linkMans({ path, pkg, top, force }),
- ])
+ // allow clobbering within the local node_modules/.bin folder. only global bins are protected in this way, or else it is yet another vector for excessive dependency conflicts.
+ return linkBins({ path, pkg, top, force: force || !top })
}
const shimBin = require('./shim-bin.js')
diff --git a/deps/npm/node_modules/bin-links/lib/link-mans.js b/deps/npm/node_modules/bin-links/lib/link-mans.js
deleted file mode 100644
index b6dd214cebd..00000000000
--- a/deps/npm/node_modules/bin-links/lib/link-mans.js
+++ /dev/null
@@ -1,53 +0,0 @@
-const { dirname, relative, join, resolve, basename } = require('path')
-const linkGently = require('./link-gently.js')
-const manTarget = require('./man-target.js')
-
-const linkMans = async ({ path, pkg, top, force }) => {
- const target = manTarget({ path, top })
- if (!target || !Array.isArray(pkg?.man) || !pkg.man.length) {
- return []
- }
-
- const links = []
- // `new Set` to filter out duplicates
- for (let man of new Set(pkg.man)) {
- if (!man || typeof man !== 'string') {
- continue
- }
- // break any links to c:\\blah or /foo/blah or ../blah
- man = join('/', man).replace(/\\|:/g, '/').slice(1)
- const parseMan = man.match(/\.([0-9]+)(\.gz)?$/)
- if (!parseMan) {
- throw Object.assign(new Error('invalid man entry name\n' +
- 'Man files must end with a number, ' +
- 'and optionally a .gz suffix if they are compressed.'
- ), {
- code: 'EBADMAN',
- path,
- pkgid: pkg._id,
- man,
- })
- }
-
- const section = parseMan[1]
- const base = basename(man)
- const absFrom = resolve(path, man)
- /* istanbul ignore if - that unpossible */
- if (absFrom.indexOf(path) !== 0) {
- throw Object.assign(new Error('invalid man entry'), {
- code: 'EBADMAN',
- path,
- pkgid: pkg._id,
- man,
- })
- }
-
- const to = resolve(target, 'man' + section, base)
- const from = relative(dirname(to), absFrom)
-
- links.push(linkGently({ from, to, path, absFrom, force }))
- }
- return Promise.all(links)
-}
-
-module.exports = linkMans
diff --git a/deps/npm/node_modules/npm-bundled/LICENSE b/deps/npm/node_modules/bin-links/node_modules/cmd-shim/LICENSE
similarity index 100%
rename from deps/npm/node_modules/npm-bundled/LICENSE
rename to deps/npm/node_modules/bin-links/node_modules/cmd-shim/LICENSE
diff --git a/deps/npm/node_modules/cmd-shim/lib/index.js b/deps/npm/node_modules/bin-links/node_modules/cmd-shim/lib/index.js
similarity index 70%
rename from deps/npm/node_modules/cmd-shim/lib/index.js
rename to deps/npm/node_modules/bin-links/node_modules/cmd-shim/lib/index.js
index c13890aed32..1b6d1d8e491 100644
--- a/deps/npm/node_modules/cmd-shim/lib/index.js
+++ b/deps/npm/node_modules/bin-links/node_modules/cmd-shim/lib/index.js
@@ -60,13 +60,14 @@ const writeShim = (from, to) =>
const writeShim_ = (from, to, prog, args, variables) => {
let shTarget = relative(dirname(to), from)
+ shTarget = shTarget.split('\\').join('/')
let target = shTarget.split('/').join('\\')
+ let pwshTarget = shTarget
let longProg
let shProg = prog && prog.split('\\').join('/')
let shLongProg
let pwshProg = shProg && `"${shProg}$exe"`
let pwshLongProg
- shTarget = shTarget.split('\\').join('/')
args = args || ''
variables = variables || ''
if (!prog) {
@@ -76,12 +77,14 @@ const writeShim_ = (from, to, prog, args, variables) => {
args = ''
target = ''
shTarget = ''
+ pwshTarget = ''
} else {
longProg = `"%dp0%\\${prog}.exe"`
shLongProg = `"$basedir/${prog}"`
pwshLongProg = `"$basedir/${prog}$exe"`
target = `"%dp0%\\${target}"`
- shTarget = `"$basedir/${shTarget}"`
+ shTarget = `"$basedir_win/${shTarget}"`
+ pwshTarget = `"$basedir/${pwshTarget}"`
}
// Subroutine trick to fix https://github.com/npm/cmd-shim/issues/10
@@ -97,7 +100,6 @@ const writeShim_ = (from, to, prog, args, variables) => {
let cmd
if (longProg) {
- shLongProg = shLongProg.trim()
args = args.trim()
const variablesBatch = toBatchSyntax.convertToSetCommands(variables)
cmd = head
@@ -107,55 +109,88 @@ const writeShim_ = (from, to, prog, args, variables) => {
+ ` SET "_prog=${longProg.replace(/(^")|("$)/g, '')}"\r\n`
+ ') ELSE (\r\n'
+ ` SET "_prog=${prog.replace(/(^")|("$)/g, '')}"\r\n`
- + ' SET PATHEXT=%PATHEXT:;.JS;=;%\r\n'
+ ')\r\n'
+ '\r\n'
// prevent "Terminate Batch Job? (Y/n)" message
// https://github.com/npm/cli/issues/969#issuecomment-737496588
+ 'endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & '
- + `"%_prog%" ${args} ${target} %*\r\n`
+ + `set PATHEXT=%PATHEXT:;.JS;=;% & "%_prog%" ${args} ${target} %*\r\n`
} else {
cmd = `${head}${prog} ${args} ${target} %*\r\n`
}
// #!/bin/sh
- // basedir=`dirname "$0"`
+ // basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+ // basedir_win="$basedir"
//
- // case `uname` in
- // *CYGWIN*|*MINGW*|*MSYS*)
- // if command -v cygpath > /dev/null 2>&1; then
- // basedir=`cygpath -w "$basedir"`
+ // case `uname -a` in
+ // *CYGWIN*|*MINGW*|*MSYS*)
+ // if command -v cygpath > /dev/null 2>&1; then
+ // basedir_win=`cygpath -w "$basedir"`
+ // fi
+ // ;;
+ // *WSL2*)
+ // if command -v wslpath > /dev/null 2>&1; then
+ // basedir_win="$(wslpath -w "$basedir" 2> /dev/null)"
+ // if [ $? -ne 0 ] || [ -z "$basedir_win" ]; then
+ // echo "Error: wslpath failed to convert path. WSL environment may be misconfigured." >&2
+ // exit 1
// fi
- // ;;
+ // fi
+ // ;;
// esac
//
- // if [ -x "$basedir/node.exe" ]; then
- // exec "$basedir/node.exe" "$basedir/node_modules/npm/bin/npm-cli.js" "$@"
- // else
- // exec node "$basedir/node_modules/npm/bin/npm-cli.js" "$@"
+ // PROG_EXE="$basedir/node.exe"
+ // if ! [ -x "$PROG_EXE" ]; then
+ // PROG_EXE="$basedir/node"
+ // if ! [ -x "$PROG_EXE" ]; then
+ // PROG_EXE=node
+ // if ! [ -x "$PROG_EXE" ]; then
+ // PROG_EXE=node.exe
+ // fi
+ // fi
// fi
+ //
+ // exec "$PROG_EXE" "$basedir_win/node_modules/npm/bin/npm-cli.js" "$@"
let sh = '#!/bin/sh\n'
sh = sh
+ `basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')")\n`
+ + 'basedir_win="$basedir"\n'
+ '\n'
- + 'case `uname` in\n'
- + ' *CYGWIN*|*MINGW*|*MSYS*)\n'
- + ' if command -v cygpath > /dev/null 2>&1; then\n'
- + ' basedir=`cygpath -w "$basedir"`\n'
- + ' fi\n'
- + ' ;;\n'
+ + 'case `uname -a` in\n'
+ + ' *CYGWIN*|*MINGW*|*MSYS*)\n'
+ + ' if command -v cygpath > /dev/null 2>&1; then\n'
+ + ' basedir_win=`cygpath -w "$basedir"`\n'
+ + ' fi\n'
+ + ' ;;\n'
+ + ' *WSL2*)\n'
+ + ' if command -v wslpath > /dev/null 2>&1; then\n'
+ + ' basedir_win="$(wslpath -w "$basedir" 2> /dev/null)"\n'
+ + ' if [ $? -ne 0 ] || [ -z "$basedir_win" ]; then\n'
+ + ' echo "Error: wslpath failed to convert path. WSL environment may be misconfigured." >&2\n'
+ + ' exit 1\n'
+ + ' fi\n'
+ + ' fi\n'
+ + ' ;;\n'
+ 'esac\n'
+ '\n'
if (shLongProg) {
sh = sh
- + `if [ -x ${shLongProg} ]; then\n`
- + ` exec ${variables}${shLongProg} ${args} ${shTarget} "$@"\n`
- + 'else \n'
- + ` exec ${variables}${shProg} ${args} ${shTarget} "$@"\n`
+ + `PROG_EXE=${shLongProg.replace(/"$/, '.exe"')}\n`
+ + 'if ! [ -x "$PROG_EXE" ]; then\n'
+ + ` PROG_EXE=${shLongProg}\n`
+ + ' if ! [ -x "$PROG_EXE" ]; then\n'
+ + ` PROG_EXE=${shProg}\n`
+ + ' if ! [ -x "$PROG_EXE" ]; then\n'
+ + ` PROG_EXE=${shProg}.exe\n`
+ + ' fi\n'
+ + ' fi\n'
+ 'fi\n'
+ + '\n'
+ + `exec ${variables}"$PROG_EXE" ${args} ${shTarget} "$@"\n`
} else {
sh = sh
+ `exec ${shProg} ${args} ${shTarget} "$@"\n`
@@ -198,23 +233,23 @@ const writeShim_ = (from, to, prog, args, variables) => {
+ ' # are installed in the same directory\n'
+ ' $exe=".exe"\n'
+ '}\n'
- if (shLongProg) {
+ if (pwshLongProg) {
pwsh = pwsh
+ '$ret=0\n'
+ `if (Test-Path ${pwshLongProg}) {\n`
+ ' # Support pipeline input\n'
+ ' if ($MyInvocation.ExpectingInput) {\n'
- + ` $input | & ${pwshLongProg} ${args} ${shTarget} $args\n`
+ + ` $input | & ${pwshLongProg} ${args} ${pwshTarget} $args\n`
+ ' } else {\n'
- + ` & ${pwshLongProg} ${args} ${shTarget} $args\n`
+ + ` & ${pwshLongProg} ${args} ${pwshTarget} $args\n`
+ ' }\n'
+ ' $ret=$LASTEXITCODE\n'
+ '} else {\n'
+ ' # Support pipeline input\n'
+ ' if ($MyInvocation.ExpectingInput) {\n'
- + ` $input | & ${pwshProg} ${args} ${shTarget} $args\n`
+ + ` $input | & ${pwshProg} ${args} ${pwshTarget} $args\n`
+ ' } else {\n'
- + ` & ${pwshProg} ${args} ${shTarget} $args\n`
+ + ` & ${pwshProg} ${args} ${pwshTarget} $args\n`
+ ' }\n'
+ ' $ret=$LASTEXITCODE\n'
+ '}\n'
@@ -223,9 +258,9 @@ const writeShim_ = (from, to, prog, args, variables) => {
pwsh = pwsh
+ '# Support pipeline input\n'
+ 'if ($MyInvocation.ExpectingInput) {\n'
- + ` $input | & ${pwshProg} ${args} ${shTarget} $args\n`
+ + ` $input | & ${pwshProg} ${args} ${pwshTarget} $args\n`
+ '} else {\n'
- + ` & ${pwshProg} ${args} ${shTarget} $args\n`
+ + ` & ${pwshProg} ${args} ${pwshTarget} $args\n`
+ '}\n'
+ 'exit $LASTEXITCODE\n'
}
diff --git a/deps/npm/node_modules/cmd-shim/lib/to-batch-syntax.js b/deps/npm/node_modules/bin-links/node_modules/cmd-shim/lib/to-batch-syntax.js
similarity index 96%
rename from deps/npm/node_modules/cmd-shim/lib/to-batch-syntax.js
rename to deps/npm/node_modules/bin-links/node_modules/cmd-shim/lib/to-batch-syntax.js
index 86a3f01405d..23e6ad28c4f 100644
--- a/deps/npm/node_modules/cmd-shim/lib/to-batch-syntax.js
+++ b/deps/npm/node_modules/bin-links/node_modules/cmd-shim/lib/to-batch-syntax.js
@@ -1,49 +1,49 @@
-exports.replaceDollarWithPercentPair = replaceDollarWithPercentPair
-exports.convertToSetCommand = convertToSetCommand
-exports.convertToSetCommands = convertToSetCommands
-
-function convertToSetCommand (key, value) {
- var line = ''
- key = key || ''
- key = key.trim()
- value = value || ''
- value = value.trim()
- if (key && value && value.length > 0) {
- line = '@SET ' + key + '=' + replaceDollarWithPercentPair(value) + '\r\n'
- }
- return line
-}
-
-function extractVariableValuePairs (declarations) {
- var pairs = {}
- declarations.map(function (declaration) {
- var split = declaration.split('=')
- pairs[split[0]] = split[1]
- })
- return pairs
-}
-
-function convertToSetCommands (variableString) {
- var variableValuePairs = extractVariableValuePairs(variableString.split(' '))
- var variableDeclarationsAsBatch = ''
- Object.keys(variableValuePairs).forEach(function (key) {
- variableDeclarationsAsBatch += convertToSetCommand(key, variableValuePairs[key])
- })
- return variableDeclarationsAsBatch
-}
-
-function replaceDollarWithPercentPair (value) {
- var dollarExpressions = /\$\{?([^$@#?\- \t{}:]+)\}?/g
- var result = ''
- var startIndex = 0
- do {
- var match = dollarExpressions.exec(value)
- if (match) {
- var betweenMatches = value.substring(startIndex, match.index) || ''
- result += betweenMatches + '%' + match[1] + '%'
- startIndex = dollarExpressions.lastIndex
- }
- } while (dollarExpressions.lastIndex > 0)
- result += value.slice(startIndex)
- return result
-}
+exports.replaceDollarWithPercentPair = replaceDollarWithPercentPair
+exports.convertToSetCommand = convertToSetCommand
+exports.convertToSetCommands = convertToSetCommands
+
+function convertToSetCommand (key, value) {
+ var line = ''
+ key = key || ''
+ key = key.trim()
+ value = value || ''
+ value = value.trim()
+ if (key && value && value.length > 0) {
+ line = '@SET ' + key + '=' + replaceDollarWithPercentPair(value) + '\r\n'
+ }
+ return line
+}
+
+function extractVariableValuePairs (declarations) {
+ var pairs = {}
+ declarations.map(function (declaration) {
+ var split = declaration.split('=')
+ pairs[split[0]] = split[1]
+ })
+ return pairs
+}
+
+function convertToSetCommands (variableString) {
+ var variableValuePairs = extractVariableValuePairs(variableString.split(' '))
+ var variableDeclarationsAsBatch = ''
+ Object.keys(variableValuePairs).forEach(function (key) {
+ variableDeclarationsAsBatch += convertToSetCommand(key, variableValuePairs[key])
+ })
+ return variableDeclarationsAsBatch
+}
+
+function replaceDollarWithPercentPair (value) {
+ var dollarExpressions = /\$\{?([^$@#?\- \t{}:]+)\}?/g
+ var result = ''
+ var startIndex = 0
+ do {
+ var match = dollarExpressions.exec(value)
+ if (match) {
+ var betweenMatches = value.substring(startIndex, match.index) || ''
+ result += betweenMatches + '%' + match[1] + '%'
+ startIndex = dollarExpressions.lastIndex
+ }
+ } while (dollarExpressions.lastIndex > 0)
+ result += value.slice(startIndex)
+ return result
+}
diff --git a/deps/npm/node_modules/cmd-shim/package.json b/deps/npm/node_modules/bin-links/node_modules/cmd-shim/package.json
similarity index 85%
rename from deps/npm/node_modules/cmd-shim/package.json
rename to deps/npm/node_modules/bin-links/node_modules/cmd-shim/package.json
index 0da1978b985..3a50fb90829 100644
--- a/deps/npm/node_modules/cmd-shim/package.json
+++ b/deps/npm/node_modules/bin-links/node_modules/cmd-shim/package.json
@@ -1,6 +1,6 @@
{
"name": "cmd-shim",
- "version": "8.0.0",
+ "version": "9.0.2",
"description": "Used in npm for command line application support",
"scripts": {
"test": "tap",
@@ -18,8 +18,8 @@
},
"license": "ISC",
"devDependencies": {
- "@npmcli/eslint-config": "^5.0.0",
- "@npmcli/template-oss": "4.27.1",
+ "@npmcli/eslint-config": "^7.0.0",
+ "@npmcli/template-oss": "5.1.1",
"tap": "^16.0.1"
},
"files": [
@@ -37,12 +37,12 @@
]
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"author": "GitHub Inc.",
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.27.1",
+ "version": "5.1.1",
"publish": true
}
}
diff --git a/deps/npm/node_modules/bin-links/node_modules/npm-normalize-package-bin/LICENSE b/deps/npm/node_modules/bin-links/node_modules/npm-normalize-package-bin/LICENSE
new file mode 100644
index 00000000000..19cec97b184
--- /dev/null
+++ b/deps/npm/node_modules/bin-links/node_modules/npm-normalize-package-bin/LICENSE
@@ -0,0 +1,15 @@
+The ISC License
+
+Copyright (c) npm, 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.
diff --git a/deps/npm/node_modules/bin-links/node_modules/npm-normalize-package-bin/lib/index.js b/deps/npm/node_modules/bin-links/node_modules/npm-normalize-package-bin/lib/index.js
new file mode 100644
index 00000000000..3cb8478cf6e
--- /dev/null
+++ b/deps/npm/node_modules/bin-links/node_modules/npm-normalize-package-bin/lib/index.js
@@ -0,0 +1,64 @@
+// pass in a manifest with a 'bin' field here, and it'll turn it
+// into a properly santized bin object
+const { join, basename } = require('path')
+
+const normalize = pkg =>
+ !pkg.bin ? removeBin(pkg)
+ : typeof pkg.bin === 'string' ? normalizeString(pkg)
+ : Array.isArray(pkg.bin) ? normalizeArray(pkg)
+ : typeof pkg.bin === 'object' ? normalizeObject(pkg)
+ : removeBin(pkg)
+
+const normalizeString = pkg => {
+ if (!pkg.name) {
+ return removeBin(pkg)
+ }
+ pkg.bin = { [pkg.name]: pkg.bin }
+ return normalizeObject(pkg)
+}
+
+const normalizeArray = pkg => {
+ pkg.bin = pkg.bin.reduce((acc, k) => {
+ acc[basename(k)] = k
+ return acc
+ }, {})
+ return normalizeObject(pkg)
+}
+
+const removeBin = pkg => {
+ delete pkg.bin
+ return pkg
+}
+
+const normalizeObject = pkg => {
+ const orig = pkg.bin
+ const clean = {}
+ let hasBins = false
+ Object.keys(orig).forEach(binKey => {
+ const base = join('/', basename(binKey.replace(/\\|:/g, '/'))).slice(1)
+
+ if (typeof orig[binKey] !== 'string' || !base) {
+ return
+ }
+
+ const binTarget = join('/', orig[binKey].replace(/\\/g, '/'))
+ .replace(/\\/g, '/').slice(1)
+
+ if (!binTarget) {
+ return
+ }
+
+ clean[base] = binTarget
+ hasBins = true
+ })
+
+ if (hasBins) {
+ pkg.bin = clean
+ } else {
+ delete pkg.bin
+ }
+
+ return pkg
+}
+
+module.exports = normalize
diff --git a/deps/npm/node_modules/bin-links/node_modules/npm-normalize-package-bin/package.json b/deps/npm/node_modules/bin-links/node_modules/npm-normalize-package-bin/package.json
new file mode 100644
index 00000000000..1d0d821b7a2
--- /dev/null
+++ b/deps/npm/node_modules/bin-links/node_modules/npm-normalize-package-bin/package.json
@@ -0,0 +1,42 @@
+{
+ "name": "npm-normalize-package-bin",
+ "version": "6.0.0",
+ "description": "Turn any flavor of allowable package.json bin into a normalized object",
+ "main": "lib/index.js",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/npm/npm-normalize-package-bin.git"
+ },
+ "author": "GitHub Inc.",
+ "license": "ISC",
+ "scripts": {
+ "test": "node --test './test/**/*.js'",
+ "snap": "node --test --test-update-snapshots './test/**/*.js'",
+ "lint": "npm run eslint",
+ "postlint": "template-oss-check",
+ "template-oss-apply": "template-oss-apply --force",
+ "lintfix": "npm run eslint -- --fix",
+ "posttest": "npm run lint",
+ "eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"",
+ "test:node20": "node --test test",
+ "test:cover": "node --test --experimental-test-coverage --test-timeout=3000 --test-coverage-lines=100 --test-coverage-functions=100 --test-coverage-branches=100 './test/**/*.js'"
+ },
+ "devDependencies": {
+ "@npmcli/eslint-config": "^6.0.0",
+ "@npmcli/template-oss": "5.0.0"
+ },
+ "files": [
+ "bin/",
+ "lib/"
+ ],
+ "engines": {
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
+ },
+ "templateOSS": {
+ "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
+ "version": "5.0.0",
+ "publish": "true",
+ "testRunner": "node:test",
+ "latestCiVersion": 24
+ }
+}
diff --git a/deps/npm/node_modules/read-cmd-shim/LICENSE b/deps/npm/node_modules/bin-links/node_modules/read-cmd-shim/LICENSE
similarity index 99%
rename from deps/npm/node_modules/read-cmd-shim/LICENSE
rename to deps/npm/node_modules/bin-links/node_modules/read-cmd-shim/LICENSE
index f4be44d881b..2a4982dc40c 100644
--- a/deps/npm/node_modules/read-cmd-shim/LICENSE
+++ b/deps/npm/node_modules/bin-links/node_modules/read-cmd-shim/LICENSE
@@ -11,4 +11,3 @@ 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.
-
diff --git a/deps/npm/node_modules/read-cmd-shim/lib/index.js b/deps/npm/node_modules/bin-links/node_modules/read-cmd-shim/lib/index.js
similarity index 100%
rename from deps/npm/node_modules/read-cmd-shim/lib/index.js
rename to deps/npm/node_modules/bin-links/node_modules/read-cmd-shim/lib/index.js
diff --git a/deps/npm/node_modules/read-cmd-shim/package.json b/deps/npm/node_modules/bin-links/node_modules/read-cmd-shim/package.json
similarity index 55%
rename from deps/npm/node_modules/read-cmd-shim/package.json
rename to deps/npm/node_modules/bin-links/node_modules/read-cmd-shim/package.json
index d3ebc40e311..cfd11bfe148 100644
--- a/deps/npm/node_modules/read-cmd-shim/package.json
+++ b/deps/npm/node_modules/bin-links/node_modules/read-cmd-shim/package.json
@@ -1,30 +1,24 @@
{
"name": "read-cmd-shim",
- "version": "6.0.0",
+ "version": "7.0.0",
"description": "Figure out what a cmd-shim is pointing at. This acts as the equivalent of fs.readlink.",
"main": "lib/index.js",
"devDependencies": {
- "@npmcli/eslint-config": "^5.0.0",
- "@npmcli/template-oss": "4.27.1",
- "cmd-shim": "^7.0.0",
- "tap": "^16.0.1"
+ "@npmcli/eslint-config": "^6.0.0",
+ "@npmcli/template-oss": "5.0.0",
+ "cmd-shim": "^8.0.0"
},
"scripts": {
- "test": "tap",
+ "test": "node --test './test/**/*.js'",
"lint": "npm run eslint",
"postlint": "template-oss-check",
"template-oss-apply": "template-oss-apply --force",
"lintfix": "npm run eslint -- --fix",
- "snap": "tap",
+ "snap": "node --test --test-update-snapshots './test/**/*.js'",
"posttest": "npm run lint",
- "eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\""
- },
- "tap": {
- "check-coverage": true,
- "nyc-arg": [
- "--exclude",
- "tap-snapshots/**"
- ]
+ "eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"",
+ "test:cover": "node --test --experimental-test-coverage --test-timeout=3000 --test-coverage-lines=100 --test-coverage-functions=100 --test-coverage-branches=100 './test/**/*.js'",
+ "test:node20": "node --test test"
},
"repository": {
"type": "git",
@@ -38,11 +32,13 @@
],
"author": "GitHub Inc.",
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.27.1",
- "publish": true
+ "version": "5.0.0",
+ "publish": true,
+ "testRunner": "node:test",
+ "latestCiVersion": 24
}
}
diff --git a/deps/npm/node_modules/bin-links/package.json b/deps/npm/node_modules/bin-links/package.json
index 80a63323e88..a6d8ae82217 100644
--- a/deps/npm/node_modules/bin-links/package.json
+++ b/deps/npm/node_modules/bin-links/package.json
@@ -1,6 +1,6 @@
{
"name": "bin-links",
- "version": "6.0.2",
+ "version": "7.0.0",
"description": "JavaScript package binary linker",
"main": "./lib/index.js",
"scripts": {
@@ -24,15 +24,15 @@
],
"license": "ISC",
"dependencies": {
- "cmd-shim": "^8.0.0",
- "npm-normalize-package-bin": "^5.0.0",
- "proc-log": "^6.0.0",
- "read-cmd-shim": "^6.0.0",
- "write-file-atomic": "^7.0.0"
+ "cmd-shim": "^9.0.0",
+ "npm-normalize-package-bin": "^6.0.0",
+ "proc-log": "^7.0.0",
+ "read-cmd-shim": "^7.0.0",
+ "write-file-atomic": "^8.0.0"
},
"devDependencies": {
- "@npmcli/eslint-config": "^5.0.0",
- "@npmcli/template-oss": "4.30.0",
+ "@npmcli/eslint-config": "^6.0.0",
+ "@npmcli/template-oss": "5.1.0",
"require-inject": "^1.4.4",
"tap": "^16.0.1"
},
@@ -49,15 +49,14 @@
"lib/"
],
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"author": "GitHub Inc.",
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
"windowsCI": false,
- "version": "4.30.0",
+ "version": "5.1.0",
"publish": true,
- "updateNpm": false,
- "latestCiVersion": 24
+ "updateNpm": false
}
}
diff --git a/deps/npm/node_modules/cacache/lib/content/write.js b/deps/npm/node_modules/cacache/lib/content/write.js
index 8deb91c066a..e8d49899815 100644
--- a/deps/npm/node_modules/cacache/lib/content/write.js
+++ b/deps/npm/node_modules/cacache/lib/content/write.js
@@ -10,6 +10,7 @@ const Pipeline = require('minipass-pipeline')
const Flush = require('minipass-flush')
const path = require('path')
const ssri = require('ssri')
+const cacheDir = require('../util/cache-dir')
const { tmpName } = require('../util/tmp')
const fsm = require('fs-minipass')
@@ -153,6 +154,7 @@ async function pipeToTmp (inputStream, cache, tmpTarget, opts) {
async function makeTmp (cache, opts) {
const tmpTarget = tmpName(cache, opts.tmpPrefix)
+ await cacheDir.mkdir(cache)
await fs.mkdir(path.dirname(tmpTarget), { recursive: true })
return {
target: tmpTarget,
diff --git a/deps/npm/node_modules/cacache/lib/entry-index.js b/deps/npm/node_modules/cacache/lib/entry-index.js
index a8fdf93a03e..6048a813cb7 100644
--- a/deps/npm/node_modules/cacache/lib/entry-index.js
+++ b/deps/npm/node_modules/cacache/lib/entry-index.js
@@ -13,6 +13,7 @@ const { Minipass } = require('minipass')
const path = require('path')
const ssri = require('ssri')
const { tmpName } = require('./util/tmp')
+const cacheDir = require('./util/cache-dir')
const contentPath = require('./content/path')
const hashToSegments = require('./util/hash-to-segments')
@@ -70,6 +71,7 @@ async function compact (cache, key, matchFn, opts = {}) {
const setup = async () => {
const target = tmpName(cache, opts.tmpPrefix)
+ await cacheDir.mkdir(cache)
await mkdir(path.dirname(target), { recursive: true })
return {
target,
@@ -121,6 +123,7 @@ async function insert (cache, key, integrity, opts = {}) {
metadata,
}
try {
+ await cacheDir.mkdir(cache)
await mkdir(path.dirname(bucket), { recursive: true })
const stringified = JSON.stringify(entry)
// NOTE - Cleverness ahoy!
diff --git a/deps/npm/node_modules/cacache/lib/rm.js b/deps/npm/node_modules/cacache/lib/rm.js
index a94760c7cf2..897ebccd5ee 100644
--- a/deps/npm/node_modules/cacache/lib/rm.js
+++ b/deps/npm/node_modules/cacache/lib/rm.js
@@ -27,5 +27,6 @@ module.exports.all = all
async function all (cache) {
memo.clearMemoized()
const paths = await glob(path.join(cache, '*(content-*|index-*)'), { silent: true, nosort: true })
+ paths.push(path.join(cache, 'CACHEDIR.TAG'))
return Promise.all(paths.map((p) => rm(p, { recursive: true, force: true })))
}
diff --git a/deps/npm/node_modules/cacache/lib/util/cache-dir.js b/deps/npm/node_modules/cacache/lib/util/cache-dir.js
new file mode 100644
index 00000000000..3cc63808f6f
--- /dev/null
+++ b/deps/npm/node_modules/cacache/lib/util/cache-dir.js
@@ -0,0 +1,29 @@
+'use strict'
+
+const fs = require('fs/promises')
+const path = require('path')
+
+const tagContent = `Signature: 8a477f597d28d172789f06886806bc55
+# This file is a cache directory tag created by cacache.
+# For information about cache directory tags, see https://bford.info/cachedir/
+`
+
+async function mkdir (cache) {
+ await fs.mkdir(cache, { recursive: true, owner: 'inherit' })
+ await writeTag(cache)
+}
+
+async function writeTag (cache) {
+ try {
+ await fs.writeFile(path.join(cache, 'CACHEDIR.TAG'), tagContent, { flag: 'wx' })
+ } catch (err) {
+ if (err.code !== 'EEXIST') {
+ throw err
+ }
+ }
+}
+
+module.exports = {
+ mkdir,
+ tagContent,
+}
diff --git a/deps/npm/node_modules/cacache/lib/util/tmp.js b/deps/npm/node_modules/cacache/lib/util/tmp.js
index d5c088e1e6d..d274499c711 100644
--- a/deps/npm/node_modules/cacache/lib/util/tmp.js
+++ b/deps/npm/node_modules/cacache/lib/util/tmp.js
@@ -4,6 +4,7 @@ const crypto = require('crypto')
const { withTempDir } = require('@npmcli/fs')
const fs = require('fs/promises')
const path = require('path')
+const cacheDir = require('./cache-dir')
module.exports.mkdir = mktmpdir
@@ -15,6 +16,7 @@ module.exports.tmpName = function tmpName (cache, tmpPrefix) {
async function mktmpdir (cache, opts = {}) {
const { tmpPrefix } = opts
const tmpDir = path.join(cache, 'tmp')
+ await cacheDir.mkdir(cache)
await fs.mkdir(tmpDir, { recursive: true, owner: 'inherit' })
// do not use path.join(), it drops the trailing / if tmpPrefix is unset
const target = `${tmpDir}${path.sep}${tmpPrefix || ''}`
@@ -28,5 +30,7 @@ function withTmp (cache, opts, cb) {
cb = opts
opts = {}
}
- return withTempDir(path.join(cache, 'tmp'), cb, opts)
+ return cacheDir.mkdir(cache).then(() =>
+ withTempDir(path.join(cache, 'tmp'), cb, opts)
+ )
}
diff --git a/deps/npm/node_modules/cacache/lib/verify.js b/deps/npm/node_modules/cacache/lib/verify.js
index dcff3aa73f3..8e2226458fd 100644
--- a/deps/npm/node_modules/cacache/lib/verify.js
+++ b/deps/npm/node_modules/cacache/lib/verify.js
@@ -1,7 +1,6 @@
'use strict'
const {
- mkdir,
readFile,
rm,
stat,
@@ -12,6 +11,7 @@ const contentPath = require('./content/path')
const fsm = require('fs-minipass')
const glob = require('./util/glob.js')
const index = require('./entry-index')
+const cacheDir = require('./util/cache-dir')
const path = require('path')
const ssri = require('ssri')
@@ -77,7 +77,7 @@ async function markEndTime () {
async function fixPerms (cache, opts) {
opts.log.silly('verify', 'fixing cache permissions')
- await mkdir(cache, { recursive: true })
+ await cacheDir.mkdir(cache)
return null
}
diff --git a/deps/npm/node_modules/cacache/package.json b/deps/npm/node_modules/cacache/package.json
index 170e43646fa..1dbd6507ad9 100644
--- a/deps/npm/node_modules/cacache/package.json
+++ b/deps/npm/node_modules/cacache/package.json
@@ -1,6 +1,6 @@
{
"name": "cacache",
- "version": "20.0.4",
+ "version": "21.0.1",
"cache-version": {
"content": "2",
"index": "5"
@@ -46,7 +46,7 @@
],
"license": "ISC",
"dependencies": {
- "@npmcli/fs": "^5.0.0",
+ "@npmcli/fs": "^6.0.0",
"fs-minipass": "^3.0.0",
"glob": "^13.0.0",
"lru-cache": "^11.1.0",
@@ -55,20 +55,20 @@
"minipass-flush": "^1.0.5",
"minipass-pipeline": "^1.2.4",
"p-map": "^7.0.2",
- "ssri": "^13.0.0"
+ "ssri": "^14.0.0"
},
"devDependencies": {
- "@npmcli/eslint-config": "^6.0.1",
- "@npmcli/template-oss": "4.29.0",
+ "@npmcli/eslint-config": "^7.0.0",
+ "@npmcli/template-oss": "5.1.0",
"tap": "^16.0.0"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
"windowsCI": false,
- "version": "4.29.0",
+ "version": "5.1.0",
"publish": "true"
},
"author": "GitHub Inc.",
diff --git a/deps/npm/node_modules/cidr-regex/package.json b/deps/npm/node_modules/cidr-regex/package.json
index c15a446e7e2..0462dc87dc8 100644
--- a/deps/npm/node_modules/cidr-regex/package.json
+++ b/deps/npm/node_modules/cidr-regex/package.json
@@ -1,6 +1,6 @@
{
"name": "cidr-regex",
- "version": "5.0.5",
+ "version": "6.0.0",
"description": "Regular expression for matching IP addresses in CIDR notation",
"author": "silverwind <me@silverwind.io>",
"contributors": [
@@ -30,7 +30,7 @@
"dist"
],
"engines": {
- "node": ">=20"
+ "node": ">=22"
},
"devDependencies": {
"@types/node": "25.6.0",
@@ -39,13 +39,13 @@
"eslint-config-silverwind": "132.0.0",
"jest-extended": "7.0.0",
"tsdown": "0.21.10",
- "tsdown-config-silverwind": "2.1.1",
+ "tsdown-config-silverwind": "3.0.0",
"typescript": "6.0.3",
"typescript-config-silverwind": "18.0.0",
"updates": "17.16.4",
- "updates-config-silverwind": "2.1.1",
+ "updates-config-silverwind": "3.0.0",
"versions": "15.0.1",
"vitest": "4.1.5",
- "vitest-config-silverwind": "11.3.1"
+ "vitest-config-silverwind": "11.3.3"
}
}
\ No newline at end of file
diff --git a/deps/npm/node_modules/hosted-git-info/lib/parse-url.js b/deps/npm/node_modules/hosted-git-info/lib/parse-url.js
index bfd54b9140c..1f7d0920652 100644
--- a/deps/npm/node_modules/hosted-git-info/lib/parse-url.js
+++ b/deps/npm/node_modules/hosted-git-info/lib/parse-url.js
@@ -1,5 +1,3 @@
-const url = require('url')
-
const lastIndexOfBefore = (str, char, beforeChar) => {
const startPosition = str.indexOf(beforeChar)
return str.lastIndexOf(char, startPosition > -1 ? startPosition : Infinity)
@@ -7,7 +5,7 @@ const lastIndexOfBefore = (str, char, beforeChar) => {
const safeUrl = (u) => {
try {
- return new url.URL(u)
+ return new URL(u)
} catch {
// this fn should never throw
}
diff --git a/deps/npm/node_modules/hosted-git-info/package.json b/deps/npm/node_modules/hosted-git-info/package.json
index f21e546a64b..6edff000952 100644
--- a/deps/npm/node_modules/hosted-git-info/package.json
+++ b/deps/npm/node_modules/hosted-git-info/package.json
@@ -1,6 +1,6 @@
{
"name": "hosted-git-info",
- "version": "9.0.3",
+ "version": "10.1.1",
"description": "Provides metadata and conversions from repository urls for GitHub, Bitbucket and GitLab",
"main": "./lib/index.js",
"repository": {
@@ -37,18 +37,18 @@
},
"devDependencies": {
"@npmcli/eslint-config": "^6.0.0",
- "@npmcli/template-oss": "4.30.0"
+ "@npmcli/template-oss": "5.1.0"
},
"files": [
"bin/",
"lib/"
],
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.30.0",
+ "version": "5.1.0",
"publish": "true",
"testRunner": "node:test",
"latestCiVersion": 24,
diff --git a/deps/npm/node_modules/iconv-lite/encodings/sbcs-data.js b/deps/npm/node_modules/iconv-lite/encodings/sbcs-data.js
index d8f8e1729e6..a08703c9bc2 100644
--- a/deps/npm/node_modules/iconv-lite/encodings/sbcs-data.js
+++ b/deps/npm/node_modules/iconv-lite/encodings/sbcs-data.js
@@ -109,6 +109,8 @@ module.exports = {
hebrew: "iso88598",
hebrew8: "iso88598",
+ iso88598i: "iso88598",
+ iso88598e: "iso88598",
turkish: "iso88599",
turkish8: "iso88599",
diff --git a/deps/npm/node_modules/iconv-lite/encodings/utf32.js b/deps/npm/node_modules/iconv-lite/encodings/utf32.js
index 723178937a3..7e49d7ad761 100644
--- a/deps/npm/node_modules/iconv-lite/encodings/utf32.js
+++ b/deps/npm/node_modules/iconv-lite/encodings/utf32.js
@@ -31,7 +31,9 @@ function Utf32Encoder (options, codec) {
Utf32Encoder.prototype.write = function (str) {
var src = Buffer.from(str, "ucs2")
- var dst = Buffer.alloc(src.length * 2)
+ // src.length * 2 covers this chunk's code units (4 bytes each); the extra 4 bytes leave room for a
+ // high surrogate held over from a previous chunk, which is flushed ahead of this chunk's units.
+ var dst = Buffer.alloc(src.length * 2 + 4)
var write32 = this.isLE ? dst.writeUInt32LE : dst.writeUInt32BE
var offset = 0
@@ -113,9 +115,9 @@ Utf32Decoder.prototype.write = function (src) {
// NOTE: codepoint is a signed int32 and can be negative.
// NOTE: We copied this block from below to help V8 optimize it (it works with array, not buffer).
if (isLE) {
- codepoint = overflow[i] | (overflow[i + 1] << 8) | (overflow[i + 2] << 16) | (overflow[i + 3] << 24)
+ codepoint = overflow[0] | (overflow[1] << 8) | (overflow[2] << 16) | (overflow[3] << 24)
} else {
- codepoint = overflow[i + 3] | (overflow[i + 2] << 8) | (overflow[i + 1] << 16) | (overflow[i] << 24)
+ codepoint = overflow[3] | (overflow[2] << 8) | (overflow[1] << 16) | (overflow[0] << 24)
}
overflow.length = 0
@@ -169,7 +171,12 @@ function _writeCodepoint (dst, offset, codepoint, badChar) {
};
Utf32Decoder.prototype.end = function () {
+ if (this.overflow.length === 0) { return }
+
+ // A leftover, incomplete 4-byte code unit at the end of the input is ill-formed. Substitute a
+ // single U+FFFD (Unicode Standard conformance clause C10) instead of silently dropping the bytes.
this.overflow.length = 0
+ return String.fromCharCode(this.badChar)
}
// == UTF-32 Auto codec =============================================================
diff --git a/deps/npm/node_modules/iconv-lite/package.json b/deps/npm/node_modules/iconv-lite/package.json
index 867c98a684e..ffbb1dec7a5 100644
--- a/deps/npm/node_modules/iconv-lite/package.json
+++ b/deps/npm/node_modules/iconv-lite/package.json
@@ -1,7 +1,7 @@
{
"name": "iconv-lite",
"description": "Convert character encodings in pure javascript.",
- "version": "0.7.2",
+ "version": "0.7.3",
"license": "MIT",
"keywords": [
"iconv",
@@ -46,7 +46,7 @@
"stream": false
},
"devDependencies": {
- "@arethetypeswrong/cli": "^0.17.4",
+ "@arethetypeswrong/cli": "^0.18.4",
"@stylistic/eslint-plugin": "^5.1.0",
"@stylistic/eslint-plugin-js": "^4.1.0",
"@types/node": "^24.0.12",
diff --git a/deps/npm/node_modules/ini/package.json b/deps/npm/node_modules/ini/package.json
index 7bbc0576937..6d6ade1f253 100644
--- a/deps/npm/node_modules/ini/package.json
+++ b/deps/npm/node_modules/ini/package.json
@@ -2,7 +2,7 @@
"author": "GitHub Inc.",
"name": "ini",
"description": "An ini encoder/decoder for node",
- "version": "6.0.0",
+ "version": "7.0.0",
"repository": {
"type": "git",
"url": "git+https://github.com/npm/ini.git"
@@ -19,8 +19,8 @@
"template-oss-apply": "template-oss-apply --force"
},
"devDependencies": {
- "@npmcli/eslint-config": "^5.0.0",
- "@npmcli/template-oss": "4.27.1",
+ "@npmcli/eslint-config": "^6.0.0",
+ "@npmcli/template-oss": "5.0.0",
"tap": "^16.0.1"
},
"license": "ISC",
@@ -29,11 +29,11 @@
"lib/"
],
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.27.1",
+ "version": "5.0.0",
"publish": "true"
},
"tap": {
diff --git a/deps/npm/node_modules/init-package-json/lib/default-input.js b/deps/npm/node_modules/init-package-json/lib/default-input.js
index 7b9c8f440e0..a20217b0e47 100644
--- a/deps/npm/node_modules/init-package-json/lib/default-input.js
+++ b/deps/npm/node_modules/init-package-json/lib/default-input.js
@@ -7,47 +7,8 @@ const validateName = require('validate-npm-package-name')
const npa = require('npm-package-arg')
const semver = require('semver')
-// more popular packages should go here, maybe?
-const testPkgs = [
- 'coco',
- 'coffee-script',
- 'expresso',
- 'jasmine',
- 'jest',
- 'mocha',
- 'streamline',
- 'tap',
-]
-const isTestPkg = p => testPkgs.includes(p)
-
const invalid = (msg) => Object.assign(new Error(msg), { notValid: true })
-const readDeps = (test, excluded) => async () => {
- const dirs = await fs.readdir('node_modules').catch(() => null)
-
- if (!dirs) {
- return
- }
-
- const deps = {}
- for (const dir of dirs) {
- if (dir.match(/^\./) || test !== isTestPkg(dir) || excluded[dir]) {
- continue
- }
-
- const dp = path.join(dirname, 'node_modules', dir, 'package.json')
- const p = await fs.readFile(dp, 'utf8').then((d) => JSON.parse(d)).catch(() => null)
-
- if (!p || !p.version || p?._requiredBy?.some((r) => r === '#USER')) {
- continue
- }
-
- deps[dir] = config.get('save-exact') ? p.version : config.get('save-prefix') + p.version
- }
-
- return deps
-}
-
const getConfig = (key) => {
// dots take precedence over dashes
const def = config?.defaults?.[`init.${key}`]
@@ -167,14 +128,6 @@ exports.directories = async () => {
return Object.keys(res).length === 0 ? undefined : res
}
-if (!package.dependencies) {
- exports.dependencies = readDeps(false, package.devDependencies || {})
-}
-
-if (!package.devDependencies) {
- exports.devDependencies = readDeps(true, package.dependencies || {})
-}
-
// MUST have a test script!
if (!package.scripts) {
const scripts = package.scripts || {}
@@ -251,24 +204,54 @@ if (!package.keywords) {
})
}
-if (!package.author) {
+let author
+if (package.author) {
+ if (typeof package.author === 'string') {
+ author = package.author
+ } else {
+ const authorName = package.author.name
+ const authorEmail = package.author.email || package.author.mail
+ const authorUrl = package.author.url || package.author.web
+ author = `${authorName}${authorEmail ? ` <${authorEmail}>` : ''}${authorUrl ? ` (${authorUrl})` : ''}`
+ }
+} else {
const authorName = getConfig('author.name')
- exports.author = authorName
- ? {
- name: authorName,
- email: getConfig('author.email'),
- url: getConfig('author.url'),
- }
- : yes ? '' : prompt('author')
+ if (authorName) {
+ const authorEmail = getConfig('author.email')
+ const authorUrl = getConfig('author.url')
+ author = `${authorName}${authorEmail ? ` <${authorEmail}>` : ''}${authorUrl ? ` (${authorUrl})` : ''}`
+ }
}
-const license = package.license || getConfig('license') || 'ISC'
-exports.license = yes ? license : prompt('license', license, (data) => {
- if (validateLicense(data)) {
- return data
+if (yes) {
+ if (author) {
+ exports.author = author
}
- return invalid('Sorry, license should be a valid SPDX license expression')
-})
+} else {
+ exports.author = prompt('author', author || undefined)
+}
+
+const configLicense = getConfig('license')
+const license = package.license || configLicense || undefined
+
+if (yes) {
+ // Only include license if explicitly set in config or already in package.json
+ if (license) {
+ exports.license = license
+ }
+} else {
+ exports.license = prompt('license', license || undefined, (data) => {
+ if (!data) {
+ return undefined
+ }
+ if (validateLicense(data)) {
+ return data
+ }
+ return invalid(
+ 'License should be a valid SPDX license expression'
+ )
+ })
+}
const type = package.type || getConfig('type') || 'commonjs'
exports.type = yes ? type : prompt('type', type, (data) => {
diff --git a/deps/npm/node_modules/init-package-json/lib/init-package-json.js b/deps/npm/node_modules/init-package-json/lib/init-package-json.js
index b67ae418f7a..257bd5de0db 100644
--- a/deps/npm/node_modules/init-package-json/lib/init-package-json.js
+++ b/deps/npm/node_modules/init-package-json/lib/init-package-json.js
@@ -100,6 +100,16 @@ async function init (dir,
delete pkg.content.repository
}
+ // if no license was explicitly provided, don't include one
+ if (!pzData.license) {
+ delete pkg.content.license
+ }
+
+ // if no author was explicitly provided, don't include one
+ if (!pzData.author) {
+ delete pkg.content.author
+ }
+
// readJson filters out empty descriptions, but init-package-json
// traditionally leaves them alone
if (!pkg.content.description) {
diff --git a/deps/npm/node_modules/init-package-json/package.json b/deps/npm/node_modules/init-package-json/package.json
index a6c8213cf53..9bad73d1634 100644
--- a/deps/npm/node_modules/init-package-json/package.json
+++ b/deps/npm/node_modules/init-package-json/package.json
@@ -1,6 +1,6 @@
{
"name": "init-package-json",
- "version": "8.2.5",
+ "version": "9.0.0",
"main": "lib/init-package-json.js",
"scripts": {
"test": "tap",
@@ -20,21 +20,21 @@
"license": "ISC",
"description": "A node module to get your node module started",
"dependencies": {
- "@npmcli/package-json": "^7.0.0",
- "npm-package-arg": "^13.0.0",
- "promzard": "^3.0.1",
- "read": "^5.0.1",
+ "@npmcli/package-json": "^8.0.0",
+ "npm-package-arg": "^14.0.0",
+ "promzard": "^4.0.0",
+ "read": "^6.0.0",
"semver": "^7.7.2",
- "validate-npm-package-name": "^7.0.0"
+ "validate-npm-package-name": "^8.0.0"
},
"devDependencies": {
"@npmcli/config": "^10.0.0",
- "@npmcli/eslint-config": "^6.0.1",
- "@npmcli/template-oss": "4.29.0",
+ "@npmcli/eslint-config": "^7.0.0",
+ "@npmcli/template-oss": "5.1.0",
"tap": "^16.0.1"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"tap": {
"test-ignore": "fixtures/",
@@ -60,7 +60,8 @@
],
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.29.0",
- "publish": true
+ "version": "5.1.0",
+ "publish": true,
+ "updateNpm": false
}
}
diff --git a/deps/npm/node_modules/is-cidr/package.json b/deps/npm/node_modules/is-cidr/package.json
index 2aed432996a..ace65f1de99 100644
--- a/deps/npm/node_modules/is-cidr/package.json
+++ b/deps/npm/node_modules/is-cidr/package.json
@@ -1,6 +1,6 @@
{
"name": "is-cidr",
- "version": "6.0.4",
+ "version": "7.0.0",
"description": "Check if a string is an IP address in CIDR notation",
"author": "silverwind <me@silverwind.io>",
"contributors": [
@@ -8,6 +8,14 @@
],
"repository": "silverwind/is-cidr",
"license": "BSD-2-Clause",
+ "keywords": [
+ "cidr",
+ "ip",
+ "ipv4",
+ "ipv6",
+ "subnet",
+ "network"
+ ],
"type": "module",
"sideEffects": false,
"main": "./dist/index.js",
@@ -17,25 +25,25 @@
"dist"
],
"engines": {
- "node": ">=20"
+ "node": ">=22"
},
"dependencies": {
- "cidr-regex": "^5.0.4"
+ "cidr-regex": "^6.0.0"
},
"devDependencies": {
"@types/node": "25.6.0",
- "@typescript/native-preview": "7.0.0-dev.20260420.1",
+ "@typescript/native-preview": "7.0.0-dev.20260427.1",
"eslint": "10.2.1",
- "eslint-config-silverwind": "131.0.5",
+ "eslint-config-silverwind": "132.0.0",
"jest-extended": "7.0.0",
- "tsdown": "0.21.9",
- "tsdown-config-silverwind": "2.1.0",
+ "tsdown": "0.21.10",
+ "tsdown-config-silverwind": "3.0.0",
"typescript": "6.0.3",
"typescript-config-silverwind": "18.0.0",
- "updates": "17.15.5",
- "updates-config-silverwind": "2.1.0",
- "versions": "15.0.0",
- "vitest": "4.1.4",
- "vitest-config-silverwind": "11.3.0"
+ "updates": "17.16.4",
+ "updates-config-silverwind": "3.0.0",
+ "versions": "15.0.1",
+ "vitest": "4.1.5",
+ "vitest-config-silverwind": "11.3.3"
}
}
\ No newline at end of file
diff --git a/deps/npm/node_modules/json-parse-even-better-errors/lib/index.js b/deps/npm/node_modules/json-parse-even-better-errors/lib/index.js
index 3ffdaac96d2..3fd812dba3e 100644
--- a/deps/npm/node_modules/json-parse-even-better-errors/lib/index.js
+++ b/deps/npm/node_modules/json-parse-even-better-errors/lib/index.js
@@ -52,11 +52,13 @@ const parseError = (e, txt, context = 20) => {
let errIdx
if (badIndexMatch) {
errIdx = +badIndexMatch[1]
- } else /* istanbul ignore next - doesnt happen in Node 22 */ if (
+ } else /* node:coverage disable */ if (
+ // doesn't happen in Node 22+
msg.match(/^Unexpected end of JSON.*/i)
) {
errIdx = txt.length - 1
}
+ /* node:coverage enable */
if (errIdx == null) {
return makeParsedError(msg, `'${txt.slice(0, context * 2)}'`)
diff --git a/deps/npm/node_modules/json-parse-even-better-errors/package.json b/deps/npm/node_modules/json-parse-even-better-errors/package.json
index 6e696c98548..23d27149ddc 100644
--- a/deps/npm/node_modules/json-parse-even-better-errors/package.json
+++ b/deps/npm/node_modules/json-parse-even-better-errors/package.json
@@ -1,6 +1,6 @@
{
"name": "json-parse-even-better-errors",
- "version": "5.0.0",
+ "version": "6.0.0",
"description": "JSON.parse with context information on error",
"main": "lib/index.js",
"files": [
@@ -8,14 +8,16 @@
"lib/"
],
"scripts": {
- "test": "tap",
- "snap": "tap",
+ "test": "node --test './test/**/*.js'",
+ "snap": "node --test --test-update-snapshots './test/**/*.js'",
"lint": "npm run eslint",
"postlint": "template-oss-check",
"template-oss-apply": "template-oss-apply --force",
"lintfix": "npm run eslint -- --fix",
"posttest": "npm run lint",
- "eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\""
+ "eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"",
+ "test:node20": "node --test test",
+ "test:cover": "node --test --experimental-test-coverage --test-timeout=3000 --test-coverage-lines=100 --test-coverage-functions=100 --test-coverage-branches=100 './test/**/*.js'"
},
"repository": {
"type": "git",
@@ -28,23 +30,17 @@
"author": "GitHub Inc.",
"license": "MIT",
"devDependencies": {
- "@npmcli/eslint-config": "^5.0.0",
- "@npmcli/template-oss": "4.27.1",
- "tap": "^16.3.0"
- },
- "tap": {
- "check-coverage": true,
- "nyc-arg": [
- "--exclude",
- "tap-snapshots/**"
- ]
+ "@npmcli/eslint-config": "^6.0.0",
+ "@npmcli/template-oss": "5.0.0"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.27.1",
- "publish": true
+ "version": "5.0.0",
+ "publish": true,
+ "testRunner": "node:test",
+ "latestCiVersion": 24
}
}
diff --git a/deps/npm/node_modules/libnpmaccess/package.json b/deps/npm/node_modules/libnpmaccess/package.json
index 6b250a69ede..fcb3c77200c 100644
--- a/deps/npm/node_modules/libnpmaccess/package.json
+++ b/deps/npm/node_modules/libnpmaccess/package.json
@@ -1,6 +1,6 @@
{
"name": "libnpmaccess",
- "version": "10.0.3",
+ "version": "11.0.0",
"description": "programmatic library for `npm access` commands",
"author": "GitHub Inc.",
"license": "ISC",
@@ -18,7 +18,7 @@
"devDependencies": {
"@npmcli/eslint-config": "^5.0.1",
"@npmcli/mock-registry": "^1.0.0",
- "@npmcli/template-oss": "4.29.0",
+ "@npmcli/template-oss": "5.1.1",
"tap": "^16.3.8"
},
"repository": {
@@ -29,11 +29,11 @@
"bugs": "https://github.com/npm/libnpmaccess/issues",
"homepage": "https://npmjs.com/package/libnpmaccess",
"dependencies": {
- "npm-package-arg": "^13.0.0",
- "npm-registry-fetch": "^19.0.0"
+ "npm-package-arg": "^14.0.0",
+ "npm-registry-fetch": "^20.0.1"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"files": [
"bin/",
@@ -41,10 +41,14 @@
],
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.29.0",
+ "version": "5.1.1",
"content": "../../scripts/template-oss/index.js"
},
"tap": {
+ "node-arg": [
+ "--require",
+ "../../scripts/disable-agent-for-tests.js"
+ ],
"nyc-arg": [
"--exclude",
"tap-snapshots/**"
diff --git a/deps/npm/node_modules/libnpmdiff/lib/tarball.js b/deps/npm/node_modules/libnpmdiff/lib/tarball.js
index e2738b58f11..a78b3e18ee8 100644
--- a/deps/npm/node_modules/libnpmdiff/lib/tarball.js
+++ b/deps/npm/node_modules/libnpmdiff/lib/tarball.js
@@ -29,10 +29,21 @@ const tarball = (manifest, opts) => {
return nodeModulesTarball(manifest, opts)
}
- return pacote.tarball(manifest._resolved, {
- ...opts,
- Arborist,
- })
+ // pacote re-parses manifest._resolved as type=remote, so allow-remote=none
+ // would mis-fire on the tarball URL the registry just handed us. mirror
+ // arborist reify's carve-out: trust resolved tarballs for registry-typed specs.
+ const tarballOpts = { ...opts, Arborist }
+ let fromSpec
+ try {
+ fromSpec = manifest._from ? npa(manifest._from) : null
+ } catch {
+ fromSpec = null
+ }
+ if (fromSpec?.registry) {
+ tarballOpts.allowRemote = 'all'
+ }
+
+ return pacote.tarball(manifest._resolved, tarballOpts)
}
module.exports = tarball
diff --git a/deps/npm/node_modules/libnpmdiff/package.json b/deps/npm/node_modules/libnpmdiff/package.json
index 8ce3729c325..d36879f339b 100644
--- a/deps/npm/node_modules/libnpmdiff/package.json
+++ b/deps/npm/node_modules/libnpmdiff/package.json
@@ -1,6 +1,6 @@
{
"name": "libnpmdiff",
- "version": "8.1.12",
+ "version": "9.0.3",
"description": "The registry diff",
"repository": {
"type": "git",
@@ -13,7 +13,7 @@
"lib/"
],
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"keywords": [
"npm",
@@ -43,22 +43,22 @@
},
"devDependencies": {
"@npmcli/eslint-config": "^5.0.1",
- "@npmcli/template-oss": "4.29.0",
+ "@npmcli/template-oss": "5.1.1",
"tap": "^16.3.8"
},
"dependencies": {
- "@npmcli/arborist": "^9.9.1",
- "@npmcli/installed-package-contents": "^4.0.0",
+ "@npmcli/arborist": "^10.0.3",
+ "@npmcli/installed-package-contents": "^5.0.0",
"binary-extensions": "^3.0.0",
"diff": "^8.0.2",
"minimatch": "^10.0.3",
- "npm-package-arg": "^13.0.0",
- "pacote": "^21.0.2",
+ "npm-package-arg": "^14.0.0",
+ "pacote": "^22.0.0",
"tar": "^7.5.1"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.29.0",
+ "version": "5.1.1",
"content": "../../scripts/template-oss/index.js"
},
"tap": {
diff --git a/deps/npm/node_modules/libnpmexec/package.json b/deps/npm/node_modules/libnpmexec/package.json
index c76c285e56a..f7a5e16db36 100644
--- a/deps/npm/node_modules/libnpmexec/package.json
+++ b/deps/npm/node_modules/libnpmexec/package.json
@@ -1,13 +1,13 @@
{
"name": "libnpmexec",
- "version": "10.3.2",
+ "version": "11.0.3",
"files": [
"bin/",
"lib/"
],
"main": "lib/index.js",
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"description": "npm exec (npx) programmatic API",
"repository": {
@@ -44,6 +44,10 @@
},
"tap": {
"files": "test/*.js",
+ "node-arg": [
+ "--require",
+ "../../scripts/disable-agent-for-tests.js"
+ ],
"nyc-arg": [
"--exclude",
"tap-snapshots/**"
@@ -52,8 +56,8 @@
"devDependencies": {
"@npmcli/eslint-config": "^5.0.1",
"@npmcli/mock-registry": "^1.0.0",
- "@npmcli/template-oss": "4.29.0",
- "bin-links": "^6.0.0",
+ "@npmcli/template-oss": "5.1.1",
+ "bin-links": "^7.0.0",
"chalk": "^5.2.0",
"just-extend": "^6.2.0",
"just-safe-set": "^4.2.1",
@@ -61,21 +65,21 @@
},
"dependencies": {
"@gar/promise-retry": "^1.0.0",
- "@npmcli/arborist": "^9.9.1",
- "@npmcli/package-json": "^7.0.0",
- "@npmcli/run-script": "^10.0.0",
+ "@npmcli/arborist": "^10.0.3",
+ "@npmcli/package-json": "^8.0.0",
+ "@npmcli/run-script": "^11.0.0",
"ci-info": "^4.0.0",
- "npm-package-arg": "^13.0.0",
- "pacote": "^21.0.2",
- "proc-log": "^6.0.0",
- "read": "^5.0.1",
+ "npm-package-arg": "^14.0.0",
+ "pacote": "^22.0.0",
+ "proc-log": "^7.0.0",
+ "read": "^6.0.0",
"semver": "^7.3.7",
"signal-exit": "^4.1.0",
"walk-up-path": "^4.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.29.0",
+ "version": "5.1.1",
"content": "../../scripts/template-oss/index.js"
}
}
diff --git a/deps/npm/node_modules/libnpmfund/package.json b/deps/npm/node_modules/libnpmfund/package.json
index 88852421c70..7946efb2a22 100644
--- a/deps/npm/node_modules/libnpmfund/package.json
+++ b/deps/npm/node_modules/libnpmfund/package.json
@@ -1,6 +1,6 @@
{
"name": "libnpmfund",
- "version": "7.0.26",
+ "version": "8.0.3",
"main": "lib/index.js",
"files": [
"bin/",
@@ -42,18 +42,18 @@
},
"devDependencies": {
"@npmcli/eslint-config": "^5.0.1",
- "@npmcli/template-oss": "4.29.0",
+ "@npmcli/template-oss": "5.1.1",
"tap": "^16.3.8"
},
"dependencies": {
- "@npmcli/arborist": "^9.9.1"
+ "@npmcli/arborist": "^10.0.3"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.29.0",
+ "version": "5.1.1",
"content": "../../scripts/template-oss/index.js"
},
"tap": {
diff --git a/deps/npm/node_modules/libnpmorg/package.json b/deps/npm/node_modules/libnpmorg/package.json
index 0df17f3c1a1..878b1cdb0dc 100644
--- a/deps/npm/node_modules/libnpmorg/package.json
+++ b/deps/npm/node_modules/libnpmorg/package.json
@@ -1,6 +1,6 @@
{
"name": "libnpmorg",
- "version": "8.0.1",
+ "version": "9.0.0",
"description": "Programmatic api for `npm org` commands",
"author": "GitHub Inc.",
"main": "lib/index.js",
@@ -29,9 +29,9 @@
],
"devDependencies": {
"@npmcli/eslint-config": "^5.0.1",
- "@npmcli/template-oss": "4.29.0",
+ "@npmcli/template-oss": "5.1.1",
"minipass": "^7.1.1",
- "nock": "^13.3.3",
+ "nock": "^14.0.0",
"tap": "^16.3.8"
},
"repository": {
@@ -43,17 +43,21 @@
"homepage": "https://npmjs.com/package/libnpmorg",
"dependencies": {
"aproba": "^2.0.0",
- "npm-registry-fetch": "^19.0.0"
+ "npm-registry-fetch": "^20.0.1"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.29.0",
+ "version": "5.1.1",
"content": "../../scripts/template-oss/index.js"
},
"tap": {
+ "node-arg": [
+ "--require",
+ "../../scripts/disable-agent-for-tests.js"
+ ],
"nyc-arg": [
"--exclude",
"tap-snapshots/**"
diff --git a/deps/npm/node_modules/libnpmpack/lib/index.js b/deps/npm/node_modules/libnpmpack/lib/index.js
index ce6707938bb..8bf68e2a400 100644
--- a/deps/npm/node_modules/libnpmpack/lib/index.js
+++ b/deps/npm/node_modules/libnpmpack/lib/index.js
@@ -19,6 +19,42 @@ async function pack (spec = 'file:.', opts = {}) {
const manifest = await pacote.manifest(spec, { ...opts, Arborist, _isRoot: true })
+ if (spec.type === 'directory') {
+ const hasBundled = manifest.bundleDependencies?.length > 0
+ const hasOverrides = manifest.overrides
+ && typeof manifest.overrides === 'object'
+ && Object.keys(manifest.overrides).length > 0
+ if (hasBundled && hasOverrides) {
+ // Only refuse when an override rule actually applies to a package that is bundled by the root.
+ // Overrides targeting dev dependencies or any package outside the bundled tree are harmless to consumers, because consumers do not apply the publishing package's overrides.
+ // We rely on Arborist's own semantics (inBundle/inDepBundle/overridden) rather than reimplementing what npm-packlist/arborist already knows.
+ const arb = new Arborist({ path: spec.fetchSpec })
+ const tree = await arb.loadActual()
+ const offenders = new Set()
+ for (const node of tree.inventory.values()) {
+ if (node.isRoot) {
+ continue
+ }
+ // Only packages bundled by the root are at risk: nested dep-bundles are published as-is and arborist already treats them as immune to the root's overrides (see Edge#satisfiedBy).
+ if (!node.inBundle || node.inDepBundle) {
+ continue
+ }
+ if (node.overridden) {
+ offenders.add(node.name)
+ }
+ }
+ if (offenders.size) {
+ const names = [...offenders].sort()
+ const list = names.join(', ')
+ const isOne = names.length === 1
+ throw Object.assign(
+ new Error(`Cannot pack or publish: "overrides" ${isOne ? 'affects a bundled package' : 'affect bundled packages'} (${list}). Consumers do not apply your package's overrides, so the published bundle will produce invalid dependency edges. Remove ${isOne ? 'this package' : 'these packages'} from "bundledDependencies"/"bundleDependencies" or from "overrides" before publishing.`),
+ { code: 'EBUNDLEOVERRIDE', packages: names }
+ )
+ }
+ }
+ }
+
const stdio = opts.foregroundScripts ? 'inherit' : 'pipe'
if (spec.type === 'directory' && !opts.ignoreScripts) {
@@ -33,11 +69,18 @@ async function pack (spec = 'file:.', opts = {}) {
}
// packs tarball
- const tarball = await pacote.tarball(manifest._resolved, {
+ const tarballOpts = {
...opts,
Arborist,
integrity: manifest._integrity,
- })
+ }
+ // pacote re-parses manifest._resolved as type=remote, so allow-remote=none
+ // would mis-fire on the tarball URL the registry just handed us. mirror
+ // arborist reify's carve-out: trust resolved tarballs for registry-typed specs.
+ if (spec.registry) {
+ tarballOpts.allowRemote = 'all'
+ }
+ const tarball = await pacote.tarball(manifest._resolved, tarballOpts)
// check for explicit `false` so the default behavior is to skip writing to disk
if (opts.dryRun === false) {
diff --git a/deps/npm/node_modules/libnpmpack/package.json b/deps/npm/node_modules/libnpmpack/package.json
index 54c31fccd63..fd5150a7b64 100644
--- a/deps/npm/node_modules/libnpmpack/package.json
+++ b/deps/npm/node_modules/libnpmpack/package.json
@@ -1,6 +1,6 @@
{
"name": "libnpmpack",
- "version": "9.1.13",
+ "version": "10.0.3",
"description": "Programmatic API for the bits behind npm pack",
"author": "GitHub Inc.",
"main": "lib/index.js",
@@ -24,8 +24,8 @@
},
"devDependencies": {
"@npmcli/eslint-config": "^5.0.1",
- "@npmcli/template-oss": "4.29.0",
- "nock": "^13.3.3",
+ "@npmcli/template-oss": "5.1.1",
+ "nock": "^14.0.0",
"spawk": "^1.7.1",
"tap": "^16.3.8"
},
@@ -37,20 +37,24 @@
"bugs": "https://github.com/npm/libnpmpack/issues",
"homepage": "https://npmjs.com/package/libnpmpack",
"dependencies": {
- "@npmcli/arborist": "^9.9.1",
- "@npmcli/run-script": "^10.0.0",
- "npm-package-arg": "^13.0.0",
- "pacote": "^21.0.2"
+ "@npmcli/arborist": "^10.0.3",
+ "@npmcli/run-script": "^11.0.0",
+ "npm-package-arg": "^14.0.0",
+ "pacote": "^22.0.0"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.29.0",
+ "version": "5.1.1",
"content": "../../scripts/template-oss/index.js"
},
"tap": {
+ "node-arg": [
+ "--require",
+ "../../scripts/disable-agent-for-tests.js"
+ ],
"nyc-arg": [
"--exclude",
"tap-snapshots/**"
diff --git a/deps/npm/node_modules/libnpmpublish/README.md b/deps/npm/node_modules/libnpmpublish/README.md
index 4daac34feaa..897c61b7bfe 100644
--- a/deps/npm/node_modules/libnpmpublish/README.md
+++ b/deps/npm/node_modules/libnpmpublish/README.md
@@ -44,8 +44,13 @@ A couple of options of note:
defaults to `latest`.
* `opts.access` - tells the registry whether this package should be
- published as `public` or `restricted`. Only applies to scoped
- packages. Defaults to `public`.
+ published as `'public'` or `'restricted'`. May also be `null`, which
+ preserves the existing access level on already-published packages and
+ defers to the registry's default for new packages (the registry treats
+ scoped packages as `restricted` and unscoped packages as `public` by
+ default). Only `'restricted'` and `null` are meaningful for scoped
+ packages; `'restricted'` is rejected for unscoped packages. Defaults to
+ `null`.
* `opts.token` - can be passed in and will be used as the authentication
token for the registry. For other ways to pass in auth details, see the
@@ -53,11 +58,15 @@ A couple of options of note:
* `opts.provenance` - when running in a supported CI environment, will trigger
the generation of a signed provenance statement to be published alongside
- the package. Mutually exclusive with the `provenanceFile` option.
+ the package. Mutually exclusive with the `provenanceFile` option; providing
+ both will throw an `EUSAGE` error. In the npm CLI's trusted
+ publishing flows, automatic provenance generation is skipped when
+ `provenanceFile` is supplied.
* `opts.provenanceFile` - specifies the path to an externally-generated
provenance statement to be published alongside the package. Mutually
- exclusive with the `provenance` option. The specified file should be a
+ exclusive with the `provenance` option; providing both will throw an
+ `EUSAGE` error. The specified file should be a
[Sigstore Bundle](https://github.com/sigstore/protobuf-specs/blob/main/protos/sigstore_bundle.proto)
containing a [DSSE](https://github.com/secure-systems-lab/dsse)-packaged
provenance statement.
diff --git a/deps/npm/node_modules/libnpmpublish/lib/publish.js b/deps/npm/node_modules/libnpmpublish/lib/publish.js
index cfe85d2d29f..d9afc066eb4 100644
--- a/deps/npm/node_modules/libnpmpublish/lib/publish.js
+++ b/deps/npm/node_modules/libnpmpublish/lib/publish.js
@@ -20,10 +20,18 @@ Remove the 'private' field from the package.json to publish it.`),
)
}
+ // packageExtensions is root-only project policy and must never reach the registry manifest or the published tarball
+ if (manifest.packageExtensions !== undefined) {
+ throw Object.assign(
+ new Error('packageExtensions is only honored at the project root and must not be published.'),
+ { code: 'EPACKAGEEXTENSIONS' }
+ )
+ }
+
// spec is used to pick the appropriate registry/auth combo
const spec = npa.resolve(manifest.name, manifest.version)
opts = {
- access: 'public',
+ access: null,
algorithms: ['sha512'],
defaultTag: 'latest',
...opts,
@@ -87,6 +95,8 @@ const patchManifest = async (_manifest, opts) => {
)
}
manifest.version = version
+ // patchedDependencies is consumer-side state and must never be published
+ delete manifest.patchedDependencies
return manifest
}
@@ -134,6 +144,12 @@ const buildMetadata = async (registry, manifest, tarballData, spec, opts) => {
// Handle case where --provenance flag was set to true
let transparencyLogUrl
+ if (provenance === true && provenanceFile) {
+ throw Object.assign(
+ new Error('provenance and provenanceFile cannot be used together'),
+ { code: 'EUSAGE' }
+ )
+ }
if (provenance === true || provenanceFile) {
let provenanceBundle
const subject = {
diff --git a/deps/npm/node_modules/libnpmpublish/package.json b/deps/npm/node_modules/libnpmpublish/package.json
index 5b4ae66e572..27e7d1a567c 100644
--- a/deps/npm/node_modules/libnpmpublish/package.json
+++ b/deps/npm/node_modules/libnpmpublish/package.json
@@ -1,6 +1,6 @@
{
"name": "libnpmpublish",
- "version": "11.2.0",
+ "version": "12.0.1",
"description": "Programmatic API for the bits behind npm publish and unpublish",
"author": "GitHub Inc.",
"main": "lib/index.js",
@@ -27,7 +27,7 @@
"@npmcli/eslint-config": "^5.0.1",
"@npmcli/mock-globals": "^1.0.0",
"@npmcli/mock-registry": "^1.0.0",
- "@npmcli/template-oss": "4.29.0",
+ "@npmcli/template-oss": "5.1.1",
"tap": "^16.3.8"
},
"repository": {
@@ -38,24 +38,28 @@
"bugs": "https://github.com/npm/cli/issues",
"homepage": "https://npmjs.com/package/libnpmpublish",
"dependencies": {
- "@npmcli/package-json": "^7.0.0",
+ "@npmcli/package-json": "^8.0.0",
"ci-info": "^4.0.0",
- "npm-package-arg": "^13.0.0",
- "npm-registry-fetch": "^19.0.0",
- "proc-log": "^6.0.0",
+ "npm-package-arg": "^14.0.0",
+ "npm-registry-fetch": "^20.0.1",
+ "proc-log": "^7.0.0",
"semver": "^7.3.7",
- "sigstore": "^4.0.0",
- "ssri": "^13.0.0"
+ "sigstore": "^5.0.0",
+ "ssri": "^14.0.0"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.29.0",
+ "version": "5.1.1",
"content": "../../scripts/template-oss/index.js"
},
"tap": {
+ "node-arg": [
+ "--require",
+ "../../scripts/disable-agent-for-tests.js"
+ ],
"nyc-arg": [
"--exclude",
"tap-snapshots/**"
diff --git a/deps/npm/node_modules/libnpmsearch/package.json b/deps/npm/node_modules/libnpmsearch/package.json
index e17ac5ab98f..97854267213 100644
--- a/deps/npm/node_modules/libnpmsearch/package.json
+++ b/deps/npm/node_modules/libnpmsearch/package.json
@@ -1,6 +1,6 @@
{
"name": "libnpmsearch",
- "version": "9.0.1",
+ "version": "10.0.0",
"description": "Programmatic API for searching in npm and compatible registries.",
"author": "GitHub Inc.",
"main": "lib/index.js",
@@ -27,8 +27,8 @@
},
"devDependencies": {
"@npmcli/eslint-config": "^5.0.1",
- "@npmcli/template-oss": "4.29.0",
- "nock": "^13.3.3",
+ "@npmcli/template-oss": "5.1.1",
+ "nock": "^14.0.0",
"tap": "^16.3.8"
},
"repository": {
@@ -39,17 +39,21 @@
"bugs": "https://github.com/npm/libnpmsearch/issues",
"homepage": "https://npmjs.com/package/libnpmsearch",
"dependencies": {
- "npm-registry-fetch": "^19.0.0"
+ "npm-registry-fetch": "^20.0.1"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.29.0",
+ "version": "5.1.1",
"content": "../../scripts/template-oss/index.js"
},
"tap": {
+ "node-arg": [
+ "--require",
+ "../../scripts/disable-agent-for-tests.js"
+ ],
"nyc-arg": [
"--exclude",
"tap-snapshots/**"
diff --git a/deps/npm/node_modules/libnpmteam/package.json b/deps/npm/node_modules/libnpmteam/package.json
index 0531259b3e7..a2ff85cab1c 100644
--- a/deps/npm/node_modules/libnpmteam/package.json
+++ b/deps/npm/node_modules/libnpmteam/package.json
@@ -1,7 +1,7 @@
{
"name": "libnpmteam",
"description": "npm Team management APIs",
- "version": "8.0.2",
+ "version": "9.0.0",
"author": "GitHub Inc.",
"license": "ISC",
"main": "lib/index.js",
@@ -17,8 +17,8 @@
},
"devDependencies": {
"@npmcli/eslint-config": "^5.0.1",
- "@npmcli/template-oss": "4.29.0",
- "nock": "^13.3.3",
+ "@npmcli/template-oss": "5.1.1",
+ "nock": "^14.0.0",
"tap": "^16.3.8"
},
"repository": {
@@ -33,17 +33,21 @@
"homepage": "https://npmjs.com/package/libnpmteam",
"dependencies": {
"aproba": "^2.0.0",
- "npm-registry-fetch": "^19.0.0"
+ "npm-registry-fetch": "^20.0.1"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.29.0",
+ "version": "5.1.1",
"content": "../../scripts/template-oss/index.js"
},
"tap": {
+ "node-arg": [
+ "--require",
+ "../../scripts/disable-agent-for-tests.js"
+ ],
"nyc-arg": [
"--exclude",
"tap-snapshots/**"
diff --git a/deps/npm/node_modules/libnpmversion/README.md b/deps/npm/node_modules/libnpmversion/README.md
index d60a144bcc1..8f3f89e453a 100644
--- a/deps/npm/node_modules/libnpmversion/README.md
+++ b/deps/npm/node_modules/libnpmversion/README.md
@@ -39,8 +39,7 @@ npmVersion(arg, {
## Description
Run this in a package directory to bump the version and write the new data
-back to `package.json`, `package-lock.json`, and, if present,
-`npm-shrinkwrap.json`.
+back to `package.json` and `package-lock.json`.
The `newversion` argument should be a valid semver string, a valid second
argument to [semver.inc](https://github.com/npm/node-semver#functions) (one
diff --git a/deps/npm/node_modules/libnpmversion/lib/version.js b/deps/npm/node_modules/libnpmversion/lib/version.js
index bfcd8a52149..df78e06c230 100644
--- a/deps/npm/node_modules/libnpmversion/lib/version.js
+++ b/deps/npm/node_modules/libnpmversion/lib/version.js
@@ -76,21 +76,19 @@ module.exports = async (newversion, opts) => {
delete pkg._id
await writeJson(`${path}/package.json`, pkg)
- // try to update shrinkwrap, but ok if this fails
- const locks = [`${path}/package-lock.json`, `${path}/npm-shrinkwrap.json`]
- const haveLocks = []
- for (const lock of locks) {
- try {
- const sw = await readJson(lock)
- sw.version = newV
- if (sw.packages && sw.packages['']) {
- sw.packages[''].version = newV
- }
- await writeJson(lock, sw)
- haveLocks.push(lock)
- } catch {
- // ignore errors
+ // try to update the lockfile, but ok if this fails
+ const lock = `${path}/package-lock.json`
+ let lockUpdated = false
+ try {
+ const sw = await readJson(lock)
+ sw.version = newV
+ if (sw.packages && sw.packages['']) {
+ sw.packages[''].version = newV
}
+ await writeJson(lock, sw)
+ lockUpdated = true
+ } catch {
+ // ignore errors
}
if (!ignoreScripts) {
@@ -110,7 +108,7 @@ module.exports = async (newversion, opts) => {
// - git add, git commit, git tag
await git.spawn(['add', `${path}/package.json`], opts)
// sometimes people .gitignore their lockfiles
- for (const lock of haveLocks) {
+ if (lockUpdated) {
await git.spawn(['add', lock], opts).catch(() => {})
}
await commit(newV, opts)
diff --git a/deps/npm/node_modules/libnpmversion/package.json b/deps/npm/node_modules/libnpmversion/package.json
index f8be6d8fdb3..8c1e1f1fa00 100644
--- a/deps/npm/node_modules/libnpmversion/package.json
+++ b/deps/npm/node_modules/libnpmversion/package.json
@@ -1,6 +1,6 @@
{
"name": "libnpmversion",
- "version": "8.0.4",
+ "version": "9.0.0",
"main": "lib/index.js",
"files": [
"bin/",
@@ -33,23 +33,23 @@
},
"devDependencies": {
"@npmcli/eslint-config": "^5.0.1",
- "@npmcli/template-oss": "4.29.0",
+ "@npmcli/template-oss": "5.1.1",
"require-inject": "^1.4.4",
"tap": "^16.3.8"
},
"dependencies": {
- "@npmcli/git": "^7.0.0",
- "@npmcli/run-script": "^10.0.0",
- "json-parse-even-better-errors": "^5.0.0",
- "proc-log": "^6.0.0",
+ "@npmcli/git": "^8.0.0",
+ "@npmcli/run-script": "^11.0.0",
+ "json-parse-even-better-errors": "^6.0.0",
+ "proc-log": "^7.0.0",
"semver": "^7.3.7"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.29.0",
+ "version": "5.1.1",
"content": "../../scripts/template-oss/index.js"
}
}
diff --git a/deps/npm/node_modules/lru-cache/dist/commonjs/browser/index.js b/deps/npm/node_modules/lru-cache/dist/commonjs/browser/index.js
index 6b8268b0ea9..3f5cceec7ae 100644
--- a/deps/npm/node_modules/lru-cache/dist/commonjs/browser/index.js
+++ b/deps/npm/node_modules/lru-cache/dist/commonjs/browser/index.js
@@ -412,17 +412,17 @@ class LRUCache {
this.#setItemTTL = (index, ttl, start = this.#perf.now()) => {
starts[index] = ttl !== 0 ? start : 0;
ttls[index] = ttl;
- setPurgetTimer(index, ttl);
+ setPurgeTimer(index, ttl);
};
this.#updateItemAge = index => {
starts[index] = ttls[index] !== 0 ? this.#perf.now() : 0;
- setPurgetTimer(index, ttls[index]);
+ setPurgeTimer(index, ttls[index]);
};
// clear out the purge timer if we're setting TTL to 0, and
// previously had a ttl purge timer running, so it doesn't
// fire unnecessarily. Don't need to do this if we're not doing
// autopurge.
- const setPurgetTimer = !this.ttlAutopurge ?
+ const setPurgeTimer = !this.ttlAutopurge ?
() => { }
: (index, ttl) => {
if (purgeTimers?.[index]) {
@@ -433,6 +433,10 @@ class LRUCache {
const t = setTimeout(() => {
if (this.#isStale(index)) {
this.#delete(this.#keyList[index], 'expire');
+ purgeTimers[index] = undefined;
+ }
+ else {
+ setPurgeTimer(index, getRemainingTTL(index));
}
}, ttl + 1);
// unref() not supported on all platforms
@@ -482,6 +486,9 @@ class LRUCache {
if (index === undefined) {
return 0;
}
+ return getRemainingTTL(index);
+ };
+ const getRemainingTTL = (index) => {
const ttl = ttls[index];
const start = starts[index];
if (!ttl || !start) {
@@ -1621,7 +1628,7 @@ class LRUCache {
const index = this.#keyMap.get(k);
if (index !== undefined) {
if (this.#autopurgeTimers?.[index]) {
- clearTimeout(this.#autopurgeTimers?.[index]);
+ clearTimeout(this.#autopurgeTimers[index]);
this.#autopurgeTimers[index] = undefined;
}
deleted = true;
diff --git a/deps/npm/node_modules/lru-cache/dist/commonjs/browser/index.min.js b/deps/npm/node_modules/lru-cache/dist/commonjs/browser/index.min.js
index 8e424610744..d20fcc5eb89 100644
--- a/deps/npm/node_modules/lru-cache/dist/commonjs/browser/index.min.js
+++ b/deps/npm/node_modules/lru-cache/dist/commonjs/browser/index.min.js
@@ -1,2 +1,2 @@
-"use strict";var j=(c,t)=>()=>(t||c((t={exports:{}}).exports,t),t.exports);var I=j(O=>{"use strict";Object.defineProperty(O,"__esModule",{value:!0});O.tracing=O.metrics=void 0;var U={hasSubscribers:!1};O.metrics=U;O.tracing=U});var P=j(D=>{"use strict";Object.defineProperty(D,"__esModule",{value:!0});D.defaultPerf=void 0;D.defaultPerf=typeof performance=="object"&&performance&&typeof performance.now=="function"?performance:Date});Object.defineProperty(exports,"__esModule",{value:!0});exports.LRUCache=void 0;var g=I(),N=P(),x=()=>g.metrics.hasSubscribers||g.tracing.hasSubscribers,k=new Set,G=typeof process=="object"&&process?process:{},V=(c,t,e,i)=>{typeof G.emitWarning=="function"?G.emitWarning(c,t,e,i):console.error(`[${e}] ${t}: ${c}`)},B=c=>!k.has(c);var T=c=>!!c&&c===Math.floor(c)&&c>0&&isFinite(c),H=c=>T(c)?c<=Math.pow(2,8)?Uint8Array:c<=Math.pow(2,16)?Uint16Array:c<=Math.pow(2,32)?Uint32Array:c<=Number.MAX_SAFE_INTEGER?W:null:null,W=class extends Array{constructor(t){super(t),this.fill(0)}},C=class c{heap;length;static#o=!1;static create(t){let e=H(t);if(!e)return[];c.#o=!0;let i=new c(t,e);return c.#o=!1,i}constructor(t,e){if(!c.#o)throw new TypeError("instantiate Stack using Stack.create(n)");this.heap=new e(t),this.length=0}push(t){this.heap[this.length++]=t}pop(){return this.heap[--this.length]}},L=class c{#o;#c;#m;#W;#S;#M;#j;#w;get perf(){return this.#w}ttl;ttlResolution;ttlAutopurge;updateAgeOnGet;updateAgeOnHas;allowStale;noDisposeOnSet;noUpdateTTL;maxEntrySize;sizeCalculation;noDeleteOnFetchRejection;noDeleteOnStaleGet;allowStaleOnFetchAbort;allowStaleOnFetchRejection;ignoreFetchAbort;backgroundFetchSize;#n;#b;#s;#i;#t;#l;#u;#a;#h;#y;#r;#_;#F;#d;#g;#T;#U;#f;#D;static unsafeExposeInternals(t){return{starts:t.#F,ttls:t.#d,autopurgeTimers:t.#g,sizes:t.#_,keyMap:t.#s,keyList:t.#i,valList:t.#t,next:t.#l,prev:t.#u,get head(){return t.#a},get tail(){return t.#h},free:t.#y,isBackgroundFetch:e=>t.#e(e),backgroundFetch:(e,i,s,n)=>t.#G(e,i,s,n),moveToTail:e=>t.#L(e),indexes:e=>t.#A(e),rindexes:e=>t.#z(e),isStale:e=>t.#p(e)}}get max(){return this.#o}get maxSize(){return this.#c}get calculatedSize(){return this.#b}get size(){return this.#n}get fetchMethod(){return this.#M}get memoMethod(){return this.#j}get dispose(){return this.#m}get onInsert(){return this.#W}get disposeAfter(){return this.#S}constructor(t){let{max:e=0,ttl:i,ttlResolution:s=1,ttlAutopurge:n,updateAgeOnGet:r,updateAgeOnHas:h,allowStale:a,dispose:o,onInsert:d,disposeAfter:y,noDisposeOnSet:_,noUpdateTTL:u,maxSize:p=0,maxEntrySize:f=0,sizeCalculation:b,fetchMethod:l,memoMethod:S,noDeleteOnFetchRejection:F,noDeleteOnStaleGet:w,allowStaleOnFetchRejection:m,allowStaleOnFetchAbort:A,ignoreFetchAbort:z,backgroundFetchSize:M=1,perf:v}=t;if(this.backgroundFetchSize=M,v!==void 0&&typeof v?.now!="function")throw new TypeError("perf option must have a now() method if specified");if(this.#w=v??N.defaultPerf,e!==0&&!T(e))throw new TypeError("max option must be a nonnegative integer");let E=e?H(e):Array;if(!E)throw new Error("invalid max value: "+e);if(this.#o=e,this.#c=p,this.maxEntrySize=f||this.#c,this.sizeCalculation=b,this.sizeCalculation){if(!this.#c&&!this.maxEntrySize)throw new TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");if(typeof this.sizeCalculation!="function")throw new TypeError("sizeCalculation set to non-function")}if(S!==void 0&&typeof S!="function")throw new TypeError("memoMethod must be a function if defined");if(this.#j=S,l!==void 0&&typeof l!="function")throw new TypeError("fetchMethod must be a function if specified");if(this.#M=l,this.#U=!!l,this.#s=new Map,this.#i=Array.from({length:e}).fill(void 0),this.#t=Array.from({length:e}).fill(void 0),this.#l=new E(e),this.#u=new E(e),this.#a=0,this.#h=0,this.#y=C.create(e),this.#n=0,this.#b=0,typeof o=="function"&&(this.#m=o),typeof d=="function"&&(this.#W=d),typeof y=="function"?(this.#S=y,this.#r=[]):(this.#S=void 0,this.#r=void 0),this.#T=!!this.#m,this.#D=!!this.#W,this.#f=!!this.#S,this.noDisposeOnSet=!!_,this.noUpdateTTL=!!u,this.noDeleteOnFetchRejection=!!F,this.allowStaleOnFetchRejection=!!m,this.allowStaleOnFetchAbort=!!A,this.ignoreFetchAbort=!!z,this.maxEntrySize!==0){if(this.#c!==0&&!T(this.#c))throw new TypeError("maxSize must be a positive integer if specified");if(!T(this.maxEntrySize))throw new TypeError("maxEntrySize must be a positive integer if specified");this.#X()}if(this.allowStale=!!a,this.noDeleteOnStaleGet=!!w,this.updateAgeOnGet=!!r,this.updateAgeOnHas=!!h,this.ttlResolution=T(s)||s===0?s:1,this.ttlAutopurge=!!n,this.ttl=i||0,this.ttl){if(!T(this.ttl))throw new TypeError("ttl must be a positive integer if specified");this.#k()}if(this.#o===0&&this.ttl===0&&this.#c===0)throw new TypeError("At least one of max, maxSize, or ttl is required");if(!this.ttlAutopurge&&!this.#o&&!this.#c){let R="LRU_CACHE_UNBOUNDED";B(R)&&(k.add(R),V("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.","UnboundedCacheWarning",R,c))}}getRemainingTTL(t){return this.#s.has(t)?1/0:0}#k(){let t=new W(this.#o),e=new W(this.#o);this.#d=t,this.#F=e;let i=this.ttlAutopurge?Array.from({length:this.#o}):void 0;this.#g=i,this.#H=(h,a,o=this.#w.now())=>{e[h]=a!==0?o:0,t[h]=a,s(h,a)},this.#R=h=>{e[h]=t[h]!==0?this.#w.now():0,s(h,t[h])};let s=this.ttlAutopurge?(h,a)=>{if(i?.[h]&&(clearTimeout(i[h]),i[h]=void 0),a&&a!==0&&i){let o=setTimeout(()=>{this.#p(h)&&this.#v(this.#i[h],"expire")},a+1);o.unref&&o.unref(),i[h]=o}}:()=>{};this.#E=(h,a)=>{if(t[a]){let o=t[a],d=e[a];if(!o||!d)return;h.ttl=o,h.start=d,h.now=n||r();let y=h.now-d;h.remainingTTL=o-y}};let n=0,r=()=>{let h=this.#w.now();if(this.ttlResolution>0){n=h;let a=setTimeout(()=>n=0,this.ttlResolution);a.unref&&a.unref()}return h};this.getRemainingTTL=h=>{let a=this.#s.get(h);if(a===void 0)return 0;let o=t[a],d=e[a];if(!o||!d)return 1/0;let y=(n||r())-d;return o-y},this.#p=h=>{let a=e[h],o=t[h];return!!o&&!!a&&(n||r())-a>o}}#R=()=>{};#E=()=>{};#H=()=>{};#p=()=>!1;#X(){let t=new W(this.#o);this.#b=0,this.#_=t,this.#x=e=>{this.#b-=t[e],t[e]=0},this.#N=(e,i,s,n)=>{if(!T(s)){if(this.#e(i))return this.backgroundFetchSize;if(n){if(typeof n!="function")throw new TypeError("sizeCalculation must be a function");if(s=n(i,e),!T(s))throw new TypeError("sizeCalculation return invalid (expect positive integer)")}else throw new TypeError("invalid size value (must be positive integer). When maxSize or maxEntrySize is used, sizeCalculation or size must be set.")}return s},this.#I=(e,i,s)=>{if(t[e]=i,this.#c){let n=this.#c-t[e];for(;this.#b>n;)this.#P(!0)}this.#b+=t[e],s&&(s.entrySize=i,s.totalCalculatedSize=this.#b)}}#x=t=>{};#I=(t,e,i)=>{};#N=(t,e,i,s)=>{if(i||s)throw new TypeError("cannot set size without setting maxSize or maxEntrySize on cache");return 0};*#A({allowStale:t=this.allowStale}={}){if(this.#n)for(let e=this.#h;this.#V(e)&&((t||!this.#p(e))&&(yield e),e!==this.#a);)e=this.#u[e]}*#z({allowStale:t=this.allowStale}={}){if(this.#n)for(let e=this.#a;this.#V(e)&&((t||!this.#p(e))&&(yield e),e!==this.#h);)e=this.#l[e]}#V(t){return t!==void 0&&this.#s.get(this.#i[t])===t}*entries(){for(let t of this.#A())this.#t[t]!==void 0&&this.#i[t]!==void 0&&!this.#e(this.#t[t])&&(yield[this.#i[t],this.#t[t]])}*rentries(){for(let t of this.#z())this.#t[t]!==void 0&&this.#i[t]!==void 0&&!this.#e(this.#t[t])&&(yield[this.#i[t],this.#t[t]])}*keys(){for(let t of this.#A()){let e=this.#i[t];e!==void 0&&!this.#e(this.#t[t])&&(yield e)}}*rkeys(){for(let t of this.#z()){let e=this.#i[t];e!==void 0&&!this.#e(this.#t[t])&&(yield e)}}*values(){for(let t of this.#A())this.#t[t]!==void 0&&!this.#e(this.#t[t])&&(yield this.#t[t])}*rvalues(){for(let t of this.#z())this.#t[t]!==void 0&&!this.#e(this.#t[t])&&(yield this.#t[t])}[Symbol.iterator](){return this.entries()}[Symbol.toStringTag]="LRUCache";find(t,e={}){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;if(n!==void 0&&t(n,this.#i[i],this))return this.#C(this.#i[i],e)}}forEach(t,e=this){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&t.call(e,n,this.#i[i],this)}}rforEach(t,e=this){for(let i of this.#z()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&t.call(e,n,this.#i[i],this)}}purgeStale(){let t=!1;for(let e of this.#z({allowStale:!0}))this.#p(e)&&(this.#v(this.#i[e],"expire"),t=!0);return t}info(t){let e=this.#s.get(t);if(e===void 0)return;let i=this.#t[e],s=this.#e(i)?i.__staleWhileFetching:i;if(s===void 0)return;let n={value:s};if(this.#d&&this.#F){let r=this.#d[e],h=this.#F[e];if(r&&h){let a=r-(this.#w.now()-h);n.ttl=a,n.start=Date.now()}}return this.#_&&(n.size=this.#_[e]),n}dump(){let t=[];for(let e of this.#A({allowStale:!0})){let i=this.#i[e],s=this.#t[e],n=this.#e(s)?s.__staleWhileFetching:s;if(n===void 0||i===void 0)continue;let r={value:n};if(this.#d&&this.#F){r.ttl=this.#d[e];let h=this.#w.now()-this.#F[e];r.start=Math.floor(Date.now()-h)}this.#_&&(r.size=this.#_[e]),t.unshift([i,r])}return t}load(t){this.clear();for(let[e,i]of t){if(i.start){let s=Date.now()-i.start;i.start=this.#w.now()-s}this.#O(e,i.value,i)}}set(t,e,i={}){let{status:s=g.metrics.hasSubscribers?{}:void 0}=i;i.status=s,s&&(s.op="set",s.key=t,e!==void 0&&(s.value=e),s.cache=this);let n=this.#O(t,e,i);return s&&g.metrics.hasSubscribers&&g.metrics.publish(s),n}#O(t,e,i,s){let{ttl:n=this.ttl,start:r,noDisposeOnSet:h=this.noDisposeOnSet,sizeCalculation:a=this.sizeCalculation,status:o}=i,d=this.#e(e);if(e===void 0)return o&&(o.set="deleted"),this.delete(t),this;let{noUpdateTTL:y=this.noUpdateTTL}=i;o&&!d&&(o.value=e);let _=this.#N(t,e,i.size||0,a,o);if(this.maxEntrySize&&_>this.maxEntrySize)return this.#v(t,"set"),o&&(o.set="miss",o.maxEntrySizeExceeded=!0),this;let u=this.#n===0?void 0:this.#s.get(t);if(u===void 0)u=this.#n===0?this.#h:this.#y.length!==0?this.#y.pop():this.#n===this.#o?this.#P(!1):this.#n,this.#i[u]=t,this.#t[u]=e,this.#s.set(t,u),this.#l[this.#h]=u,this.#u[u]=this.#h,this.#h=u,this.#n++,this.#I(u,_,o),o&&(o.set="add"),y=!1,this.#D&&!d&&this.#W?.(e,t,"add");else{this.#L(u);let p=this.#t[u];if(e!==p){if(!h)if(this.#e(p)){p!==s&&p.__abortController.abort(new Error("replaced"));let{__staleWhileFetching:f}=p;f!==void 0&&f!==e&&(this.#T&&this.#m?.(f,t,"set"),this.#f&&this.#r?.push([f,t,"set"]))}else this.#T&&this.#m?.(p,t,"set"),this.#f&&this.#r?.push([p,t,"set"]);if(this.#x(u),this.#I(u,_,o),this.#t[u]=e,!d){let f=p&&this.#e(p)?p.__staleWhileFetching:p,b=f===void 0?"add":e!==f?"replace":"update";o&&(o.set=b,f!==void 0&&(o.oldValue=f)),this.#D&&this.onInsert?.(e,t,b)}}else d||(o&&(o.set="update"),this.#D&&this.onInsert?.(e,t,"update"))}if(n!==0&&!this.#d&&this.#k(),this.#d&&(y||this.#H(u,n,r),o&&this.#E(o,u)),!h&&this.#f&&this.#r){let p=this.#r,f;for(;f=p?.shift();)this.#S?.(...f)}return this}pop(){try{for(;this.#n;){let t=this.#t[this.#a];if(this.#P(!0),this.#e(t)){if(t.__staleWhileFetching)return t.__staleWhileFetching}else if(t!==void 0)return t}}finally{if(this.#f&&this.#r){let t=this.#r,e;for(;e=t?.shift();)this.#S?.(...e)}}}#P(t){let e=this.#a,i=this.#i[e],s=this.#t[e],n=this.#e(s);n&&s.__abortController.abort(new Error("evicted"));let r=n?s.__staleWhileFetching:s;return(this.#T||this.#f)&&r!==void 0&&(this.#T&&this.#m?.(r,i,"evict"),this.#f&&this.#r?.push([r,i,"evict"])),this.#x(e),this.#g?.[e]&&(clearTimeout(this.#g[e]),this.#g[e]=void 0),t&&(this.#i[e]=void 0,this.#t[e]=void 0,this.#y.push(e)),this.#n===1?(this.#a=this.#h=0,this.#y.length=0):this.#a=this.#l[e],this.#s.delete(i),this.#n--,e}has(t,e={}){let{status:i=g.metrics.hasSubscribers?{}:void 0}=e;e.status=i,i&&(i.op="has",i.key=t,i.cache=this);let s=this.#Y(t,e);return g.metrics.hasSubscribers&&g.metrics.publish(i),s}#Y(t,e={}){let{updateAgeOnHas:i=this.updateAgeOnHas,status:s}=e,n=this.#s.get(t);if(n!==void 0){let r=this.#t[n];if(this.#e(r)&&r.__staleWhileFetching===void 0)return!1;if(this.#p(n))s&&(s.has="stale",this.#E(s,n));else return i&&this.#R(n),s&&(s.has="hit",this.#E(s,n)),!0}else s&&(s.has="miss");return!1}peek(t,e={}){let{status:i=x()?{}:void 0}=e;i&&(i.op="peek",i.key=t,i.cache=this),e.status=i;let s=this.#J(t,e);return g.metrics.hasSubscribers&&g.metrics.publish(i),s}#J(t,e){let{status:i,allowStale:s=this.allowStale}=e,n=this.#s.get(t);if(n===void 0||!s&&this.#p(n)){i&&(i.peek=n===void 0?"miss":"stale");return}let r=this.#t[n],h=this.#e(r)?r.__staleWhileFetching:r;return i&&(h!==void 0?(i.peek="hit",i.value=h):i.peek="miss"),h}#G(t,e,i,s){let n=e===void 0?void 0:this.#t[e];if(this.#e(n))return n;let r=new AbortController,{signal:h}=i;h?.addEventListener("abort",()=>r.abort(h.reason),{signal:r.signal});let a={signal:r.signal,options:i,context:s},o=(f,b=!1)=>{let{aborted:l}=r.signal,S=i.ignoreFetchAbort&&f!==void 0,F=i.ignoreFetchAbort||!!(i.allowStaleOnFetchAbort&&f!==void 0);if(i.status&&(l&&!b?(i.status.fetchAborted=!0,i.status.fetchError=r.signal.reason,S&&(i.status.fetchAbortIgnored=!0)):i.status.fetchResolved=!0),l&&!S&&!b)return y(r.signal.reason,F);let w=u,m=this.#t[e];return(m===u||m===void 0&&S&&b)&&(f===void 0?w.__staleWhileFetching!==void 0?this.#t[e]=w.__staleWhileFetching:this.#v(t,"fetch"):(i.status&&(i.status.fetchUpdated=!0),this.#O(t,f,a.options,w))),f},d=f=>(i.status&&(i.status.fetchRejected=!0,i.status.fetchError=f),y(f,!1)),y=(f,b)=>{let{aborted:l}=r.signal,S=l&&i.allowStaleOnFetchAbort,F=S||i.allowStaleOnFetchRejection,w=F||i.noDeleteOnFetchRejection,m=u;if(this.#t[e]===u&&(!w||!b&&m.__staleWhileFetching===void 0?this.#v(t,"fetch"):S||(this.#t[e]=m.__staleWhileFetching)),F)return i.status&&m.__staleWhileFetching!==void 0&&(i.status.returnedStale=!0),m.__staleWhileFetching;if(m.__returned===m)throw f},_=(f,b)=>{let l=this.#M?.(t,n,a);r.signal.addEventListener("abort",()=>{(!i.ignoreFetchAbort||i.allowStaleOnFetchAbort)&&(f(void 0),i.allowStaleOnFetchAbort&&(f=S=>o(S,!0)))}),l&&l instanceof Promise?l.then(S=>f(S===void 0?void 0:S),b):l!==void 0&&f(l)};i.status&&(i.status.fetchDispatched=!0);let u=new Promise(_).then(o,d),p=Object.assign(u,{__abortController:r,__staleWhileFetching:n,__returned:void 0});return e===void 0?(this.#O(t,p,{...a.options,status:void 0}),e=this.#s.get(t)):this.#t[e]=p,p}#e(t){if(!this.#U)return!1;let e=t;return!!e&&e instanceof Promise&&e.hasOwnProperty("__staleWhileFetching")&&e.__abortController instanceof AbortController}fetch(t,e={}){let i=g.tracing.hasSubscribers,{status:s=x()?{}:void 0}=e;e.status=s,s&&e.context&&(s.context=e.context);let n=this.#B(t,e);return s&&i&&(s.trace=!0,g.tracing.tracePromise(()=>n,s).catch(()=>{})),n}async#B(t,e={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,ttl:r=this.ttl,noDisposeOnSet:h=this.noDisposeOnSet,size:a=0,sizeCalculation:o=this.sizeCalculation,noUpdateTTL:d=this.noUpdateTTL,noDeleteOnFetchRejection:y=this.noDeleteOnFetchRejection,allowStaleOnFetchRejection:_=this.allowStaleOnFetchRejection,ignoreFetchAbort:u=this.ignoreFetchAbort,allowStaleOnFetchAbort:p=this.allowStaleOnFetchAbort,context:f,forceRefresh:b=!1,status:l,signal:S}=e;if(l&&(l.op="fetch",l.key=t,b&&(l.forceRefresh=!0),l.cache=this),!this.#U)return l&&(l.fetch="get"),this.#C(t,{allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,status:l});let F={allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,ttl:r,noDisposeOnSet:h,size:a,sizeCalculation:o,noUpdateTTL:d,noDeleteOnFetchRejection:y,allowStaleOnFetchRejection:_,allowStaleOnFetchAbort:p,ignoreFetchAbort:u,status:l,signal:S},w=this.#s.get(t);if(w===void 0){l&&(l.fetch="miss");let m=this.#G(t,w,F,f);return m.__returned=m}else{let m=this.#t[w];if(this.#e(m)){let E=i&&m.__staleWhileFetching!==void 0;return l&&(l.fetch="inflight",E&&(l.returnedStale=!0)),E?m.__staleWhileFetching:m.__returned=m}let A=this.#p(w);if(!b&&!A)return l&&(l.fetch="hit"),this.#L(w),s&&this.#R(w),l&&this.#E(l,w),m;let z=this.#G(t,w,F,f),v=z.__staleWhileFetching!==void 0&&i;return l&&(l.fetch=A?"stale":"refresh",v&&A&&(l.returnedStale=!0)),v?z.__staleWhileFetching:z.__returned=z}}forceFetch(t,e={}){let i=g.tracing.hasSubscribers,{status:s=x()?{}:void 0}=e;e.status=s,s&&e.context&&(s.context=e.context);let n=this.#K(t,e);return s&&i&&(s.trace=!0,g.tracing.tracePromise(()=>n,s).catch(()=>{})),n}async#K(t,e={}){let i=await this.#B(t,e);if(i===void 0)throw new Error("fetch() returned undefined");return i}memo(t,e={}){let{status:i=g.metrics.hasSubscribers?{}:void 0}=e;e.status=i,i&&(i.op="memo",i.key=t,e.context&&(i.context=e.context),i.cache=this);let s=this.#Q(t,e);return i&&(i.value=s),g.metrics.hasSubscribers&&g.metrics.publish(i),s}#Q(t,e={}){let i=this.#j;if(!i)throw new Error("no memoMethod provided to constructor");let{context:s,status:n,forceRefresh:r,...h}=e;n&&r&&(n.forceRefresh=!0);let a=this.#C(t,h),o=r||a===void 0;if(n&&(n.memo=o?"miss":"hit",o||(n.value=a)),!o)return a;let d=i(t,a,{options:h,context:s});return n&&(n.value=d),this.#O(t,d,h),d}get(t,e={}){let{status:i=g.metrics.hasSubscribers?{}:void 0}=e;e.status=i,i&&(i.op="get",i.key=t,i.cache=this);let s=this.#C(t,e);return i&&(s!==void 0&&(i.value=s),g.metrics.hasSubscribers&&g.metrics.publish(i)),s}#C(t,e={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,status:r}=e,h=this.#s.get(t);if(h===void 0){r&&(r.get="miss");return}let a=this.#t[h],o=this.#e(a);return r&&this.#E(r,h),this.#p(h)?o?(r&&(r.get="stale-fetching"),i&&a.__staleWhileFetching!==void 0?(r&&(r.returnedStale=!0),a.__staleWhileFetching):void 0):(n||this.#v(t,"expire"),r&&(r.get="stale"),i?(r&&(r.returnedStale=!0),a):void 0):(r&&(r.get=o?"fetching":"hit"),this.#L(h),s&&this.#R(h),o?a.__staleWhileFetching:a)}#q(t,e){this.#u[e]=t,this.#l[t]=e}#L(t){t!==this.#h&&(t===this.#a?this.#a=this.#l[t]:this.#q(this.#u[t],this.#l[t]),this.#q(this.#h,t),this.#h=t)}delete(t){return this.#v(t,"delete")}#v(t,e){g.metrics.hasSubscribers&&g.metrics.publish({op:"delete",delete:e,key:t,cache:this});let i=!1;if(this.#n!==0){let s=this.#s.get(t);if(s!==void 0)if(this.#g?.[s]&&(clearTimeout(this.#g?.[s]),this.#g[s]=void 0),i=!0,this.#n===1)this.#$(e);else{this.#x(s);let n=this.#t[s];if(this.#e(n)?n.__abortController.abort(new Error("deleted")):(this.#T||this.#f)&&(this.#T&&this.#m?.(n,t,e),this.#f&&this.#r?.push([n,t,e])),this.#s.delete(t),this.#i[s]=void 0,this.#t[s]=void 0,s===this.#h)this.#h=this.#u[s];else if(s===this.#a)this.#a=this.#l[s];else{let r=this.#u[s];this.#l[r]=this.#l[s];let h=this.#l[s];this.#u[h]=this.#u[s]}this.#n--,this.#y.push(s)}}if(this.#f&&this.#r?.length){let s=this.#r,n;for(;n=s?.shift();)this.#S?.(...n)}return i}clear(){return this.#$("delete")}#$(t){for(let e of this.#z({allowStale:!0})){let i=this.#t[e];if(this.#e(i))i.__abortController.abort(new Error("deleted"));else{let s=this.#i[e];this.#T&&this.#m?.(i,s,t),this.#f&&this.#r?.push([i,s,t])}}if(this.#s.clear(),this.#t.fill(void 0),this.#i.fill(void 0),this.#d&&this.#F){this.#d.fill(0),this.#F.fill(0);for(let e of this.#g??[])e!==void 0&&clearTimeout(e);this.#g?.fill(void 0)}if(this.#_&&this.#_.fill(0),this.#a=0,this.#h=0,this.#y.length=0,this.#b=0,this.#n=0,this.#f&&this.#r){let e=this.#r,i;for(;i=e?.shift();)this.#S?.(...i)}}};exports.LRUCache=L;
+"use strict";var j=(u,t)=>()=>(t||u((t={exports:{}}).exports,t),t.exports);var I=j(O=>{"use strict";Object.defineProperty(O,"__esModule",{value:!0});O.tracing=O.metrics=void 0;var U={hasSubscribers:!1};O.metrics=U;O.tracing=U});var P=j(R=>{"use strict";Object.defineProperty(R,"__esModule",{value:!0});R.defaultPerf=void 0;R.defaultPerf=typeof performance=="object"&&performance&&typeof performance.now=="function"?performance:Date});Object.defineProperty(exports,"__esModule",{value:!0});exports.LRUCache=void 0;var g=I(),N=P(),C=()=>g.metrics.hasSubscribers||g.tracing.hasSubscribers,k=new Set,G=typeof process=="object"&&process?process:{},V=(u,t,e,i)=>{typeof G.emitWarning=="function"?G.emitWarning(u,t,e,i):console.error(`[${e}] ${t}: ${u}`)},B=u=>!k.has(u);var T=u=>!!u&&u===Math.floor(u)&&u>0&&isFinite(u),H=u=>T(u)?u<=Math.pow(2,8)?Uint8Array:u<=Math.pow(2,16)?Uint16Array:u<=Math.pow(2,32)?Uint32Array:u<=Number.MAX_SAFE_INTEGER?W:null:null,W=class extends Array{constructor(t){super(t),this.fill(0)}},L=class u{heap;length;static#o=!1;static create(t){let e=H(t);if(!e)return[];u.#o=!0;let i=new u(t,e);return u.#o=!1,i}constructor(t,e){if(!u.#o)throw new TypeError("instantiate Stack using Stack.create(n)");this.heap=new e(t),this.length=0}push(t){this.heap[this.length++]=t}pop(){return this.heap[--this.length]}},M=class u{#o;#c;#m;#W;#S;#x;#j;#w;get perf(){return this.#w}ttl;ttlResolution;ttlAutopurge;updateAgeOnGet;updateAgeOnHas;allowStale;noDisposeOnSet;noUpdateTTL;maxEntrySize;sizeCalculation;noDeleteOnFetchRejection;noDeleteOnStaleGet;allowStaleOnFetchAbort;allowStaleOnFetchRejection;ignoreFetchAbort;backgroundFetchSize;#n;#b;#s;#i;#t;#l;#u;#a;#h;#y;#r;#_;#F;#d;#g;#T;#U;#f;#R;static unsafeExposeInternals(t){return{starts:t.#F,ttls:t.#d,autopurgeTimers:t.#g,sizes:t.#_,keyMap:t.#s,keyList:t.#i,valList:t.#t,next:t.#l,prev:t.#u,get head(){return t.#a},get tail(){return t.#h},free:t.#y,isBackgroundFetch:e=>t.#e(e),backgroundFetch:(e,i,s,n)=>t.#G(e,i,s,n),moveToTail:e=>t.#M(e),indexes:e=>t.#A(e),rindexes:e=>t.#z(e),isStale:e=>t.#p(e)}}get max(){return this.#o}get maxSize(){return this.#c}get calculatedSize(){return this.#b}get size(){return this.#n}get fetchMethod(){return this.#x}get memoMethod(){return this.#j}get dispose(){return this.#m}get onInsert(){return this.#W}get disposeAfter(){return this.#S}constructor(t){let{max:e=0,ttl:i,ttlResolution:s=1,ttlAutopurge:n,updateAgeOnGet:o,updateAgeOnHas:l,allowStale:h,dispose:r,onInsert:c,disposeAfter:w,noDisposeOnSet:_,noUpdateTTL:d,maxSize:p=0,maxEntrySize:f=0,sizeCalculation:y,fetchMethod:a,memoMethod:S,noDeleteOnFetchRejection:F,noDeleteOnStaleGet:b,allowStaleOnFetchRejection:m,allowStaleOnFetchAbort:A,ignoreFetchAbort:z,backgroundFetchSize:x=1,perf:v}=t;if(this.backgroundFetchSize=x,v!==void 0&&typeof v?.now!="function")throw new TypeError("perf option must have a now() method if specified");if(this.#w=v??N.defaultPerf,e!==0&&!T(e))throw new TypeError("max option must be a nonnegative integer");let E=e?H(e):Array;if(!E)throw new Error("invalid max value: "+e);if(this.#o=e,this.#c=p,this.maxEntrySize=f||this.#c,this.sizeCalculation=y,this.sizeCalculation){if(!this.#c&&!this.maxEntrySize)throw new TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");if(typeof this.sizeCalculation!="function")throw new TypeError("sizeCalculation set to non-function")}if(S!==void 0&&typeof S!="function")throw new TypeError("memoMethod must be a function if defined");if(this.#j=S,a!==void 0&&typeof a!="function")throw new TypeError("fetchMethod must be a function if specified");if(this.#x=a,this.#U=!!a,this.#s=new Map,this.#i=Array.from({length:e}).fill(void 0),this.#t=Array.from({length:e}).fill(void 0),this.#l=new E(e),this.#u=new E(e),this.#a=0,this.#h=0,this.#y=L.create(e),this.#n=0,this.#b=0,typeof r=="function"&&(this.#m=r),typeof c=="function"&&(this.#W=c),typeof w=="function"?(this.#S=w,this.#r=[]):(this.#S=void 0,this.#r=void 0),this.#T=!!this.#m,this.#R=!!this.#W,this.#f=!!this.#S,this.noDisposeOnSet=!!_,this.noUpdateTTL=!!d,this.noDeleteOnFetchRejection=!!F,this.allowStaleOnFetchRejection=!!m,this.allowStaleOnFetchAbort=!!A,this.ignoreFetchAbort=!!z,this.maxEntrySize!==0){if(this.#c!==0&&!T(this.#c))throw new TypeError("maxSize must be a positive integer if specified");if(!T(this.maxEntrySize))throw new TypeError("maxEntrySize must be a positive integer if specified");this.#X()}if(this.allowStale=!!h,this.noDeleteOnStaleGet=!!b,this.updateAgeOnGet=!!o,this.updateAgeOnHas=!!l,this.ttlResolution=T(s)||s===0?s:1,this.ttlAutopurge=!!n,this.ttl=i||0,this.ttl){if(!T(this.ttl))throw new TypeError("ttl must be a positive integer if specified");this.#k()}if(this.#o===0&&this.ttl===0&&this.#c===0)throw new TypeError("At least one of max, maxSize, or ttl is required");if(!this.ttlAutopurge&&!this.#o&&!this.#c){let D="LRU_CACHE_UNBOUNDED";B(D)&&(k.add(D),V("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.","UnboundedCacheWarning",D,u))}}getRemainingTTL(t){return this.#s.has(t)?1/0:0}#k(){let t=new W(this.#o),e=new W(this.#o);this.#d=t,this.#F=e;let i=this.ttlAutopurge?Array.from({length:this.#o}):void 0;this.#g=i,this.#H=(h,r,c=this.#w.now())=>{e[h]=r!==0?c:0,t[h]=r,s(h,r)},this.#D=h=>{e[h]=t[h]!==0?this.#w.now():0,s(h,t[h])};let s=this.ttlAutopurge?(h,r)=>{if(i?.[h]&&(clearTimeout(i[h]),i[h]=void 0),r&&r!==0&&i){let c=setTimeout(()=>{this.#p(h)?(this.#v(this.#i[h],"expire"),i[h]=void 0):s(h,l(h))},r+1);c.unref&&c.unref(),i[h]=c}}:()=>{};this.#E=(h,r)=>{if(t[r]){let c=t[r],w=e[r];if(!c||!w)return;h.ttl=c,h.start=w,h.now=n||o();let _=h.now-w;h.remainingTTL=c-_}};let n=0,o=()=>{let h=this.#w.now();if(this.ttlResolution>0){n=h;let r=setTimeout(()=>n=0,this.ttlResolution);r.unref&&r.unref()}return h};this.getRemainingTTL=h=>{let r=this.#s.get(h);return r===void 0?0:l(r)};let l=h=>{let r=t[h],c=e[h];if(!r||!c)return 1/0;let w=(n||o())-c;return r-w};this.#p=h=>{let r=e[h],c=t[h];return!!c&&!!r&&(n||o())-r>c}}#D=()=>{};#E=()=>{};#H=()=>{};#p=()=>!1;#X(){let t=new W(this.#o);this.#b=0,this.#_=t,this.#C=e=>{this.#b-=t[e],t[e]=0},this.#N=(e,i,s,n)=>{if(!T(s)){if(this.#e(i))return this.backgroundFetchSize;if(n){if(typeof n!="function")throw new TypeError("sizeCalculation must be a function");if(s=n(i,e),!T(s))throw new TypeError("sizeCalculation return invalid (expect positive integer)")}else throw new TypeError("invalid size value (must be positive integer). When maxSize or maxEntrySize is used, sizeCalculation or size must be set.")}return s},this.#I=(e,i,s)=>{if(t[e]=i,this.#c){let n=this.#c-t[e];for(;this.#b>n;)this.#P(!0)}this.#b+=t[e],s&&(s.entrySize=i,s.totalCalculatedSize=this.#b)}}#C=t=>{};#I=(t,e,i)=>{};#N=(t,e,i,s)=>{if(i||s)throw new TypeError("cannot set size without setting maxSize or maxEntrySize on cache");return 0};*#A({allowStale:t=this.allowStale}={}){if(this.#n)for(let e=this.#h;this.#V(e)&&((t||!this.#p(e))&&(yield e),e!==this.#a);)e=this.#u[e]}*#z({allowStale:t=this.allowStale}={}){if(this.#n)for(let e=this.#a;this.#V(e)&&((t||!this.#p(e))&&(yield e),e!==this.#h);)e=this.#l[e]}#V(t){return t!==void 0&&this.#s.get(this.#i[t])===t}*entries(){for(let t of this.#A())this.#t[t]!==void 0&&this.#i[t]!==void 0&&!this.#e(this.#t[t])&&(yield[this.#i[t],this.#t[t]])}*rentries(){for(let t of this.#z())this.#t[t]!==void 0&&this.#i[t]!==void 0&&!this.#e(this.#t[t])&&(yield[this.#i[t],this.#t[t]])}*keys(){for(let t of this.#A()){let e=this.#i[t];e!==void 0&&!this.#e(this.#t[t])&&(yield e)}}*rkeys(){for(let t of this.#z()){let e=this.#i[t];e!==void 0&&!this.#e(this.#t[t])&&(yield e)}}*values(){for(let t of this.#A())this.#t[t]!==void 0&&!this.#e(this.#t[t])&&(yield this.#t[t])}*rvalues(){for(let t of this.#z())this.#t[t]!==void 0&&!this.#e(this.#t[t])&&(yield this.#t[t])}[Symbol.iterator](){return this.entries()}[Symbol.toStringTag]="LRUCache";find(t,e={}){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;if(n!==void 0&&t(n,this.#i[i],this))return this.#L(this.#i[i],e)}}forEach(t,e=this){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&t.call(e,n,this.#i[i],this)}}rforEach(t,e=this){for(let i of this.#z()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&t.call(e,n,this.#i[i],this)}}purgeStale(){let t=!1;for(let e of this.#z({allowStale:!0}))this.#p(e)&&(this.#v(this.#i[e],"expire"),t=!0);return t}info(t){let e=this.#s.get(t);if(e===void 0)return;let i=this.#t[e],s=this.#e(i)?i.__staleWhileFetching:i;if(s===void 0)return;let n={value:s};if(this.#d&&this.#F){let o=this.#d[e],l=this.#F[e];if(o&&l){let h=o-(this.#w.now()-l);n.ttl=h,n.start=Date.now()}}return this.#_&&(n.size=this.#_[e]),n}dump(){let t=[];for(let e of this.#A({allowStale:!0})){let i=this.#i[e],s=this.#t[e],n=this.#e(s)?s.__staleWhileFetching:s;if(n===void 0||i===void 0)continue;let o={value:n};if(this.#d&&this.#F){o.ttl=this.#d[e];let l=this.#w.now()-this.#F[e];o.start=Math.floor(Date.now()-l)}this.#_&&(o.size=this.#_[e]),t.unshift([i,o])}return t}load(t){this.clear();for(let[e,i]of t){if(i.start){let s=Date.now()-i.start;i.start=this.#w.now()-s}this.#O(e,i.value,i)}}set(t,e,i={}){let{status:s=g.metrics.hasSubscribers?{}:void 0}=i;i.status=s,s&&(s.op="set",s.key=t,e!==void 0&&(s.value=e),s.cache=this);let n=this.#O(t,e,i);return s&&g.metrics.hasSubscribers&&g.metrics.publish(s),n}#O(t,e,i,s){let{ttl:n=this.ttl,start:o,noDisposeOnSet:l=this.noDisposeOnSet,sizeCalculation:h=this.sizeCalculation,status:r}=i,c=this.#e(e);if(e===void 0)return r&&(r.set="deleted"),this.delete(t),this;let{noUpdateTTL:w=this.noUpdateTTL}=i;r&&!c&&(r.value=e);let _=this.#N(t,e,i.size||0,h,r);if(this.maxEntrySize&&_>this.maxEntrySize)return this.#v(t,"set"),r&&(r.set="miss",r.maxEntrySizeExceeded=!0),this;let d=this.#n===0?void 0:this.#s.get(t);if(d===void 0)d=this.#n===0?this.#h:this.#y.length!==0?this.#y.pop():this.#n===this.#o?this.#P(!1):this.#n,this.#i[d]=t,this.#t[d]=e,this.#s.set(t,d),this.#l[this.#h]=d,this.#u[d]=this.#h,this.#h=d,this.#n++,this.#I(d,_,r),r&&(r.set="add"),w=!1,this.#R&&!c&&this.#W?.(e,t,"add");else{this.#M(d);let p=this.#t[d];if(e!==p){if(!l)if(this.#e(p)){p!==s&&p.__abortController.abort(new Error("replaced"));let{__staleWhileFetching:f}=p;f!==void 0&&f!==e&&(this.#T&&this.#m?.(f,t,"set"),this.#f&&this.#r?.push([f,t,"set"]))}else this.#T&&this.#m?.(p,t,"set"),this.#f&&this.#r?.push([p,t,"set"]);if(this.#C(d),this.#I(d,_,r),this.#t[d]=e,!c){let f=p&&this.#e(p)?p.__staleWhileFetching:p,y=f===void 0?"add":e!==f?"replace":"update";r&&(r.set=y,f!==void 0&&(r.oldValue=f)),this.#R&&this.onInsert?.(e,t,y)}}else c||(r&&(r.set="update"),this.#R&&this.onInsert?.(e,t,"update"))}if(n!==0&&!this.#d&&this.#k(),this.#d&&(w||this.#H(d,n,o),r&&this.#E(r,d)),!l&&this.#f&&this.#r){let p=this.#r,f;for(;f=p?.shift();)this.#S?.(...f)}return this}pop(){try{for(;this.#n;){let t=this.#t[this.#a];if(this.#P(!0),this.#e(t)){if(t.__staleWhileFetching)return t.__staleWhileFetching}else if(t!==void 0)return t}}finally{if(this.#f&&this.#r){let t=this.#r,e;for(;e=t?.shift();)this.#S?.(...e)}}}#P(t){let e=this.#a,i=this.#i[e],s=this.#t[e],n=this.#e(s);n&&s.__abortController.abort(new Error("evicted"));let o=n?s.__staleWhileFetching:s;return(this.#T||this.#f)&&o!==void 0&&(this.#T&&this.#m?.(o,i,"evict"),this.#f&&this.#r?.push([o,i,"evict"])),this.#C(e),this.#g?.[e]&&(clearTimeout(this.#g[e]),this.#g[e]=void 0),t&&(this.#i[e]=void 0,this.#t[e]=void 0,this.#y.push(e)),this.#n===1?(this.#a=this.#h=0,this.#y.length=0):this.#a=this.#l[e],this.#s.delete(i),this.#n--,e}has(t,e={}){let{status:i=g.metrics.hasSubscribers?{}:void 0}=e;e.status=i,i&&(i.op="has",i.key=t,i.cache=this);let s=this.#Y(t,e);return g.metrics.hasSubscribers&&g.metrics.publish(i),s}#Y(t,e={}){let{updateAgeOnHas:i=this.updateAgeOnHas,status:s}=e,n=this.#s.get(t);if(n!==void 0){let o=this.#t[n];if(this.#e(o)&&o.__staleWhileFetching===void 0)return!1;if(this.#p(n))s&&(s.has="stale",this.#E(s,n));else return i&&this.#D(n),s&&(s.has="hit",this.#E(s,n)),!0}else s&&(s.has="miss");return!1}peek(t,e={}){let{status:i=C()?{}:void 0}=e;i&&(i.op="peek",i.key=t,i.cache=this),e.status=i;let s=this.#J(t,e);return g.metrics.hasSubscribers&&g.metrics.publish(i),s}#J(t,e){let{status:i,allowStale:s=this.allowStale}=e,n=this.#s.get(t);if(n===void 0||!s&&this.#p(n)){i&&(i.peek=n===void 0?"miss":"stale");return}let o=this.#t[n],l=this.#e(o)?o.__staleWhileFetching:o;return i&&(l!==void 0?(i.peek="hit",i.value=l):i.peek="miss"),l}#G(t,e,i,s){let n=e===void 0?void 0:this.#t[e];if(this.#e(n))return n;let o=new AbortController,{signal:l}=i;l?.addEventListener("abort",()=>o.abort(l.reason),{signal:o.signal});let h={signal:o.signal,options:i,context:s},r=(f,y=!1)=>{let{aborted:a}=o.signal,S=i.ignoreFetchAbort&&f!==void 0,F=i.ignoreFetchAbort||!!(i.allowStaleOnFetchAbort&&f!==void 0);if(i.status&&(a&&!y?(i.status.fetchAborted=!0,i.status.fetchError=o.signal.reason,S&&(i.status.fetchAbortIgnored=!0)):i.status.fetchResolved=!0),a&&!S&&!y)return w(o.signal.reason,F);let b=d,m=this.#t[e];return(m===d||m===void 0&&S&&y)&&(f===void 0?b.__staleWhileFetching!==void 0?this.#t[e]=b.__staleWhileFetching:this.#v(t,"fetch"):(i.status&&(i.status.fetchUpdated=!0),this.#O(t,f,h.options,b))),f},c=f=>(i.status&&(i.status.fetchRejected=!0,i.status.fetchError=f),w(f,!1)),w=(f,y)=>{let{aborted:a}=o.signal,S=a&&i.allowStaleOnFetchAbort,F=S||i.allowStaleOnFetchRejection,b=F||i.noDeleteOnFetchRejection,m=d;if(this.#t[e]===d&&(!b||!y&&m.__staleWhileFetching===void 0?this.#v(t,"fetch"):S||(this.#t[e]=m.__staleWhileFetching)),F)return i.status&&m.__staleWhileFetching!==void 0&&(i.status.returnedStale=!0),m.__staleWhileFetching;if(m.__returned===m)throw f},_=(f,y)=>{let a=this.#x?.(t,n,h);o.signal.addEventListener("abort",()=>{(!i.ignoreFetchAbort||i.allowStaleOnFetchAbort)&&(f(void 0),i.allowStaleOnFetchAbort&&(f=S=>r(S,!0)))}),a&&a instanceof Promise?a.then(S=>f(S===void 0?void 0:S),y):a!==void 0&&f(a)};i.status&&(i.status.fetchDispatched=!0);let d=new Promise(_).then(r,c),p=Object.assign(d,{__abortController:o,__staleWhileFetching:n,__returned:void 0});return e===void 0?(this.#O(t,p,{...h.options,status:void 0}),e=this.#s.get(t)):this.#t[e]=p,p}#e(t){if(!this.#U)return!1;let e=t;return!!e&&e instanceof Promise&&e.hasOwnProperty("__staleWhileFetching")&&e.__abortController instanceof AbortController}fetch(t,e={}){let i=g.tracing.hasSubscribers,{status:s=C()?{}:void 0}=e;e.status=s,s&&e.context&&(s.context=e.context);let n=this.#B(t,e);return s&&i&&(s.trace=!0,g.tracing.tracePromise(()=>n,s).catch(()=>{})),n}async#B(t,e={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,ttl:o=this.ttl,noDisposeOnSet:l=this.noDisposeOnSet,size:h=0,sizeCalculation:r=this.sizeCalculation,noUpdateTTL:c=this.noUpdateTTL,noDeleteOnFetchRejection:w=this.noDeleteOnFetchRejection,allowStaleOnFetchRejection:_=this.allowStaleOnFetchRejection,ignoreFetchAbort:d=this.ignoreFetchAbort,allowStaleOnFetchAbort:p=this.allowStaleOnFetchAbort,context:f,forceRefresh:y=!1,status:a,signal:S}=e;if(a&&(a.op="fetch",a.key=t,y&&(a.forceRefresh=!0),a.cache=this),!this.#U)return a&&(a.fetch="get"),this.#L(t,{allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,status:a});let F={allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,ttl:o,noDisposeOnSet:l,size:h,sizeCalculation:r,noUpdateTTL:c,noDeleteOnFetchRejection:w,allowStaleOnFetchRejection:_,allowStaleOnFetchAbort:p,ignoreFetchAbort:d,status:a,signal:S},b=this.#s.get(t);if(b===void 0){a&&(a.fetch="miss");let m=this.#G(t,b,F,f);return m.__returned=m}else{let m=this.#t[b];if(this.#e(m)){let E=i&&m.__staleWhileFetching!==void 0;return a&&(a.fetch="inflight",E&&(a.returnedStale=!0)),E?m.__staleWhileFetching:m.__returned=m}let A=this.#p(b);if(!y&&!A)return a&&(a.fetch="hit"),this.#M(b),s&&this.#D(b),a&&this.#E(a,b),m;let z=this.#G(t,b,F,f),v=z.__staleWhileFetching!==void 0&&i;return a&&(a.fetch=A?"stale":"refresh",v&&A&&(a.returnedStale=!0)),v?z.__staleWhileFetching:z.__returned=z}}forceFetch(t,e={}){let i=g.tracing.hasSubscribers,{status:s=C()?{}:void 0}=e;e.status=s,s&&e.context&&(s.context=e.context);let n=this.#K(t,e);return s&&i&&(s.trace=!0,g.tracing.tracePromise(()=>n,s).catch(()=>{})),n}async#K(t,e={}){let i=await this.#B(t,e);if(i===void 0)throw new Error("fetch() returned undefined");return i}memo(t,e={}){let{status:i=g.metrics.hasSubscribers?{}:void 0}=e;e.status=i,i&&(i.op="memo",i.key=t,e.context&&(i.context=e.context),i.cache=this);let s=this.#Q(t,e);return i&&(i.value=s),g.metrics.hasSubscribers&&g.metrics.publish(i),s}#Q(t,e={}){let i=this.#j;if(!i)throw new Error("no memoMethod provided to constructor");let{context:s,status:n,forceRefresh:o,...l}=e;n&&o&&(n.forceRefresh=!0);let h=this.#L(t,l),r=o||h===void 0;if(n&&(n.memo=r?"miss":"hit",r||(n.value=h)),!r)return h;let c=i(t,h,{options:l,context:s});return n&&(n.value=c),this.#O(t,c,l),c}get(t,e={}){let{status:i=g.metrics.hasSubscribers?{}:void 0}=e;e.status=i,i&&(i.op="get",i.key=t,i.cache=this);let s=this.#L(t,e);return i&&(s!==void 0&&(i.value=s),g.metrics.hasSubscribers&&g.metrics.publish(i)),s}#L(t,e={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,status:o}=e,l=this.#s.get(t);if(l===void 0){o&&(o.get="miss");return}let h=this.#t[l],r=this.#e(h);return o&&this.#E(o,l),this.#p(l)?r?(o&&(o.get="stale-fetching"),i&&h.__staleWhileFetching!==void 0?(o&&(o.returnedStale=!0),h.__staleWhileFetching):void 0):(n||this.#v(t,"expire"),o&&(o.get="stale"),i?(o&&(o.returnedStale=!0),h):void 0):(o&&(o.get=r?"fetching":"hit"),this.#M(l),s&&this.#D(l),r?h.__staleWhileFetching:h)}#q(t,e){this.#u[e]=t,this.#l[t]=e}#M(t){t!==this.#h&&(t===this.#a?this.#a=this.#l[t]:this.#q(this.#u[t],this.#l[t]),this.#q(this.#h,t),this.#h=t)}delete(t){return this.#v(t,"delete")}#v(t,e){g.metrics.hasSubscribers&&g.metrics.publish({op:"delete",delete:e,key:t,cache:this});let i=!1;if(this.#n!==0){let s=this.#s.get(t);if(s!==void 0)if(this.#g?.[s]&&(clearTimeout(this.#g[s]),this.#g[s]=void 0),i=!0,this.#n===1)this.#$(e);else{this.#C(s);let n=this.#t[s];if(this.#e(n)?n.__abortController.abort(new Error("deleted")):(this.#T||this.#f)&&(this.#T&&this.#m?.(n,t,e),this.#f&&this.#r?.push([n,t,e])),this.#s.delete(t),this.#i[s]=void 0,this.#t[s]=void 0,s===this.#h)this.#h=this.#u[s];else if(s===this.#a)this.#a=this.#l[s];else{let o=this.#u[s];this.#l[o]=this.#l[s];let l=this.#l[s];this.#u[l]=this.#u[s]}this.#n--,this.#y.push(s)}}if(this.#f&&this.#r?.length){let s=this.#r,n;for(;n=s?.shift();)this.#S?.(...n)}return i}clear(){return this.#$("delete")}#$(t){for(let e of this.#z({allowStale:!0})){let i=this.#t[e];if(this.#e(i))i.__abortController.abort(new Error("deleted"));else{let s=this.#i[e];this.#T&&this.#m?.(i,s,t),this.#f&&this.#r?.push([i,s,t])}}if(this.#s.clear(),this.#t.fill(void 0),this.#i.fill(void 0),this.#d&&this.#F){this.#d.fill(0),this.#F.fill(0);for(let e of this.#g??[])e!==void 0&&clearTimeout(e);this.#g?.fill(void 0)}if(this.#_&&this.#_.fill(0),this.#a=0,this.#h=0,this.#y.length=0,this.#b=0,this.#n=0,this.#f&&this.#r){let e=this.#r,i;for(;i=e?.shift();)this.#S?.(...i)}}};exports.LRUCache=M;
//# sourceMappingURL=index.min.js.map
diff --git a/deps/npm/node_modules/lru-cache/dist/commonjs/index.js b/deps/npm/node_modules/lru-cache/dist/commonjs/index.js
index 6b8268b0ea9..3f5cceec7ae 100644
--- a/deps/npm/node_modules/lru-cache/dist/commonjs/index.js
+++ b/deps/npm/node_modules/lru-cache/dist/commonjs/index.js
@@ -412,17 +412,17 @@ class LRUCache {
this.#setItemTTL = (index, ttl, start = this.#perf.now()) => {
starts[index] = ttl !== 0 ? start : 0;
ttls[index] = ttl;
- setPurgetTimer(index, ttl);
+ setPurgeTimer(index, ttl);
};
this.#updateItemAge = index => {
starts[index] = ttls[index] !== 0 ? this.#perf.now() : 0;
- setPurgetTimer(index, ttls[index]);
+ setPurgeTimer(index, ttls[index]);
};
// clear out the purge timer if we're setting TTL to 0, and
// previously had a ttl purge timer running, so it doesn't
// fire unnecessarily. Don't need to do this if we're not doing
// autopurge.
- const setPurgetTimer = !this.ttlAutopurge ?
+ const setPurgeTimer = !this.ttlAutopurge ?
() => { }
: (index, ttl) => {
if (purgeTimers?.[index]) {
@@ -433,6 +433,10 @@ class LRUCache {
const t = setTimeout(() => {
if (this.#isStale(index)) {
this.#delete(this.#keyList[index], 'expire');
+ purgeTimers[index] = undefined;
+ }
+ else {
+ setPurgeTimer(index, getRemainingTTL(index));
}
}, ttl + 1);
// unref() not supported on all platforms
@@ -482,6 +486,9 @@ class LRUCache {
if (index === undefined) {
return 0;
}
+ return getRemainingTTL(index);
+ };
+ const getRemainingTTL = (index) => {
const ttl = ttls[index];
const start = starts[index];
if (!ttl || !start) {
@@ -1621,7 +1628,7 @@ class LRUCache {
const index = this.#keyMap.get(k);
if (index !== undefined) {
if (this.#autopurgeTimers?.[index]) {
- clearTimeout(this.#autopurgeTimers?.[index]);
+ clearTimeout(this.#autopurgeTimers[index]);
this.#autopurgeTimers[index] = undefined;
}
deleted = true;
diff --git a/deps/npm/node_modules/lru-cache/dist/commonjs/index.min.js b/deps/npm/node_modules/lru-cache/dist/commonjs/index.min.js
index 8e424610744..d20fcc5eb89 100644
--- a/deps/npm/node_modules/lru-cache/dist/commonjs/index.min.js
+++ b/deps/npm/node_modules/lru-cache/dist/commonjs/index.min.js
@@ -1,2 +1,2 @@
-"use strict";var j=(c,t)=>()=>(t||c((t={exports:{}}).exports,t),t.exports);var I=j(O=>{"use strict";Object.defineProperty(O,"__esModule",{value:!0});O.tracing=O.metrics=void 0;var U={hasSubscribers:!1};O.metrics=U;O.tracing=U});var P=j(D=>{"use strict";Object.defineProperty(D,"__esModule",{value:!0});D.defaultPerf=void 0;D.defaultPerf=typeof performance=="object"&&performance&&typeof performance.now=="function"?performance:Date});Object.defineProperty(exports,"__esModule",{value:!0});exports.LRUCache=void 0;var g=I(),N=P(),x=()=>g.metrics.hasSubscribers||g.tracing.hasSubscribers,k=new Set,G=typeof process=="object"&&process?process:{},V=(c,t,e,i)=>{typeof G.emitWarning=="function"?G.emitWarning(c,t,e,i):console.error(`[${e}] ${t}: ${c}`)},B=c=>!k.has(c);var T=c=>!!c&&c===Math.floor(c)&&c>0&&isFinite(c),H=c=>T(c)?c<=Math.pow(2,8)?Uint8Array:c<=Math.pow(2,16)?Uint16Array:c<=Math.pow(2,32)?Uint32Array:c<=Number.MAX_SAFE_INTEGER?W:null:null,W=class extends Array{constructor(t){super(t),this.fill(0)}},C=class c{heap;length;static#o=!1;static create(t){let e=H(t);if(!e)return[];c.#o=!0;let i=new c(t,e);return c.#o=!1,i}constructor(t,e){if(!c.#o)throw new TypeError("instantiate Stack using Stack.create(n)");this.heap=new e(t),this.length=0}push(t){this.heap[this.length++]=t}pop(){return this.heap[--this.length]}},L=class c{#o;#c;#m;#W;#S;#M;#j;#w;get perf(){return this.#w}ttl;ttlResolution;ttlAutopurge;updateAgeOnGet;updateAgeOnHas;allowStale;noDisposeOnSet;noUpdateTTL;maxEntrySize;sizeCalculation;noDeleteOnFetchRejection;noDeleteOnStaleGet;allowStaleOnFetchAbort;allowStaleOnFetchRejection;ignoreFetchAbort;backgroundFetchSize;#n;#b;#s;#i;#t;#l;#u;#a;#h;#y;#r;#_;#F;#d;#g;#T;#U;#f;#D;static unsafeExposeInternals(t){return{starts:t.#F,ttls:t.#d,autopurgeTimers:t.#g,sizes:t.#_,keyMap:t.#s,keyList:t.#i,valList:t.#t,next:t.#l,prev:t.#u,get head(){return t.#a},get tail(){return t.#h},free:t.#y,isBackgroundFetch:e=>t.#e(e),backgroundFetch:(e,i,s,n)=>t.#G(e,i,s,n),moveToTail:e=>t.#L(e),indexes:e=>t.#A(e),rindexes:e=>t.#z(e),isStale:e=>t.#p(e)}}get max(){return this.#o}get maxSize(){return this.#c}get calculatedSize(){return this.#b}get size(){return this.#n}get fetchMethod(){return this.#M}get memoMethod(){return this.#j}get dispose(){return this.#m}get onInsert(){return this.#W}get disposeAfter(){return this.#S}constructor(t){let{max:e=0,ttl:i,ttlResolution:s=1,ttlAutopurge:n,updateAgeOnGet:r,updateAgeOnHas:h,allowStale:a,dispose:o,onInsert:d,disposeAfter:y,noDisposeOnSet:_,noUpdateTTL:u,maxSize:p=0,maxEntrySize:f=0,sizeCalculation:b,fetchMethod:l,memoMethod:S,noDeleteOnFetchRejection:F,noDeleteOnStaleGet:w,allowStaleOnFetchRejection:m,allowStaleOnFetchAbort:A,ignoreFetchAbort:z,backgroundFetchSize:M=1,perf:v}=t;if(this.backgroundFetchSize=M,v!==void 0&&typeof v?.now!="function")throw new TypeError("perf option must have a now() method if specified");if(this.#w=v??N.defaultPerf,e!==0&&!T(e))throw new TypeError("max option must be a nonnegative integer");let E=e?H(e):Array;if(!E)throw new Error("invalid max value: "+e);if(this.#o=e,this.#c=p,this.maxEntrySize=f||this.#c,this.sizeCalculation=b,this.sizeCalculation){if(!this.#c&&!this.maxEntrySize)throw new TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");if(typeof this.sizeCalculation!="function")throw new TypeError("sizeCalculation set to non-function")}if(S!==void 0&&typeof S!="function")throw new TypeError("memoMethod must be a function if defined");if(this.#j=S,l!==void 0&&typeof l!="function")throw new TypeError("fetchMethod must be a function if specified");if(this.#M=l,this.#U=!!l,this.#s=new Map,this.#i=Array.from({length:e}).fill(void 0),this.#t=Array.from({length:e}).fill(void 0),this.#l=new E(e),this.#u=new E(e),this.#a=0,this.#h=0,this.#y=C.create(e),this.#n=0,this.#b=0,typeof o=="function"&&(this.#m=o),typeof d=="function"&&(this.#W=d),typeof y=="function"?(this.#S=y,this.#r=[]):(this.#S=void 0,this.#r=void 0),this.#T=!!this.#m,this.#D=!!this.#W,this.#f=!!this.#S,this.noDisposeOnSet=!!_,this.noUpdateTTL=!!u,this.noDeleteOnFetchRejection=!!F,this.allowStaleOnFetchRejection=!!m,this.allowStaleOnFetchAbort=!!A,this.ignoreFetchAbort=!!z,this.maxEntrySize!==0){if(this.#c!==0&&!T(this.#c))throw new TypeError("maxSize must be a positive integer if specified");if(!T(this.maxEntrySize))throw new TypeError("maxEntrySize must be a positive integer if specified");this.#X()}if(this.allowStale=!!a,this.noDeleteOnStaleGet=!!w,this.updateAgeOnGet=!!r,this.updateAgeOnHas=!!h,this.ttlResolution=T(s)||s===0?s:1,this.ttlAutopurge=!!n,this.ttl=i||0,this.ttl){if(!T(this.ttl))throw new TypeError("ttl must be a positive integer if specified");this.#k()}if(this.#o===0&&this.ttl===0&&this.#c===0)throw new TypeError("At least one of max, maxSize, or ttl is required");if(!this.ttlAutopurge&&!this.#o&&!this.#c){let R="LRU_CACHE_UNBOUNDED";B(R)&&(k.add(R),V("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.","UnboundedCacheWarning",R,c))}}getRemainingTTL(t){return this.#s.has(t)?1/0:0}#k(){let t=new W(this.#o),e=new W(this.#o);this.#d=t,this.#F=e;let i=this.ttlAutopurge?Array.from({length:this.#o}):void 0;this.#g=i,this.#H=(h,a,o=this.#w.now())=>{e[h]=a!==0?o:0,t[h]=a,s(h,a)},this.#R=h=>{e[h]=t[h]!==0?this.#w.now():0,s(h,t[h])};let s=this.ttlAutopurge?(h,a)=>{if(i?.[h]&&(clearTimeout(i[h]),i[h]=void 0),a&&a!==0&&i){let o=setTimeout(()=>{this.#p(h)&&this.#v(this.#i[h],"expire")},a+1);o.unref&&o.unref(),i[h]=o}}:()=>{};this.#E=(h,a)=>{if(t[a]){let o=t[a],d=e[a];if(!o||!d)return;h.ttl=o,h.start=d,h.now=n||r();let y=h.now-d;h.remainingTTL=o-y}};let n=0,r=()=>{let h=this.#w.now();if(this.ttlResolution>0){n=h;let a=setTimeout(()=>n=0,this.ttlResolution);a.unref&&a.unref()}return h};this.getRemainingTTL=h=>{let a=this.#s.get(h);if(a===void 0)return 0;let o=t[a],d=e[a];if(!o||!d)return 1/0;let y=(n||r())-d;return o-y},this.#p=h=>{let a=e[h],o=t[h];return!!o&&!!a&&(n||r())-a>o}}#R=()=>{};#E=()=>{};#H=()=>{};#p=()=>!1;#X(){let t=new W(this.#o);this.#b=0,this.#_=t,this.#x=e=>{this.#b-=t[e],t[e]=0},this.#N=(e,i,s,n)=>{if(!T(s)){if(this.#e(i))return this.backgroundFetchSize;if(n){if(typeof n!="function")throw new TypeError("sizeCalculation must be a function");if(s=n(i,e),!T(s))throw new TypeError("sizeCalculation return invalid (expect positive integer)")}else throw new TypeError("invalid size value (must be positive integer). When maxSize or maxEntrySize is used, sizeCalculation or size must be set.")}return s},this.#I=(e,i,s)=>{if(t[e]=i,this.#c){let n=this.#c-t[e];for(;this.#b>n;)this.#P(!0)}this.#b+=t[e],s&&(s.entrySize=i,s.totalCalculatedSize=this.#b)}}#x=t=>{};#I=(t,e,i)=>{};#N=(t,e,i,s)=>{if(i||s)throw new TypeError("cannot set size without setting maxSize or maxEntrySize on cache");return 0};*#A({allowStale:t=this.allowStale}={}){if(this.#n)for(let e=this.#h;this.#V(e)&&((t||!this.#p(e))&&(yield e),e!==this.#a);)e=this.#u[e]}*#z({allowStale:t=this.allowStale}={}){if(this.#n)for(let e=this.#a;this.#V(e)&&((t||!this.#p(e))&&(yield e),e!==this.#h);)e=this.#l[e]}#V(t){return t!==void 0&&this.#s.get(this.#i[t])===t}*entries(){for(let t of this.#A())this.#t[t]!==void 0&&this.#i[t]!==void 0&&!this.#e(this.#t[t])&&(yield[this.#i[t],this.#t[t]])}*rentries(){for(let t of this.#z())this.#t[t]!==void 0&&this.#i[t]!==void 0&&!this.#e(this.#t[t])&&(yield[this.#i[t],this.#t[t]])}*keys(){for(let t of this.#A()){let e=this.#i[t];e!==void 0&&!this.#e(this.#t[t])&&(yield e)}}*rkeys(){for(let t of this.#z()){let e=this.#i[t];e!==void 0&&!this.#e(this.#t[t])&&(yield e)}}*values(){for(let t of this.#A())this.#t[t]!==void 0&&!this.#e(this.#t[t])&&(yield this.#t[t])}*rvalues(){for(let t of this.#z())this.#t[t]!==void 0&&!this.#e(this.#t[t])&&(yield this.#t[t])}[Symbol.iterator](){return this.entries()}[Symbol.toStringTag]="LRUCache";find(t,e={}){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;if(n!==void 0&&t(n,this.#i[i],this))return this.#C(this.#i[i],e)}}forEach(t,e=this){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&t.call(e,n,this.#i[i],this)}}rforEach(t,e=this){for(let i of this.#z()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&t.call(e,n,this.#i[i],this)}}purgeStale(){let t=!1;for(let e of this.#z({allowStale:!0}))this.#p(e)&&(this.#v(this.#i[e],"expire"),t=!0);return t}info(t){let e=this.#s.get(t);if(e===void 0)return;let i=this.#t[e],s=this.#e(i)?i.__staleWhileFetching:i;if(s===void 0)return;let n={value:s};if(this.#d&&this.#F){let r=this.#d[e],h=this.#F[e];if(r&&h){let a=r-(this.#w.now()-h);n.ttl=a,n.start=Date.now()}}return this.#_&&(n.size=this.#_[e]),n}dump(){let t=[];for(let e of this.#A({allowStale:!0})){let i=this.#i[e],s=this.#t[e],n=this.#e(s)?s.__staleWhileFetching:s;if(n===void 0||i===void 0)continue;let r={value:n};if(this.#d&&this.#F){r.ttl=this.#d[e];let h=this.#w.now()-this.#F[e];r.start=Math.floor(Date.now()-h)}this.#_&&(r.size=this.#_[e]),t.unshift([i,r])}return t}load(t){this.clear();for(let[e,i]of t){if(i.start){let s=Date.now()-i.start;i.start=this.#w.now()-s}this.#O(e,i.value,i)}}set(t,e,i={}){let{status:s=g.metrics.hasSubscribers?{}:void 0}=i;i.status=s,s&&(s.op="set",s.key=t,e!==void 0&&(s.value=e),s.cache=this);let n=this.#O(t,e,i);return s&&g.metrics.hasSubscribers&&g.metrics.publish(s),n}#O(t,e,i,s){let{ttl:n=this.ttl,start:r,noDisposeOnSet:h=this.noDisposeOnSet,sizeCalculation:a=this.sizeCalculation,status:o}=i,d=this.#e(e);if(e===void 0)return o&&(o.set="deleted"),this.delete(t),this;let{noUpdateTTL:y=this.noUpdateTTL}=i;o&&!d&&(o.value=e);let _=this.#N(t,e,i.size||0,a,o);if(this.maxEntrySize&&_>this.maxEntrySize)return this.#v(t,"set"),o&&(o.set="miss",o.maxEntrySizeExceeded=!0),this;let u=this.#n===0?void 0:this.#s.get(t);if(u===void 0)u=this.#n===0?this.#h:this.#y.length!==0?this.#y.pop():this.#n===this.#o?this.#P(!1):this.#n,this.#i[u]=t,this.#t[u]=e,this.#s.set(t,u),this.#l[this.#h]=u,this.#u[u]=this.#h,this.#h=u,this.#n++,this.#I(u,_,o),o&&(o.set="add"),y=!1,this.#D&&!d&&this.#W?.(e,t,"add");else{this.#L(u);let p=this.#t[u];if(e!==p){if(!h)if(this.#e(p)){p!==s&&p.__abortController.abort(new Error("replaced"));let{__staleWhileFetching:f}=p;f!==void 0&&f!==e&&(this.#T&&this.#m?.(f,t,"set"),this.#f&&this.#r?.push([f,t,"set"]))}else this.#T&&this.#m?.(p,t,"set"),this.#f&&this.#r?.push([p,t,"set"]);if(this.#x(u),this.#I(u,_,o),this.#t[u]=e,!d){let f=p&&this.#e(p)?p.__staleWhileFetching:p,b=f===void 0?"add":e!==f?"replace":"update";o&&(o.set=b,f!==void 0&&(o.oldValue=f)),this.#D&&this.onInsert?.(e,t,b)}}else d||(o&&(o.set="update"),this.#D&&this.onInsert?.(e,t,"update"))}if(n!==0&&!this.#d&&this.#k(),this.#d&&(y||this.#H(u,n,r),o&&this.#E(o,u)),!h&&this.#f&&this.#r){let p=this.#r,f;for(;f=p?.shift();)this.#S?.(...f)}return this}pop(){try{for(;this.#n;){let t=this.#t[this.#a];if(this.#P(!0),this.#e(t)){if(t.__staleWhileFetching)return t.__staleWhileFetching}else if(t!==void 0)return t}}finally{if(this.#f&&this.#r){let t=this.#r,e;for(;e=t?.shift();)this.#S?.(...e)}}}#P(t){let e=this.#a,i=this.#i[e],s=this.#t[e],n=this.#e(s);n&&s.__abortController.abort(new Error("evicted"));let r=n?s.__staleWhileFetching:s;return(this.#T||this.#f)&&r!==void 0&&(this.#T&&this.#m?.(r,i,"evict"),this.#f&&this.#r?.push([r,i,"evict"])),this.#x(e),this.#g?.[e]&&(clearTimeout(this.#g[e]),this.#g[e]=void 0),t&&(this.#i[e]=void 0,this.#t[e]=void 0,this.#y.push(e)),this.#n===1?(this.#a=this.#h=0,this.#y.length=0):this.#a=this.#l[e],this.#s.delete(i),this.#n--,e}has(t,e={}){let{status:i=g.metrics.hasSubscribers?{}:void 0}=e;e.status=i,i&&(i.op="has",i.key=t,i.cache=this);let s=this.#Y(t,e);return g.metrics.hasSubscribers&&g.metrics.publish(i),s}#Y(t,e={}){let{updateAgeOnHas:i=this.updateAgeOnHas,status:s}=e,n=this.#s.get(t);if(n!==void 0){let r=this.#t[n];if(this.#e(r)&&r.__staleWhileFetching===void 0)return!1;if(this.#p(n))s&&(s.has="stale",this.#E(s,n));else return i&&this.#R(n),s&&(s.has="hit",this.#E(s,n)),!0}else s&&(s.has="miss");return!1}peek(t,e={}){let{status:i=x()?{}:void 0}=e;i&&(i.op="peek",i.key=t,i.cache=this),e.status=i;let s=this.#J(t,e);return g.metrics.hasSubscribers&&g.metrics.publish(i),s}#J(t,e){let{status:i,allowStale:s=this.allowStale}=e,n=this.#s.get(t);if(n===void 0||!s&&this.#p(n)){i&&(i.peek=n===void 0?"miss":"stale");return}let r=this.#t[n],h=this.#e(r)?r.__staleWhileFetching:r;return i&&(h!==void 0?(i.peek="hit",i.value=h):i.peek="miss"),h}#G(t,e,i,s){let n=e===void 0?void 0:this.#t[e];if(this.#e(n))return n;let r=new AbortController,{signal:h}=i;h?.addEventListener("abort",()=>r.abort(h.reason),{signal:r.signal});let a={signal:r.signal,options:i,context:s},o=(f,b=!1)=>{let{aborted:l}=r.signal,S=i.ignoreFetchAbort&&f!==void 0,F=i.ignoreFetchAbort||!!(i.allowStaleOnFetchAbort&&f!==void 0);if(i.status&&(l&&!b?(i.status.fetchAborted=!0,i.status.fetchError=r.signal.reason,S&&(i.status.fetchAbortIgnored=!0)):i.status.fetchResolved=!0),l&&!S&&!b)return y(r.signal.reason,F);let w=u,m=this.#t[e];return(m===u||m===void 0&&S&&b)&&(f===void 0?w.__staleWhileFetching!==void 0?this.#t[e]=w.__staleWhileFetching:this.#v(t,"fetch"):(i.status&&(i.status.fetchUpdated=!0),this.#O(t,f,a.options,w))),f},d=f=>(i.status&&(i.status.fetchRejected=!0,i.status.fetchError=f),y(f,!1)),y=(f,b)=>{let{aborted:l}=r.signal,S=l&&i.allowStaleOnFetchAbort,F=S||i.allowStaleOnFetchRejection,w=F||i.noDeleteOnFetchRejection,m=u;if(this.#t[e]===u&&(!w||!b&&m.__staleWhileFetching===void 0?this.#v(t,"fetch"):S||(this.#t[e]=m.__staleWhileFetching)),F)return i.status&&m.__staleWhileFetching!==void 0&&(i.status.returnedStale=!0),m.__staleWhileFetching;if(m.__returned===m)throw f},_=(f,b)=>{let l=this.#M?.(t,n,a);r.signal.addEventListener("abort",()=>{(!i.ignoreFetchAbort||i.allowStaleOnFetchAbort)&&(f(void 0),i.allowStaleOnFetchAbort&&(f=S=>o(S,!0)))}),l&&l instanceof Promise?l.then(S=>f(S===void 0?void 0:S),b):l!==void 0&&f(l)};i.status&&(i.status.fetchDispatched=!0);let u=new Promise(_).then(o,d),p=Object.assign(u,{__abortController:r,__staleWhileFetching:n,__returned:void 0});return e===void 0?(this.#O(t,p,{...a.options,status:void 0}),e=this.#s.get(t)):this.#t[e]=p,p}#e(t){if(!this.#U)return!1;let e=t;return!!e&&e instanceof Promise&&e.hasOwnProperty("__staleWhileFetching")&&e.__abortController instanceof AbortController}fetch(t,e={}){let i=g.tracing.hasSubscribers,{status:s=x()?{}:void 0}=e;e.status=s,s&&e.context&&(s.context=e.context);let n=this.#B(t,e);return s&&i&&(s.trace=!0,g.tracing.tracePromise(()=>n,s).catch(()=>{})),n}async#B(t,e={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,ttl:r=this.ttl,noDisposeOnSet:h=this.noDisposeOnSet,size:a=0,sizeCalculation:o=this.sizeCalculation,noUpdateTTL:d=this.noUpdateTTL,noDeleteOnFetchRejection:y=this.noDeleteOnFetchRejection,allowStaleOnFetchRejection:_=this.allowStaleOnFetchRejection,ignoreFetchAbort:u=this.ignoreFetchAbort,allowStaleOnFetchAbort:p=this.allowStaleOnFetchAbort,context:f,forceRefresh:b=!1,status:l,signal:S}=e;if(l&&(l.op="fetch",l.key=t,b&&(l.forceRefresh=!0),l.cache=this),!this.#U)return l&&(l.fetch="get"),this.#C(t,{allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,status:l});let F={allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,ttl:r,noDisposeOnSet:h,size:a,sizeCalculation:o,noUpdateTTL:d,noDeleteOnFetchRejection:y,allowStaleOnFetchRejection:_,allowStaleOnFetchAbort:p,ignoreFetchAbort:u,status:l,signal:S},w=this.#s.get(t);if(w===void 0){l&&(l.fetch="miss");let m=this.#G(t,w,F,f);return m.__returned=m}else{let m=this.#t[w];if(this.#e(m)){let E=i&&m.__staleWhileFetching!==void 0;return l&&(l.fetch="inflight",E&&(l.returnedStale=!0)),E?m.__staleWhileFetching:m.__returned=m}let A=this.#p(w);if(!b&&!A)return l&&(l.fetch="hit"),this.#L(w),s&&this.#R(w),l&&this.#E(l,w),m;let z=this.#G(t,w,F,f),v=z.__staleWhileFetching!==void 0&&i;return l&&(l.fetch=A?"stale":"refresh",v&&A&&(l.returnedStale=!0)),v?z.__staleWhileFetching:z.__returned=z}}forceFetch(t,e={}){let i=g.tracing.hasSubscribers,{status:s=x()?{}:void 0}=e;e.status=s,s&&e.context&&(s.context=e.context);let n=this.#K(t,e);return s&&i&&(s.trace=!0,g.tracing.tracePromise(()=>n,s).catch(()=>{})),n}async#K(t,e={}){let i=await this.#B(t,e);if(i===void 0)throw new Error("fetch() returned undefined");return i}memo(t,e={}){let{status:i=g.metrics.hasSubscribers?{}:void 0}=e;e.status=i,i&&(i.op="memo",i.key=t,e.context&&(i.context=e.context),i.cache=this);let s=this.#Q(t,e);return i&&(i.value=s),g.metrics.hasSubscribers&&g.metrics.publish(i),s}#Q(t,e={}){let i=this.#j;if(!i)throw new Error("no memoMethod provided to constructor");let{context:s,status:n,forceRefresh:r,...h}=e;n&&r&&(n.forceRefresh=!0);let a=this.#C(t,h),o=r||a===void 0;if(n&&(n.memo=o?"miss":"hit",o||(n.value=a)),!o)return a;let d=i(t,a,{options:h,context:s});return n&&(n.value=d),this.#O(t,d,h),d}get(t,e={}){let{status:i=g.metrics.hasSubscribers?{}:void 0}=e;e.status=i,i&&(i.op="get",i.key=t,i.cache=this);let s=this.#C(t,e);return i&&(s!==void 0&&(i.value=s),g.metrics.hasSubscribers&&g.metrics.publish(i)),s}#C(t,e={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,status:r}=e,h=this.#s.get(t);if(h===void 0){r&&(r.get="miss");return}let a=this.#t[h],o=this.#e(a);return r&&this.#E(r,h),this.#p(h)?o?(r&&(r.get="stale-fetching"),i&&a.__staleWhileFetching!==void 0?(r&&(r.returnedStale=!0),a.__staleWhileFetching):void 0):(n||this.#v(t,"expire"),r&&(r.get="stale"),i?(r&&(r.returnedStale=!0),a):void 0):(r&&(r.get=o?"fetching":"hit"),this.#L(h),s&&this.#R(h),o?a.__staleWhileFetching:a)}#q(t,e){this.#u[e]=t,this.#l[t]=e}#L(t){t!==this.#h&&(t===this.#a?this.#a=this.#l[t]:this.#q(this.#u[t],this.#l[t]),this.#q(this.#h,t),this.#h=t)}delete(t){return this.#v(t,"delete")}#v(t,e){g.metrics.hasSubscribers&&g.metrics.publish({op:"delete",delete:e,key:t,cache:this});let i=!1;if(this.#n!==0){let s=this.#s.get(t);if(s!==void 0)if(this.#g?.[s]&&(clearTimeout(this.#g?.[s]),this.#g[s]=void 0),i=!0,this.#n===1)this.#$(e);else{this.#x(s);let n=this.#t[s];if(this.#e(n)?n.__abortController.abort(new Error("deleted")):(this.#T||this.#f)&&(this.#T&&this.#m?.(n,t,e),this.#f&&this.#r?.push([n,t,e])),this.#s.delete(t),this.#i[s]=void 0,this.#t[s]=void 0,s===this.#h)this.#h=this.#u[s];else if(s===this.#a)this.#a=this.#l[s];else{let r=this.#u[s];this.#l[r]=this.#l[s];let h=this.#l[s];this.#u[h]=this.#u[s]}this.#n--,this.#y.push(s)}}if(this.#f&&this.#r?.length){let s=this.#r,n;for(;n=s?.shift();)this.#S?.(...n)}return i}clear(){return this.#$("delete")}#$(t){for(let e of this.#z({allowStale:!0})){let i=this.#t[e];if(this.#e(i))i.__abortController.abort(new Error("deleted"));else{let s=this.#i[e];this.#T&&this.#m?.(i,s,t),this.#f&&this.#r?.push([i,s,t])}}if(this.#s.clear(),this.#t.fill(void 0),this.#i.fill(void 0),this.#d&&this.#F){this.#d.fill(0),this.#F.fill(0);for(let e of this.#g??[])e!==void 0&&clearTimeout(e);this.#g?.fill(void 0)}if(this.#_&&this.#_.fill(0),this.#a=0,this.#h=0,this.#y.length=0,this.#b=0,this.#n=0,this.#f&&this.#r){let e=this.#r,i;for(;i=e?.shift();)this.#S?.(...i)}}};exports.LRUCache=L;
+"use strict";var j=(u,t)=>()=>(t||u((t={exports:{}}).exports,t),t.exports);var I=j(O=>{"use strict";Object.defineProperty(O,"__esModule",{value:!0});O.tracing=O.metrics=void 0;var U={hasSubscribers:!1};O.metrics=U;O.tracing=U});var P=j(R=>{"use strict";Object.defineProperty(R,"__esModule",{value:!0});R.defaultPerf=void 0;R.defaultPerf=typeof performance=="object"&&performance&&typeof performance.now=="function"?performance:Date});Object.defineProperty(exports,"__esModule",{value:!0});exports.LRUCache=void 0;var g=I(),N=P(),C=()=>g.metrics.hasSubscribers||g.tracing.hasSubscribers,k=new Set,G=typeof process=="object"&&process?process:{},V=(u,t,e,i)=>{typeof G.emitWarning=="function"?G.emitWarning(u,t,e,i):console.error(`[${e}] ${t}: ${u}`)},B=u=>!k.has(u);var T=u=>!!u&&u===Math.floor(u)&&u>0&&isFinite(u),H=u=>T(u)?u<=Math.pow(2,8)?Uint8Array:u<=Math.pow(2,16)?Uint16Array:u<=Math.pow(2,32)?Uint32Array:u<=Number.MAX_SAFE_INTEGER?W:null:null,W=class extends Array{constructor(t){super(t),this.fill(0)}},L=class u{heap;length;static#o=!1;static create(t){let e=H(t);if(!e)return[];u.#o=!0;let i=new u(t,e);return u.#o=!1,i}constructor(t,e){if(!u.#o)throw new TypeError("instantiate Stack using Stack.create(n)");this.heap=new e(t),this.length=0}push(t){this.heap[this.length++]=t}pop(){return this.heap[--this.length]}},M=class u{#o;#c;#m;#W;#S;#x;#j;#w;get perf(){return this.#w}ttl;ttlResolution;ttlAutopurge;updateAgeOnGet;updateAgeOnHas;allowStale;noDisposeOnSet;noUpdateTTL;maxEntrySize;sizeCalculation;noDeleteOnFetchRejection;noDeleteOnStaleGet;allowStaleOnFetchAbort;allowStaleOnFetchRejection;ignoreFetchAbort;backgroundFetchSize;#n;#b;#s;#i;#t;#l;#u;#a;#h;#y;#r;#_;#F;#d;#g;#T;#U;#f;#R;static unsafeExposeInternals(t){return{starts:t.#F,ttls:t.#d,autopurgeTimers:t.#g,sizes:t.#_,keyMap:t.#s,keyList:t.#i,valList:t.#t,next:t.#l,prev:t.#u,get head(){return t.#a},get tail(){return t.#h},free:t.#y,isBackgroundFetch:e=>t.#e(e),backgroundFetch:(e,i,s,n)=>t.#G(e,i,s,n),moveToTail:e=>t.#M(e),indexes:e=>t.#A(e),rindexes:e=>t.#z(e),isStale:e=>t.#p(e)}}get max(){return this.#o}get maxSize(){return this.#c}get calculatedSize(){return this.#b}get size(){return this.#n}get fetchMethod(){return this.#x}get memoMethod(){return this.#j}get dispose(){return this.#m}get onInsert(){return this.#W}get disposeAfter(){return this.#S}constructor(t){let{max:e=0,ttl:i,ttlResolution:s=1,ttlAutopurge:n,updateAgeOnGet:o,updateAgeOnHas:l,allowStale:h,dispose:r,onInsert:c,disposeAfter:w,noDisposeOnSet:_,noUpdateTTL:d,maxSize:p=0,maxEntrySize:f=0,sizeCalculation:y,fetchMethod:a,memoMethod:S,noDeleteOnFetchRejection:F,noDeleteOnStaleGet:b,allowStaleOnFetchRejection:m,allowStaleOnFetchAbort:A,ignoreFetchAbort:z,backgroundFetchSize:x=1,perf:v}=t;if(this.backgroundFetchSize=x,v!==void 0&&typeof v?.now!="function")throw new TypeError("perf option must have a now() method if specified");if(this.#w=v??N.defaultPerf,e!==0&&!T(e))throw new TypeError("max option must be a nonnegative integer");let E=e?H(e):Array;if(!E)throw new Error("invalid max value: "+e);if(this.#o=e,this.#c=p,this.maxEntrySize=f||this.#c,this.sizeCalculation=y,this.sizeCalculation){if(!this.#c&&!this.maxEntrySize)throw new TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");if(typeof this.sizeCalculation!="function")throw new TypeError("sizeCalculation set to non-function")}if(S!==void 0&&typeof S!="function")throw new TypeError("memoMethod must be a function if defined");if(this.#j=S,a!==void 0&&typeof a!="function")throw new TypeError("fetchMethod must be a function if specified");if(this.#x=a,this.#U=!!a,this.#s=new Map,this.#i=Array.from({length:e}).fill(void 0),this.#t=Array.from({length:e}).fill(void 0),this.#l=new E(e),this.#u=new E(e),this.#a=0,this.#h=0,this.#y=L.create(e),this.#n=0,this.#b=0,typeof r=="function"&&(this.#m=r),typeof c=="function"&&(this.#W=c),typeof w=="function"?(this.#S=w,this.#r=[]):(this.#S=void 0,this.#r=void 0),this.#T=!!this.#m,this.#R=!!this.#W,this.#f=!!this.#S,this.noDisposeOnSet=!!_,this.noUpdateTTL=!!d,this.noDeleteOnFetchRejection=!!F,this.allowStaleOnFetchRejection=!!m,this.allowStaleOnFetchAbort=!!A,this.ignoreFetchAbort=!!z,this.maxEntrySize!==0){if(this.#c!==0&&!T(this.#c))throw new TypeError("maxSize must be a positive integer if specified");if(!T(this.maxEntrySize))throw new TypeError("maxEntrySize must be a positive integer if specified");this.#X()}if(this.allowStale=!!h,this.noDeleteOnStaleGet=!!b,this.updateAgeOnGet=!!o,this.updateAgeOnHas=!!l,this.ttlResolution=T(s)||s===0?s:1,this.ttlAutopurge=!!n,this.ttl=i||0,this.ttl){if(!T(this.ttl))throw new TypeError("ttl must be a positive integer if specified");this.#k()}if(this.#o===0&&this.ttl===0&&this.#c===0)throw new TypeError("At least one of max, maxSize, or ttl is required");if(!this.ttlAutopurge&&!this.#o&&!this.#c){let D="LRU_CACHE_UNBOUNDED";B(D)&&(k.add(D),V("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.","UnboundedCacheWarning",D,u))}}getRemainingTTL(t){return this.#s.has(t)?1/0:0}#k(){let t=new W(this.#o),e=new W(this.#o);this.#d=t,this.#F=e;let i=this.ttlAutopurge?Array.from({length:this.#o}):void 0;this.#g=i,this.#H=(h,r,c=this.#w.now())=>{e[h]=r!==0?c:0,t[h]=r,s(h,r)},this.#D=h=>{e[h]=t[h]!==0?this.#w.now():0,s(h,t[h])};let s=this.ttlAutopurge?(h,r)=>{if(i?.[h]&&(clearTimeout(i[h]),i[h]=void 0),r&&r!==0&&i){let c=setTimeout(()=>{this.#p(h)?(this.#v(this.#i[h],"expire"),i[h]=void 0):s(h,l(h))},r+1);c.unref&&c.unref(),i[h]=c}}:()=>{};this.#E=(h,r)=>{if(t[r]){let c=t[r],w=e[r];if(!c||!w)return;h.ttl=c,h.start=w,h.now=n||o();let _=h.now-w;h.remainingTTL=c-_}};let n=0,o=()=>{let h=this.#w.now();if(this.ttlResolution>0){n=h;let r=setTimeout(()=>n=0,this.ttlResolution);r.unref&&r.unref()}return h};this.getRemainingTTL=h=>{let r=this.#s.get(h);return r===void 0?0:l(r)};let l=h=>{let r=t[h],c=e[h];if(!r||!c)return 1/0;let w=(n||o())-c;return r-w};this.#p=h=>{let r=e[h],c=t[h];return!!c&&!!r&&(n||o())-r>c}}#D=()=>{};#E=()=>{};#H=()=>{};#p=()=>!1;#X(){let t=new W(this.#o);this.#b=0,this.#_=t,this.#C=e=>{this.#b-=t[e],t[e]=0},this.#N=(e,i,s,n)=>{if(!T(s)){if(this.#e(i))return this.backgroundFetchSize;if(n){if(typeof n!="function")throw new TypeError("sizeCalculation must be a function");if(s=n(i,e),!T(s))throw new TypeError("sizeCalculation return invalid (expect positive integer)")}else throw new TypeError("invalid size value (must be positive integer). When maxSize or maxEntrySize is used, sizeCalculation or size must be set.")}return s},this.#I=(e,i,s)=>{if(t[e]=i,this.#c){let n=this.#c-t[e];for(;this.#b>n;)this.#P(!0)}this.#b+=t[e],s&&(s.entrySize=i,s.totalCalculatedSize=this.#b)}}#C=t=>{};#I=(t,e,i)=>{};#N=(t,e,i,s)=>{if(i||s)throw new TypeError("cannot set size without setting maxSize or maxEntrySize on cache");return 0};*#A({allowStale:t=this.allowStale}={}){if(this.#n)for(let e=this.#h;this.#V(e)&&((t||!this.#p(e))&&(yield e),e!==this.#a);)e=this.#u[e]}*#z({allowStale:t=this.allowStale}={}){if(this.#n)for(let e=this.#a;this.#V(e)&&((t||!this.#p(e))&&(yield e),e!==this.#h);)e=this.#l[e]}#V(t){return t!==void 0&&this.#s.get(this.#i[t])===t}*entries(){for(let t of this.#A())this.#t[t]!==void 0&&this.#i[t]!==void 0&&!this.#e(this.#t[t])&&(yield[this.#i[t],this.#t[t]])}*rentries(){for(let t of this.#z())this.#t[t]!==void 0&&this.#i[t]!==void 0&&!this.#e(this.#t[t])&&(yield[this.#i[t],this.#t[t]])}*keys(){for(let t of this.#A()){let e=this.#i[t];e!==void 0&&!this.#e(this.#t[t])&&(yield e)}}*rkeys(){for(let t of this.#z()){let e=this.#i[t];e!==void 0&&!this.#e(this.#t[t])&&(yield e)}}*values(){for(let t of this.#A())this.#t[t]!==void 0&&!this.#e(this.#t[t])&&(yield this.#t[t])}*rvalues(){for(let t of this.#z())this.#t[t]!==void 0&&!this.#e(this.#t[t])&&(yield this.#t[t])}[Symbol.iterator](){return this.entries()}[Symbol.toStringTag]="LRUCache";find(t,e={}){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;if(n!==void 0&&t(n,this.#i[i],this))return this.#L(this.#i[i],e)}}forEach(t,e=this){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&t.call(e,n,this.#i[i],this)}}rforEach(t,e=this){for(let i of this.#z()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&t.call(e,n,this.#i[i],this)}}purgeStale(){let t=!1;for(let e of this.#z({allowStale:!0}))this.#p(e)&&(this.#v(this.#i[e],"expire"),t=!0);return t}info(t){let e=this.#s.get(t);if(e===void 0)return;let i=this.#t[e],s=this.#e(i)?i.__staleWhileFetching:i;if(s===void 0)return;let n={value:s};if(this.#d&&this.#F){let o=this.#d[e],l=this.#F[e];if(o&&l){let h=o-(this.#w.now()-l);n.ttl=h,n.start=Date.now()}}return this.#_&&(n.size=this.#_[e]),n}dump(){let t=[];for(let e of this.#A({allowStale:!0})){let i=this.#i[e],s=this.#t[e],n=this.#e(s)?s.__staleWhileFetching:s;if(n===void 0||i===void 0)continue;let o={value:n};if(this.#d&&this.#F){o.ttl=this.#d[e];let l=this.#w.now()-this.#F[e];o.start=Math.floor(Date.now()-l)}this.#_&&(o.size=this.#_[e]),t.unshift([i,o])}return t}load(t){this.clear();for(let[e,i]of t){if(i.start){let s=Date.now()-i.start;i.start=this.#w.now()-s}this.#O(e,i.value,i)}}set(t,e,i={}){let{status:s=g.metrics.hasSubscribers?{}:void 0}=i;i.status=s,s&&(s.op="set",s.key=t,e!==void 0&&(s.value=e),s.cache=this);let n=this.#O(t,e,i);return s&&g.metrics.hasSubscribers&&g.metrics.publish(s),n}#O(t,e,i,s){let{ttl:n=this.ttl,start:o,noDisposeOnSet:l=this.noDisposeOnSet,sizeCalculation:h=this.sizeCalculation,status:r}=i,c=this.#e(e);if(e===void 0)return r&&(r.set="deleted"),this.delete(t),this;let{noUpdateTTL:w=this.noUpdateTTL}=i;r&&!c&&(r.value=e);let _=this.#N(t,e,i.size||0,h,r);if(this.maxEntrySize&&_>this.maxEntrySize)return this.#v(t,"set"),r&&(r.set="miss",r.maxEntrySizeExceeded=!0),this;let d=this.#n===0?void 0:this.#s.get(t);if(d===void 0)d=this.#n===0?this.#h:this.#y.length!==0?this.#y.pop():this.#n===this.#o?this.#P(!1):this.#n,this.#i[d]=t,this.#t[d]=e,this.#s.set(t,d),this.#l[this.#h]=d,this.#u[d]=this.#h,this.#h=d,this.#n++,this.#I(d,_,r),r&&(r.set="add"),w=!1,this.#R&&!c&&this.#W?.(e,t,"add");else{this.#M(d);let p=this.#t[d];if(e!==p){if(!l)if(this.#e(p)){p!==s&&p.__abortController.abort(new Error("replaced"));let{__staleWhileFetching:f}=p;f!==void 0&&f!==e&&(this.#T&&this.#m?.(f,t,"set"),this.#f&&this.#r?.push([f,t,"set"]))}else this.#T&&this.#m?.(p,t,"set"),this.#f&&this.#r?.push([p,t,"set"]);if(this.#C(d),this.#I(d,_,r),this.#t[d]=e,!c){let f=p&&this.#e(p)?p.__staleWhileFetching:p,y=f===void 0?"add":e!==f?"replace":"update";r&&(r.set=y,f!==void 0&&(r.oldValue=f)),this.#R&&this.onInsert?.(e,t,y)}}else c||(r&&(r.set="update"),this.#R&&this.onInsert?.(e,t,"update"))}if(n!==0&&!this.#d&&this.#k(),this.#d&&(w||this.#H(d,n,o),r&&this.#E(r,d)),!l&&this.#f&&this.#r){let p=this.#r,f;for(;f=p?.shift();)this.#S?.(...f)}return this}pop(){try{for(;this.#n;){let t=this.#t[this.#a];if(this.#P(!0),this.#e(t)){if(t.__staleWhileFetching)return t.__staleWhileFetching}else if(t!==void 0)return t}}finally{if(this.#f&&this.#r){let t=this.#r,e;for(;e=t?.shift();)this.#S?.(...e)}}}#P(t){let e=this.#a,i=this.#i[e],s=this.#t[e],n=this.#e(s);n&&s.__abortController.abort(new Error("evicted"));let o=n?s.__staleWhileFetching:s;return(this.#T||this.#f)&&o!==void 0&&(this.#T&&this.#m?.(o,i,"evict"),this.#f&&this.#r?.push([o,i,"evict"])),this.#C(e),this.#g?.[e]&&(clearTimeout(this.#g[e]),this.#g[e]=void 0),t&&(this.#i[e]=void 0,this.#t[e]=void 0,this.#y.push(e)),this.#n===1?(this.#a=this.#h=0,this.#y.length=0):this.#a=this.#l[e],this.#s.delete(i),this.#n--,e}has(t,e={}){let{status:i=g.metrics.hasSubscribers?{}:void 0}=e;e.status=i,i&&(i.op="has",i.key=t,i.cache=this);let s=this.#Y(t,e);return g.metrics.hasSubscribers&&g.metrics.publish(i),s}#Y(t,e={}){let{updateAgeOnHas:i=this.updateAgeOnHas,status:s}=e,n=this.#s.get(t);if(n!==void 0){let o=this.#t[n];if(this.#e(o)&&o.__staleWhileFetching===void 0)return!1;if(this.#p(n))s&&(s.has="stale",this.#E(s,n));else return i&&this.#D(n),s&&(s.has="hit",this.#E(s,n)),!0}else s&&(s.has="miss");return!1}peek(t,e={}){let{status:i=C()?{}:void 0}=e;i&&(i.op="peek",i.key=t,i.cache=this),e.status=i;let s=this.#J(t,e);return g.metrics.hasSubscribers&&g.metrics.publish(i),s}#J(t,e){let{status:i,allowStale:s=this.allowStale}=e,n=this.#s.get(t);if(n===void 0||!s&&this.#p(n)){i&&(i.peek=n===void 0?"miss":"stale");return}let o=this.#t[n],l=this.#e(o)?o.__staleWhileFetching:o;return i&&(l!==void 0?(i.peek="hit",i.value=l):i.peek="miss"),l}#G(t,e,i,s){let n=e===void 0?void 0:this.#t[e];if(this.#e(n))return n;let o=new AbortController,{signal:l}=i;l?.addEventListener("abort",()=>o.abort(l.reason),{signal:o.signal});let h={signal:o.signal,options:i,context:s},r=(f,y=!1)=>{let{aborted:a}=o.signal,S=i.ignoreFetchAbort&&f!==void 0,F=i.ignoreFetchAbort||!!(i.allowStaleOnFetchAbort&&f!==void 0);if(i.status&&(a&&!y?(i.status.fetchAborted=!0,i.status.fetchError=o.signal.reason,S&&(i.status.fetchAbortIgnored=!0)):i.status.fetchResolved=!0),a&&!S&&!y)return w(o.signal.reason,F);let b=d,m=this.#t[e];return(m===d||m===void 0&&S&&y)&&(f===void 0?b.__staleWhileFetching!==void 0?this.#t[e]=b.__staleWhileFetching:this.#v(t,"fetch"):(i.status&&(i.status.fetchUpdated=!0),this.#O(t,f,h.options,b))),f},c=f=>(i.status&&(i.status.fetchRejected=!0,i.status.fetchError=f),w(f,!1)),w=(f,y)=>{let{aborted:a}=o.signal,S=a&&i.allowStaleOnFetchAbort,F=S||i.allowStaleOnFetchRejection,b=F||i.noDeleteOnFetchRejection,m=d;if(this.#t[e]===d&&(!b||!y&&m.__staleWhileFetching===void 0?this.#v(t,"fetch"):S||(this.#t[e]=m.__staleWhileFetching)),F)return i.status&&m.__staleWhileFetching!==void 0&&(i.status.returnedStale=!0),m.__staleWhileFetching;if(m.__returned===m)throw f},_=(f,y)=>{let a=this.#x?.(t,n,h);o.signal.addEventListener("abort",()=>{(!i.ignoreFetchAbort||i.allowStaleOnFetchAbort)&&(f(void 0),i.allowStaleOnFetchAbort&&(f=S=>r(S,!0)))}),a&&a instanceof Promise?a.then(S=>f(S===void 0?void 0:S),y):a!==void 0&&f(a)};i.status&&(i.status.fetchDispatched=!0);let d=new Promise(_).then(r,c),p=Object.assign(d,{__abortController:o,__staleWhileFetching:n,__returned:void 0});return e===void 0?(this.#O(t,p,{...h.options,status:void 0}),e=this.#s.get(t)):this.#t[e]=p,p}#e(t){if(!this.#U)return!1;let e=t;return!!e&&e instanceof Promise&&e.hasOwnProperty("__staleWhileFetching")&&e.__abortController instanceof AbortController}fetch(t,e={}){let i=g.tracing.hasSubscribers,{status:s=C()?{}:void 0}=e;e.status=s,s&&e.context&&(s.context=e.context);let n=this.#B(t,e);return s&&i&&(s.trace=!0,g.tracing.tracePromise(()=>n,s).catch(()=>{})),n}async#B(t,e={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,ttl:o=this.ttl,noDisposeOnSet:l=this.noDisposeOnSet,size:h=0,sizeCalculation:r=this.sizeCalculation,noUpdateTTL:c=this.noUpdateTTL,noDeleteOnFetchRejection:w=this.noDeleteOnFetchRejection,allowStaleOnFetchRejection:_=this.allowStaleOnFetchRejection,ignoreFetchAbort:d=this.ignoreFetchAbort,allowStaleOnFetchAbort:p=this.allowStaleOnFetchAbort,context:f,forceRefresh:y=!1,status:a,signal:S}=e;if(a&&(a.op="fetch",a.key=t,y&&(a.forceRefresh=!0),a.cache=this),!this.#U)return a&&(a.fetch="get"),this.#L(t,{allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,status:a});let F={allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,ttl:o,noDisposeOnSet:l,size:h,sizeCalculation:r,noUpdateTTL:c,noDeleteOnFetchRejection:w,allowStaleOnFetchRejection:_,allowStaleOnFetchAbort:p,ignoreFetchAbort:d,status:a,signal:S},b=this.#s.get(t);if(b===void 0){a&&(a.fetch="miss");let m=this.#G(t,b,F,f);return m.__returned=m}else{let m=this.#t[b];if(this.#e(m)){let E=i&&m.__staleWhileFetching!==void 0;return a&&(a.fetch="inflight",E&&(a.returnedStale=!0)),E?m.__staleWhileFetching:m.__returned=m}let A=this.#p(b);if(!y&&!A)return a&&(a.fetch="hit"),this.#M(b),s&&this.#D(b),a&&this.#E(a,b),m;let z=this.#G(t,b,F,f),v=z.__staleWhileFetching!==void 0&&i;return a&&(a.fetch=A?"stale":"refresh",v&&A&&(a.returnedStale=!0)),v?z.__staleWhileFetching:z.__returned=z}}forceFetch(t,e={}){let i=g.tracing.hasSubscribers,{status:s=C()?{}:void 0}=e;e.status=s,s&&e.context&&(s.context=e.context);let n=this.#K(t,e);return s&&i&&(s.trace=!0,g.tracing.tracePromise(()=>n,s).catch(()=>{})),n}async#K(t,e={}){let i=await this.#B(t,e);if(i===void 0)throw new Error("fetch() returned undefined");return i}memo(t,e={}){let{status:i=g.metrics.hasSubscribers?{}:void 0}=e;e.status=i,i&&(i.op="memo",i.key=t,e.context&&(i.context=e.context),i.cache=this);let s=this.#Q(t,e);return i&&(i.value=s),g.metrics.hasSubscribers&&g.metrics.publish(i),s}#Q(t,e={}){let i=this.#j;if(!i)throw new Error("no memoMethod provided to constructor");let{context:s,status:n,forceRefresh:o,...l}=e;n&&o&&(n.forceRefresh=!0);let h=this.#L(t,l),r=o||h===void 0;if(n&&(n.memo=r?"miss":"hit",r||(n.value=h)),!r)return h;let c=i(t,h,{options:l,context:s});return n&&(n.value=c),this.#O(t,c,l),c}get(t,e={}){let{status:i=g.metrics.hasSubscribers?{}:void 0}=e;e.status=i,i&&(i.op="get",i.key=t,i.cache=this);let s=this.#L(t,e);return i&&(s!==void 0&&(i.value=s),g.metrics.hasSubscribers&&g.metrics.publish(i)),s}#L(t,e={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,status:o}=e,l=this.#s.get(t);if(l===void 0){o&&(o.get="miss");return}let h=this.#t[l],r=this.#e(h);return o&&this.#E(o,l),this.#p(l)?r?(o&&(o.get="stale-fetching"),i&&h.__staleWhileFetching!==void 0?(o&&(o.returnedStale=!0),h.__staleWhileFetching):void 0):(n||this.#v(t,"expire"),o&&(o.get="stale"),i?(o&&(o.returnedStale=!0),h):void 0):(o&&(o.get=r?"fetching":"hit"),this.#M(l),s&&this.#D(l),r?h.__staleWhileFetching:h)}#q(t,e){this.#u[e]=t,this.#l[t]=e}#M(t){t!==this.#h&&(t===this.#a?this.#a=this.#l[t]:this.#q(this.#u[t],this.#l[t]),this.#q(this.#h,t),this.#h=t)}delete(t){return this.#v(t,"delete")}#v(t,e){g.metrics.hasSubscribers&&g.metrics.publish({op:"delete",delete:e,key:t,cache:this});let i=!1;if(this.#n!==0){let s=this.#s.get(t);if(s!==void 0)if(this.#g?.[s]&&(clearTimeout(this.#g[s]),this.#g[s]=void 0),i=!0,this.#n===1)this.#$(e);else{this.#C(s);let n=this.#t[s];if(this.#e(n)?n.__abortController.abort(new Error("deleted")):(this.#T||this.#f)&&(this.#T&&this.#m?.(n,t,e),this.#f&&this.#r?.push([n,t,e])),this.#s.delete(t),this.#i[s]=void 0,this.#t[s]=void 0,s===this.#h)this.#h=this.#u[s];else if(s===this.#a)this.#a=this.#l[s];else{let o=this.#u[s];this.#l[o]=this.#l[s];let l=this.#l[s];this.#u[l]=this.#u[s]}this.#n--,this.#y.push(s)}}if(this.#f&&this.#r?.length){let s=this.#r,n;for(;n=s?.shift();)this.#S?.(...n)}return i}clear(){return this.#$("delete")}#$(t){for(let e of this.#z({allowStale:!0})){let i=this.#t[e];if(this.#e(i))i.__abortController.abort(new Error("deleted"));else{let s=this.#i[e];this.#T&&this.#m?.(i,s,t),this.#f&&this.#r?.push([i,s,t])}}if(this.#s.clear(),this.#t.fill(void 0),this.#i.fill(void 0),this.#d&&this.#F){this.#d.fill(0),this.#F.fill(0);for(let e of this.#g??[])e!==void 0&&clearTimeout(e);this.#g?.fill(void 0)}if(this.#_&&this.#_.fill(0),this.#a=0,this.#h=0,this.#y.length=0,this.#b=0,this.#n=0,this.#f&&this.#r){let e=this.#r,i;for(;i=e?.shift();)this.#S?.(...i)}}};exports.LRUCache=M;
//# sourceMappingURL=index.min.js.map
diff --git a/deps/npm/node_modules/lru-cache/dist/commonjs/node/index.js b/deps/npm/node_modules/lru-cache/dist/commonjs/node/index.js
index 6b8268b0ea9..3f5cceec7ae 100644
--- a/deps/npm/node_modules/lru-cache/dist/commonjs/node/index.js
+++ b/deps/npm/node_modules/lru-cache/dist/commonjs/node/index.js
@@ -412,17 +412,17 @@ class LRUCache {
this.#setItemTTL = (index, ttl, start = this.#perf.now()) => {
starts[index] = ttl !== 0 ? start : 0;
ttls[index] = ttl;
- setPurgetTimer(index, ttl);
+ setPurgeTimer(index, ttl);
};
this.#updateItemAge = index => {
starts[index] = ttls[index] !== 0 ? this.#perf.now() : 0;
- setPurgetTimer(index, ttls[index]);
+ setPurgeTimer(index, ttls[index]);
};
// clear out the purge timer if we're setting TTL to 0, and
// previously had a ttl purge timer running, so it doesn't
// fire unnecessarily. Don't need to do this if we're not doing
// autopurge.
- const setPurgetTimer = !this.ttlAutopurge ?
+ const setPurgeTimer = !this.ttlAutopurge ?
() => { }
: (index, ttl) => {
if (purgeTimers?.[index]) {
@@ -433,6 +433,10 @@ class LRUCache {
const t = setTimeout(() => {
if (this.#isStale(index)) {
this.#delete(this.#keyList[index], 'expire');
+ purgeTimers[index] = undefined;
+ }
+ else {
+ setPurgeTimer(index, getRemainingTTL(index));
}
}, ttl + 1);
// unref() not supported on all platforms
@@ -482,6 +486,9 @@ class LRUCache {
if (index === undefined) {
return 0;
}
+ return getRemainingTTL(index);
+ };
+ const getRemainingTTL = (index) => {
const ttl = ttls[index];
const start = starts[index];
if (!ttl || !start) {
@@ -1621,7 +1628,7 @@ class LRUCache {
const index = this.#keyMap.get(k);
if (index !== undefined) {
if (this.#autopurgeTimers?.[index]) {
- clearTimeout(this.#autopurgeTimers?.[index]);
+ clearTimeout(this.#autopurgeTimers[index]);
this.#autopurgeTimers[index] = undefined;
}
deleted = true;
diff --git a/deps/npm/node_modules/lru-cache/dist/commonjs/node/index.min.js b/deps/npm/node_modules/lru-cache/dist/commonjs/node/index.min.js
index a03fc771913..122a09e5af2 100644
--- a/deps/npm/node_modules/lru-cache/dist/commonjs/node/index.min.js
+++ b/deps/npm/node_modules/lru-cache/dist/commonjs/node/index.min.js
@@ -1,2 +1,2 @@
-"use strict";var j=(c,t)=>()=>(t||c((t={exports:{}}).exports,t),t.exports);var I=j(O=>{"use strict";Object.defineProperty(O,"__esModule",{value:!0});O.tracing=O.metrics=void 0;var U=require("node:diagnostics_channel");O.metrics=(0,U.channel)("lru-cache:metrics");O.tracing=(0,U.tracingChannel)("lru-cache")});var P=j(D=>{"use strict";Object.defineProperty(D,"__esModule",{value:!0});D.defaultPerf=void 0;D.defaultPerf=typeof performance=="object"&&performance&&typeof performance.now=="function"?performance:Date});Object.defineProperty(exports,"__esModule",{value:!0});exports.LRUCache=void 0;var g=I(),N=P(),C=()=>g.metrics.hasSubscribers||g.tracing.hasSubscribers,k=new Set,G=typeof process=="object"&&process?process:{},V=(c,t,e,i)=>{typeof G.emitWarning=="function"?G.emitWarning(c,t,e,i):console.error(`[${e}] ${t}: ${c}`)},q=c=>!k.has(c);var T=c=>!!c&&c===Math.floor(c)&&c>0&&isFinite(c),H=c=>T(c)?c<=Math.pow(2,8)?Uint8Array:c<=Math.pow(2,16)?Uint16Array:c<=Math.pow(2,32)?Uint32Array:c<=Number.MAX_SAFE_INTEGER?W:null:null,W=class extends Array{constructor(t){super(t),this.fill(0)}},x=class c{heap;length;static#o=!1;static create(t){let e=H(t);if(!e)return[];c.#o=!0;let i=new c(t,e);return c.#o=!1,i}constructor(t,e){if(!c.#o)throw new TypeError("instantiate Stack using Stack.create(n)");this.heap=new e(t),this.length=0}push(t){this.heap[this.length++]=t}pop(){return this.heap[--this.length]}},L=class c{#o;#c;#m;#W;#S;#M;#j;#w;get perf(){return this.#w}ttl;ttlResolution;ttlAutopurge;updateAgeOnGet;updateAgeOnHas;allowStale;noDisposeOnSet;noUpdateTTL;maxEntrySize;sizeCalculation;noDeleteOnFetchRejection;noDeleteOnStaleGet;allowStaleOnFetchAbort;allowStaleOnFetchRejection;ignoreFetchAbort;backgroundFetchSize;#n;#b;#s;#i;#t;#l;#u;#a;#h;#_;#r;#y;#F;#d;#g;#T;#U;#f;#D;static unsafeExposeInternals(t){return{starts:t.#F,ttls:t.#d,autopurgeTimers:t.#g,sizes:t.#y,keyMap:t.#s,keyList:t.#i,valList:t.#t,next:t.#l,prev:t.#u,get head(){return t.#a},get tail(){return t.#h},free:t.#_,isBackgroundFetch:e=>t.#e(e),backgroundFetch:(e,i,s,n)=>t.#G(e,i,s,n),moveToTail:e=>t.#L(e),indexes:e=>t.#A(e),rindexes:e=>t.#z(e),isStale:e=>t.#p(e)}}get max(){return this.#o}get maxSize(){return this.#c}get calculatedSize(){return this.#b}get size(){return this.#n}get fetchMethod(){return this.#M}get memoMethod(){return this.#j}get dispose(){return this.#m}get onInsert(){return this.#W}get disposeAfter(){return this.#S}constructor(t){let{max:e=0,ttl:i,ttlResolution:s=1,ttlAutopurge:n,updateAgeOnGet:r,updateAgeOnHas:h,allowStale:a,dispose:o,onInsert:d,disposeAfter:_,noDisposeOnSet:y,noUpdateTTL:u,maxSize:p=0,maxEntrySize:f=0,sizeCalculation:b,fetchMethod:l,memoMethod:S,noDeleteOnFetchRejection:F,noDeleteOnStaleGet:w,allowStaleOnFetchRejection:m,allowStaleOnFetchAbort:A,ignoreFetchAbort:z,backgroundFetchSize:M=1,perf:v}=t;if(this.backgroundFetchSize=M,v!==void 0&&typeof v?.now!="function")throw new TypeError("perf option must have a now() method if specified");if(this.#w=v??N.defaultPerf,e!==0&&!T(e))throw new TypeError("max option must be a nonnegative integer");let E=e?H(e):Array;if(!E)throw new Error("invalid max value: "+e);if(this.#o=e,this.#c=p,this.maxEntrySize=f||this.#c,this.sizeCalculation=b,this.sizeCalculation){if(!this.#c&&!this.maxEntrySize)throw new TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");if(typeof this.sizeCalculation!="function")throw new TypeError("sizeCalculation set to non-function")}if(S!==void 0&&typeof S!="function")throw new TypeError("memoMethod must be a function if defined");if(this.#j=S,l!==void 0&&typeof l!="function")throw new TypeError("fetchMethod must be a function if specified");if(this.#M=l,this.#U=!!l,this.#s=new Map,this.#i=Array.from({length:e}).fill(void 0),this.#t=Array.from({length:e}).fill(void 0),this.#l=new E(e),this.#u=new E(e),this.#a=0,this.#h=0,this.#_=x.create(e),this.#n=0,this.#b=0,typeof o=="function"&&(this.#m=o),typeof d=="function"&&(this.#W=d),typeof _=="function"?(this.#S=_,this.#r=[]):(this.#S=void 0,this.#r=void 0),this.#T=!!this.#m,this.#D=!!this.#W,this.#f=!!this.#S,this.noDisposeOnSet=!!y,this.noUpdateTTL=!!u,this.noDeleteOnFetchRejection=!!F,this.allowStaleOnFetchRejection=!!m,this.allowStaleOnFetchAbort=!!A,this.ignoreFetchAbort=!!z,this.maxEntrySize!==0){if(this.#c!==0&&!T(this.#c))throw new TypeError("maxSize must be a positive integer if specified");if(!T(this.maxEntrySize))throw new TypeError("maxEntrySize must be a positive integer if specified");this.#X()}if(this.allowStale=!!a,this.noDeleteOnStaleGet=!!w,this.updateAgeOnGet=!!r,this.updateAgeOnHas=!!h,this.ttlResolution=T(s)||s===0?s:1,this.ttlAutopurge=!!n,this.ttl=i||0,this.ttl){if(!T(this.ttl))throw new TypeError("ttl must be a positive integer if specified");this.#k()}if(this.#o===0&&this.ttl===0&&this.#c===0)throw new TypeError("At least one of max, maxSize, or ttl is required");if(!this.ttlAutopurge&&!this.#o&&!this.#c){let R="LRU_CACHE_UNBOUNDED";q(R)&&(k.add(R),V("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.","UnboundedCacheWarning",R,c))}}getRemainingTTL(t){return this.#s.has(t)?1/0:0}#k(){let t=new W(this.#o),e=new W(this.#o);this.#d=t,this.#F=e;let i=this.ttlAutopurge?Array.from({length:this.#o}):void 0;this.#g=i,this.#H=(h,a,o=this.#w.now())=>{e[h]=a!==0?o:0,t[h]=a,s(h,a)},this.#R=h=>{e[h]=t[h]!==0?this.#w.now():0,s(h,t[h])};let s=this.ttlAutopurge?(h,a)=>{if(i?.[h]&&(clearTimeout(i[h]),i[h]=void 0),a&&a!==0&&i){let o=setTimeout(()=>{this.#p(h)&&this.#v(this.#i[h],"expire")},a+1);o.unref&&o.unref(),i[h]=o}}:()=>{};this.#E=(h,a)=>{if(t[a]){let o=t[a],d=e[a];if(!o||!d)return;h.ttl=o,h.start=d,h.now=n||r();let _=h.now-d;h.remainingTTL=o-_}};let n=0,r=()=>{let h=this.#w.now();if(this.ttlResolution>0){n=h;let a=setTimeout(()=>n=0,this.ttlResolution);a.unref&&a.unref()}return h};this.getRemainingTTL=h=>{let a=this.#s.get(h);if(a===void 0)return 0;let o=t[a],d=e[a];if(!o||!d)return 1/0;let _=(n||r())-d;return o-_},this.#p=h=>{let a=e[h],o=t[h];return!!o&&!!a&&(n||r())-a>o}}#R=()=>{};#E=()=>{};#H=()=>{};#p=()=>!1;#X(){let t=new W(this.#o);this.#b=0,this.#y=t,this.#C=e=>{this.#b-=t[e],t[e]=0},this.#N=(e,i,s,n)=>{if(!T(s)){if(this.#e(i))return this.backgroundFetchSize;if(n){if(typeof n!="function")throw new TypeError("sizeCalculation must be a function");if(s=n(i,e),!T(s))throw new TypeError("sizeCalculation return invalid (expect positive integer)")}else throw new TypeError("invalid size value (must be positive integer). When maxSize or maxEntrySize is used, sizeCalculation or size must be set.")}return s},this.#I=(e,i,s)=>{if(t[e]=i,this.#c){let n=this.#c-t[e];for(;this.#b>n;)this.#P(!0)}this.#b+=t[e],s&&(s.entrySize=i,s.totalCalculatedSize=this.#b)}}#C=t=>{};#I=(t,e,i)=>{};#N=(t,e,i,s)=>{if(i||s)throw new TypeError("cannot set size without setting maxSize or maxEntrySize on cache");return 0};*#A({allowStale:t=this.allowStale}={}){if(this.#n)for(let e=this.#h;this.#V(e)&&((t||!this.#p(e))&&(yield e),e!==this.#a);)e=this.#u[e]}*#z({allowStale:t=this.allowStale}={}){if(this.#n)for(let e=this.#a;this.#V(e)&&((t||!this.#p(e))&&(yield e),e!==this.#h);)e=this.#l[e]}#V(t){return t!==void 0&&this.#s.get(this.#i[t])===t}*entries(){for(let t of this.#A())this.#t[t]!==void 0&&this.#i[t]!==void 0&&!this.#e(this.#t[t])&&(yield[this.#i[t],this.#t[t]])}*rentries(){for(let t of this.#z())this.#t[t]!==void 0&&this.#i[t]!==void 0&&!this.#e(this.#t[t])&&(yield[this.#i[t],this.#t[t]])}*keys(){for(let t of this.#A()){let e=this.#i[t];e!==void 0&&!this.#e(this.#t[t])&&(yield e)}}*rkeys(){for(let t of this.#z()){let e=this.#i[t];e!==void 0&&!this.#e(this.#t[t])&&(yield e)}}*values(){for(let t of this.#A())this.#t[t]!==void 0&&!this.#e(this.#t[t])&&(yield this.#t[t])}*rvalues(){for(let t of this.#z())this.#t[t]!==void 0&&!this.#e(this.#t[t])&&(yield this.#t[t])}[Symbol.iterator](){return this.entries()}[Symbol.toStringTag]="LRUCache";find(t,e={}){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;if(n!==void 0&&t(n,this.#i[i],this))return this.#x(this.#i[i],e)}}forEach(t,e=this){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&t.call(e,n,this.#i[i],this)}}rforEach(t,e=this){for(let i of this.#z()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&t.call(e,n,this.#i[i],this)}}purgeStale(){let t=!1;for(let e of this.#z({allowStale:!0}))this.#p(e)&&(this.#v(this.#i[e],"expire"),t=!0);return t}info(t){let e=this.#s.get(t);if(e===void 0)return;let i=this.#t[e],s=this.#e(i)?i.__staleWhileFetching:i;if(s===void 0)return;let n={value:s};if(this.#d&&this.#F){let r=this.#d[e],h=this.#F[e];if(r&&h){let a=r-(this.#w.now()-h);n.ttl=a,n.start=Date.now()}}return this.#y&&(n.size=this.#y[e]),n}dump(){let t=[];for(let e of this.#A({allowStale:!0})){let i=this.#i[e],s=this.#t[e],n=this.#e(s)?s.__staleWhileFetching:s;if(n===void 0||i===void 0)continue;let r={value:n};if(this.#d&&this.#F){r.ttl=this.#d[e];let h=this.#w.now()-this.#F[e];r.start=Math.floor(Date.now()-h)}this.#y&&(r.size=this.#y[e]),t.unshift([i,r])}return t}load(t){this.clear();for(let[e,i]of t){if(i.start){let s=Date.now()-i.start;i.start=this.#w.now()-s}this.#O(e,i.value,i)}}set(t,e,i={}){let{status:s=g.metrics.hasSubscribers?{}:void 0}=i;i.status=s,s&&(s.op="set",s.key=t,e!==void 0&&(s.value=e),s.cache=this);let n=this.#O(t,e,i);return s&&g.metrics.hasSubscribers&&g.metrics.publish(s),n}#O(t,e,i,s){let{ttl:n=this.ttl,start:r,noDisposeOnSet:h=this.noDisposeOnSet,sizeCalculation:a=this.sizeCalculation,status:o}=i,d=this.#e(e);if(e===void 0)return o&&(o.set="deleted"),this.delete(t),this;let{noUpdateTTL:_=this.noUpdateTTL}=i;o&&!d&&(o.value=e);let y=this.#N(t,e,i.size||0,a,o);if(this.maxEntrySize&&y>this.maxEntrySize)return this.#v(t,"set"),o&&(o.set="miss",o.maxEntrySizeExceeded=!0),this;let u=this.#n===0?void 0:this.#s.get(t);if(u===void 0)u=this.#n===0?this.#h:this.#_.length!==0?this.#_.pop():this.#n===this.#o?this.#P(!1):this.#n,this.#i[u]=t,this.#t[u]=e,this.#s.set(t,u),this.#l[this.#h]=u,this.#u[u]=this.#h,this.#h=u,this.#n++,this.#I(u,y,o),o&&(o.set="add"),_=!1,this.#D&&!d&&this.#W?.(e,t,"add");else{this.#L(u);let p=this.#t[u];if(e!==p){if(!h)if(this.#e(p)){p!==s&&p.__abortController.abort(new Error("replaced"));let{__staleWhileFetching:f}=p;f!==void 0&&f!==e&&(this.#T&&this.#m?.(f,t,"set"),this.#f&&this.#r?.push([f,t,"set"]))}else this.#T&&this.#m?.(p,t,"set"),this.#f&&this.#r?.push([p,t,"set"]);if(this.#C(u),this.#I(u,y,o),this.#t[u]=e,!d){let f=p&&this.#e(p)?p.__staleWhileFetching:p,b=f===void 0?"add":e!==f?"replace":"update";o&&(o.set=b,f!==void 0&&(o.oldValue=f)),this.#D&&this.onInsert?.(e,t,b)}}else d||(o&&(o.set="update"),this.#D&&this.onInsert?.(e,t,"update"))}if(n!==0&&!this.#d&&this.#k(),this.#d&&(_||this.#H(u,n,r),o&&this.#E(o,u)),!h&&this.#f&&this.#r){let p=this.#r,f;for(;f=p?.shift();)this.#S?.(...f)}return this}pop(){try{for(;this.#n;){let t=this.#t[this.#a];if(this.#P(!0),this.#e(t)){if(t.__staleWhileFetching)return t.__staleWhileFetching}else if(t!==void 0)return t}}finally{if(this.#f&&this.#r){let t=this.#r,e;for(;e=t?.shift();)this.#S?.(...e)}}}#P(t){let e=this.#a,i=this.#i[e],s=this.#t[e],n=this.#e(s);n&&s.__abortController.abort(new Error("evicted"));let r=n?s.__staleWhileFetching:s;return(this.#T||this.#f)&&r!==void 0&&(this.#T&&this.#m?.(r,i,"evict"),this.#f&&this.#r?.push([r,i,"evict"])),this.#C(e),this.#g?.[e]&&(clearTimeout(this.#g[e]),this.#g[e]=void 0),t&&(this.#i[e]=void 0,this.#t[e]=void 0,this.#_.push(e)),this.#n===1?(this.#a=this.#h=0,this.#_.length=0):this.#a=this.#l[e],this.#s.delete(i),this.#n--,e}has(t,e={}){let{status:i=g.metrics.hasSubscribers?{}:void 0}=e;e.status=i,i&&(i.op="has",i.key=t,i.cache=this);let s=this.#Y(t,e);return g.metrics.hasSubscribers&&g.metrics.publish(i),s}#Y(t,e={}){let{updateAgeOnHas:i=this.updateAgeOnHas,status:s}=e,n=this.#s.get(t);if(n!==void 0){let r=this.#t[n];if(this.#e(r)&&r.__staleWhileFetching===void 0)return!1;if(this.#p(n))s&&(s.has="stale",this.#E(s,n));else return i&&this.#R(n),s&&(s.has="hit",this.#E(s,n)),!0}else s&&(s.has="miss");return!1}peek(t,e={}){let{status:i=C()?{}:void 0}=e;i&&(i.op="peek",i.key=t,i.cache=this),e.status=i;let s=this.#J(t,e);return g.metrics.hasSubscribers&&g.metrics.publish(i),s}#J(t,e){let{status:i,allowStale:s=this.allowStale}=e,n=this.#s.get(t);if(n===void 0||!s&&this.#p(n)){i&&(i.peek=n===void 0?"miss":"stale");return}let r=this.#t[n],h=this.#e(r)?r.__staleWhileFetching:r;return i&&(h!==void 0?(i.peek="hit",i.value=h):i.peek="miss"),h}#G(t,e,i,s){let n=e===void 0?void 0:this.#t[e];if(this.#e(n))return n;let r=new AbortController,{signal:h}=i;h?.addEventListener("abort",()=>r.abort(h.reason),{signal:r.signal});let a={signal:r.signal,options:i,context:s},o=(f,b=!1)=>{let{aborted:l}=r.signal,S=i.ignoreFetchAbort&&f!==void 0,F=i.ignoreFetchAbort||!!(i.allowStaleOnFetchAbort&&f!==void 0);if(i.status&&(l&&!b?(i.status.fetchAborted=!0,i.status.fetchError=r.signal.reason,S&&(i.status.fetchAbortIgnored=!0)):i.status.fetchResolved=!0),l&&!S&&!b)return _(r.signal.reason,F);let w=u,m=this.#t[e];return(m===u||m===void 0&&S&&b)&&(f===void 0?w.__staleWhileFetching!==void 0?this.#t[e]=w.__staleWhileFetching:this.#v(t,"fetch"):(i.status&&(i.status.fetchUpdated=!0),this.#O(t,f,a.options,w))),f},d=f=>(i.status&&(i.status.fetchRejected=!0,i.status.fetchError=f),_(f,!1)),_=(f,b)=>{let{aborted:l}=r.signal,S=l&&i.allowStaleOnFetchAbort,F=S||i.allowStaleOnFetchRejection,w=F||i.noDeleteOnFetchRejection,m=u;if(this.#t[e]===u&&(!w||!b&&m.__staleWhileFetching===void 0?this.#v(t,"fetch"):S||(this.#t[e]=m.__staleWhileFetching)),F)return i.status&&m.__staleWhileFetching!==void 0&&(i.status.returnedStale=!0),m.__staleWhileFetching;if(m.__returned===m)throw f},y=(f,b)=>{let l=this.#M?.(t,n,a);r.signal.addEventListener("abort",()=>{(!i.ignoreFetchAbort||i.allowStaleOnFetchAbort)&&(f(void 0),i.allowStaleOnFetchAbort&&(f=S=>o(S,!0)))}),l&&l instanceof Promise?l.then(S=>f(S===void 0?void 0:S),b):l!==void 0&&f(l)};i.status&&(i.status.fetchDispatched=!0);let u=new Promise(y).then(o,d),p=Object.assign(u,{__abortController:r,__staleWhileFetching:n,__returned:void 0});return e===void 0?(this.#O(t,p,{...a.options,status:void 0}),e=this.#s.get(t)):this.#t[e]=p,p}#e(t){if(!this.#U)return!1;let e=t;return!!e&&e instanceof Promise&&e.hasOwnProperty("__staleWhileFetching")&&e.__abortController instanceof AbortController}fetch(t,e={}){let i=g.tracing.hasSubscribers,{status:s=C()?{}:void 0}=e;e.status=s,s&&e.context&&(s.context=e.context);let n=this.#q(t,e);return s&&i&&(s.trace=!0,g.tracing.tracePromise(()=>n,s).catch(()=>{})),n}async#q(t,e={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,ttl:r=this.ttl,noDisposeOnSet:h=this.noDisposeOnSet,size:a=0,sizeCalculation:o=this.sizeCalculation,noUpdateTTL:d=this.noUpdateTTL,noDeleteOnFetchRejection:_=this.noDeleteOnFetchRejection,allowStaleOnFetchRejection:y=this.allowStaleOnFetchRejection,ignoreFetchAbort:u=this.ignoreFetchAbort,allowStaleOnFetchAbort:p=this.allowStaleOnFetchAbort,context:f,forceRefresh:b=!1,status:l,signal:S}=e;if(l&&(l.op="fetch",l.key=t,b&&(l.forceRefresh=!0),l.cache=this),!this.#U)return l&&(l.fetch="get"),this.#x(t,{allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,status:l});let F={allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,ttl:r,noDisposeOnSet:h,size:a,sizeCalculation:o,noUpdateTTL:d,noDeleteOnFetchRejection:_,allowStaleOnFetchRejection:y,allowStaleOnFetchAbort:p,ignoreFetchAbort:u,status:l,signal:S},w=this.#s.get(t);if(w===void 0){l&&(l.fetch="miss");let m=this.#G(t,w,F,f);return m.__returned=m}else{let m=this.#t[w];if(this.#e(m)){let E=i&&m.__staleWhileFetching!==void 0;return l&&(l.fetch="inflight",E&&(l.returnedStale=!0)),E?m.__staleWhileFetching:m.__returned=m}let A=this.#p(w);if(!b&&!A)return l&&(l.fetch="hit"),this.#L(w),s&&this.#R(w),l&&this.#E(l,w),m;let z=this.#G(t,w,F,f),v=z.__staleWhileFetching!==void 0&&i;return l&&(l.fetch=A?"stale":"refresh",v&&A&&(l.returnedStale=!0)),v?z.__staleWhileFetching:z.__returned=z}}forceFetch(t,e={}){let i=g.tracing.hasSubscribers,{status:s=C()?{}:void 0}=e;e.status=s,s&&e.context&&(s.context=e.context);let n=this.#K(t,e);return s&&i&&(s.trace=!0,g.tracing.tracePromise(()=>n,s).catch(()=>{})),n}async#K(t,e={}){let i=await this.#q(t,e);if(i===void 0)throw new Error("fetch() returned undefined");return i}memo(t,e={}){let{status:i=g.metrics.hasSubscribers?{}:void 0}=e;e.status=i,i&&(i.op="memo",i.key=t,e.context&&(i.context=e.context),i.cache=this);let s=this.#Q(t,e);return i&&(i.value=s),g.metrics.hasSubscribers&&g.metrics.publish(i),s}#Q(t,e={}){let i=this.#j;if(!i)throw new Error("no memoMethod provided to constructor");let{context:s,status:n,forceRefresh:r,...h}=e;n&&r&&(n.forceRefresh=!0);let a=this.#x(t,h),o=r||a===void 0;if(n&&(n.memo=o?"miss":"hit",o||(n.value=a)),!o)return a;let d=i(t,a,{options:h,context:s});return n&&(n.value=d),this.#O(t,d,h),d}get(t,e={}){let{status:i=g.metrics.hasSubscribers?{}:void 0}=e;e.status=i,i&&(i.op="get",i.key=t,i.cache=this);let s=this.#x(t,e);return i&&(s!==void 0&&(i.value=s),g.metrics.hasSubscribers&&g.metrics.publish(i)),s}#x(t,e={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,status:r}=e,h=this.#s.get(t);if(h===void 0){r&&(r.get="miss");return}let a=this.#t[h],o=this.#e(a);return r&&this.#E(r,h),this.#p(h)?o?(r&&(r.get="stale-fetching"),i&&a.__staleWhileFetching!==void 0?(r&&(r.returnedStale=!0),a.__staleWhileFetching):void 0):(n||this.#v(t,"expire"),r&&(r.get="stale"),i?(r&&(r.returnedStale=!0),a):void 0):(r&&(r.get=o?"fetching":"hit"),this.#L(h),s&&this.#R(h),o?a.__staleWhileFetching:a)}#B(t,e){this.#u[e]=t,this.#l[t]=e}#L(t){t!==this.#h&&(t===this.#a?this.#a=this.#l[t]:this.#B(this.#u[t],this.#l[t]),this.#B(this.#h,t),this.#h=t)}delete(t){return this.#v(t,"delete")}#v(t,e){g.metrics.hasSubscribers&&g.metrics.publish({op:"delete",delete:e,key:t,cache:this});let i=!1;if(this.#n!==0){let s=this.#s.get(t);if(s!==void 0)if(this.#g?.[s]&&(clearTimeout(this.#g?.[s]),this.#g[s]=void 0),i=!0,this.#n===1)this.#$(e);else{this.#C(s);let n=this.#t[s];if(this.#e(n)?n.__abortController.abort(new Error("deleted")):(this.#T||this.#f)&&(this.#T&&this.#m?.(n,t,e),this.#f&&this.#r?.push([n,t,e])),this.#s.delete(t),this.#i[s]=void 0,this.#t[s]=void 0,s===this.#h)this.#h=this.#u[s];else if(s===this.#a)this.#a=this.#l[s];else{let r=this.#u[s];this.#l[r]=this.#l[s];let h=this.#l[s];this.#u[h]=this.#u[s]}this.#n--,this.#_.push(s)}}if(this.#f&&this.#r?.length){let s=this.#r,n;for(;n=s?.shift();)this.#S?.(...n)}return i}clear(){return this.#$("delete")}#$(t){for(let e of this.#z({allowStale:!0})){let i=this.#t[e];if(this.#e(i))i.__abortController.abort(new Error("deleted"));else{let s=this.#i[e];this.#T&&this.#m?.(i,s,t),this.#f&&this.#r?.push([i,s,t])}}if(this.#s.clear(),this.#t.fill(void 0),this.#i.fill(void 0),this.#d&&this.#F){this.#d.fill(0),this.#F.fill(0);for(let e of this.#g??[])e!==void 0&&clearTimeout(e);this.#g?.fill(void 0)}if(this.#y&&this.#y.fill(0),this.#a=0,this.#h=0,this.#_.length=0,this.#b=0,this.#n=0,this.#f&&this.#r){let e=this.#r,i;for(;i=e?.shift();)this.#S?.(...i)}}};exports.LRUCache=L;
+"use strict";var j=(u,t)=>()=>(t||u((t={exports:{}}).exports,t),t.exports);var I=j(O=>{"use strict";Object.defineProperty(O,"__esModule",{value:!0});O.tracing=O.metrics=void 0;var U=require("node:diagnostics_channel");O.metrics=(0,U.channel)("lru-cache:metrics");O.tracing=(0,U.tracingChannel)("lru-cache")});var P=j(R=>{"use strict";Object.defineProperty(R,"__esModule",{value:!0});R.defaultPerf=void 0;R.defaultPerf=typeof performance=="object"&&performance&&typeof performance.now=="function"?performance:Date});Object.defineProperty(exports,"__esModule",{value:!0});exports.LRUCache=void 0;var g=I(),N=P(),C=()=>g.metrics.hasSubscribers||g.tracing.hasSubscribers,k=new Set,G=typeof process=="object"&&process?process:{},V=(u,t,e,i)=>{typeof G.emitWarning=="function"?G.emitWarning(u,t,e,i):console.error(`[${e}] ${t}: ${u}`)},q=u=>!k.has(u);var T=u=>!!u&&u===Math.floor(u)&&u>0&&isFinite(u),H=u=>T(u)?u<=Math.pow(2,8)?Uint8Array:u<=Math.pow(2,16)?Uint16Array:u<=Math.pow(2,32)?Uint32Array:u<=Number.MAX_SAFE_INTEGER?W:null:null,W=class extends Array{constructor(t){super(t),this.fill(0)}},L=class u{heap;length;static#o=!1;static create(t){let e=H(t);if(!e)return[];u.#o=!0;let i=new u(t,e);return u.#o=!1,i}constructor(t,e){if(!u.#o)throw new TypeError("instantiate Stack using Stack.create(n)");this.heap=new e(t),this.length=0}push(t){this.heap[this.length++]=t}pop(){return this.heap[--this.length]}},M=class u{#o;#c;#m;#W;#S;#x;#j;#w;get perf(){return this.#w}ttl;ttlResolution;ttlAutopurge;updateAgeOnGet;updateAgeOnHas;allowStale;noDisposeOnSet;noUpdateTTL;maxEntrySize;sizeCalculation;noDeleteOnFetchRejection;noDeleteOnStaleGet;allowStaleOnFetchAbort;allowStaleOnFetchRejection;ignoreFetchAbort;backgroundFetchSize;#n;#b;#s;#i;#t;#l;#u;#a;#h;#_;#r;#y;#F;#d;#g;#T;#U;#f;#R;static unsafeExposeInternals(t){return{starts:t.#F,ttls:t.#d,autopurgeTimers:t.#g,sizes:t.#y,keyMap:t.#s,keyList:t.#i,valList:t.#t,next:t.#l,prev:t.#u,get head(){return t.#a},get tail(){return t.#h},free:t.#_,isBackgroundFetch:e=>t.#e(e),backgroundFetch:(e,i,s,n)=>t.#G(e,i,s,n),moveToTail:e=>t.#M(e),indexes:e=>t.#A(e),rindexes:e=>t.#z(e),isStale:e=>t.#p(e)}}get max(){return this.#o}get maxSize(){return this.#c}get calculatedSize(){return this.#b}get size(){return this.#n}get fetchMethod(){return this.#x}get memoMethod(){return this.#j}get dispose(){return this.#m}get onInsert(){return this.#W}get disposeAfter(){return this.#S}constructor(t){let{max:e=0,ttl:i,ttlResolution:s=1,ttlAutopurge:n,updateAgeOnGet:o,updateAgeOnHas:l,allowStale:h,dispose:r,onInsert:c,disposeAfter:w,noDisposeOnSet:y,noUpdateTTL:d,maxSize:p=0,maxEntrySize:f=0,sizeCalculation:_,fetchMethod:a,memoMethod:S,noDeleteOnFetchRejection:F,noDeleteOnStaleGet:b,allowStaleOnFetchRejection:m,allowStaleOnFetchAbort:A,ignoreFetchAbort:z,backgroundFetchSize:x=1,perf:v}=t;if(this.backgroundFetchSize=x,v!==void 0&&typeof v?.now!="function")throw new TypeError("perf option must have a now() method if specified");if(this.#w=v??N.defaultPerf,e!==0&&!T(e))throw new TypeError("max option must be a nonnegative integer");let E=e?H(e):Array;if(!E)throw new Error("invalid max value: "+e);if(this.#o=e,this.#c=p,this.maxEntrySize=f||this.#c,this.sizeCalculation=_,this.sizeCalculation){if(!this.#c&&!this.maxEntrySize)throw new TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");if(typeof this.sizeCalculation!="function")throw new TypeError("sizeCalculation set to non-function")}if(S!==void 0&&typeof S!="function")throw new TypeError("memoMethod must be a function if defined");if(this.#j=S,a!==void 0&&typeof a!="function")throw new TypeError("fetchMethod must be a function if specified");if(this.#x=a,this.#U=!!a,this.#s=new Map,this.#i=Array.from({length:e}).fill(void 0),this.#t=Array.from({length:e}).fill(void 0),this.#l=new E(e),this.#u=new E(e),this.#a=0,this.#h=0,this.#_=L.create(e),this.#n=0,this.#b=0,typeof r=="function"&&(this.#m=r),typeof c=="function"&&(this.#W=c),typeof w=="function"?(this.#S=w,this.#r=[]):(this.#S=void 0,this.#r=void 0),this.#T=!!this.#m,this.#R=!!this.#W,this.#f=!!this.#S,this.noDisposeOnSet=!!y,this.noUpdateTTL=!!d,this.noDeleteOnFetchRejection=!!F,this.allowStaleOnFetchRejection=!!m,this.allowStaleOnFetchAbort=!!A,this.ignoreFetchAbort=!!z,this.maxEntrySize!==0){if(this.#c!==0&&!T(this.#c))throw new TypeError("maxSize must be a positive integer if specified");if(!T(this.maxEntrySize))throw new TypeError("maxEntrySize must be a positive integer if specified");this.#X()}if(this.allowStale=!!h,this.noDeleteOnStaleGet=!!b,this.updateAgeOnGet=!!o,this.updateAgeOnHas=!!l,this.ttlResolution=T(s)||s===0?s:1,this.ttlAutopurge=!!n,this.ttl=i||0,this.ttl){if(!T(this.ttl))throw new TypeError("ttl must be a positive integer if specified");this.#k()}if(this.#o===0&&this.ttl===0&&this.#c===0)throw new TypeError("At least one of max, maxSize, or ttl is required");if(!this.ttlAutopurge&&!this.#o&&!this.#c){let D="LRU_CACHE_UNBOUNDED";q(D)&&(k.add(D),V("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.","UnboundedCacheWarning",D,u))}}getRemainingTTL(t){return this.#s.has(t)?1/0:0}#k(){let t=new W(this.#o),e=new W(this.#o);this.#d=t,this.#F=e;let i=this.ttlAutopurge?Array.from({length:this.#o}):void 0;this.#g=i,this.#H=(h,r,c=this.#w.now())=>{e[h]=r!==0?c:0,t[h]=r,s(h,r)},this.#D=h=>{e[h]=t[h]!==0?this.#w.now():0,s(h,t[h])};let s=this.ttlAutopurge?(h,r)=>{if(i?.[h]&&(clearTimeout(i[h]),i[h]=void 0),r&&r!==0&&i){let c=setTimeout(()=>{this.#p(h)?(this.#v(this.#i[h],"expire"),i[h]=void 0):s(h,l(h))},r+1);c.unref&&c.unref(),i[h]=c}}:()=>{};this.#E=(h,r)=>{if(t[r]){let c=t[r],w=e[r];if(!c||!w)return;h.ttl=c,h.start=w,h.now=n||o();let y=h.now-w;h.remainingTTL=c-y}};let n=0,o=()=>{let h=this.#w.now();if(this.ttlResolution>0){n=h;let r=setTimeout(()=>n=0,this.ttlResolution);r.unref&&r.unref()}return h};this.getRemainingTTL=h=>{let r=this.#s.get(h);return r===void 0?0:l(r)};let l=h=>{let r=t[h],c=e[h];if(!r||!c)return 1/0;let w=(n||o())-c;return r-w};this.#p=h=>{let r=e[h],c=t[h];return!!c&&!!r&&(n||o())-r>c}}#D=()=>{};#E=()=>{};#H=()=>{};#p=()=>!1;#X(){let t=new W(this.#o);this.#b=0,this.#y=t,this.#C=e=>{this.#b-=t[e],t[e]=0},this.#N=(e,i,s,n)=>{if(!T(s)){if(this.#e(i))return this.backgroundFetchSize;if(n){if(typeof n!="function")throw new TypeError("sizeCalculation must be a function");if(s=n(i,e),!T(s))throw new TypeError("sizeCalculation return invalid (expect positive integer)")}else throw new TypeError("invalid size value (must be positive integer). When maxSize or maxEntrySize is used, sizeCalculation or size must be set.")}return s},this.#I=(e,i,s)=>{if(t[e]=i,this.#c){let n=this.#c-t[e];for(;this.#b>n;)this.#P(!0)}this.#b+=t[e],s&&(s.entrySize=i,s.totalCalculatedSize=this.#b)}}#C=t=>{};#I=(t,e,i)=>{};#N=(t,e,i,s)=>{if(i||s)throw new TypeError("cannot set size without setting maxSize or maxEntrySize on cache");return 0};*#A({allowStale:t=this.allowStale}={}){if(this.#n)for(let e=this.#h;this.#V(e)&&((t||!this.#p(e))&&(yield e),e!==this.#a);)e=this.#u[e]}*#z({allowStale:t=this.allowStale}={}){if(this.#n)for(let e=this.#a;this.#V(e)&&((t||!this.#p(e))&&(yield e),e!==this.#h);)e=this.#l[e]}#V(t){return t!==void 0&&this.#s.get(this.#i[t])===t}*entries(){for(let t of this.#A())this.#t[t]!==void 0&&this.#i[t]!==void 0&&!this.#e(this.#t[t])&&(yield[this.#i[t],this.#t[t]])}*rentries(){for(let t of this.#z())this.#t[t]!==void 0&&this.#i[t]!==void 0&&!this.#e(this.#t[t])&&(yield[this.#i[t],this.#t[t]])}*keys(){for(let t of this.#A()){let e=this.#i[t];e!==void 0&&!this.#e(this.#t[t])&&(yield e)}}*rkeys(){for(let t of this.#z()){let e=this.#i[t];e!==void 0&&!this.#e(this.#t[t])&&(yield e)}}*values(){for(let t of this.#A())this.#t[t]!==void 0&&!this.#e(this.#t[t])&&(yield this.#t[t])}*rvalues(){for(let t of this.#z())this.#t[t]!==void 0&&!this.#e(this.#t[t])&&(yield this.#t[t])}[Symbol.iterator](){return this.entries()}[Symbol.toStringTag]="LRUCache";find(t,e={}){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;if(n!==void 0&&t(n,this.#i[i],this))return this.#L(this.#i[i],e)}}forEach(t,e=this){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&t.call(e,n,this.#i[i],this)}}rforEach(t,e=this){for(let i of this.#z()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&t.call(e,n,this.#i[i],this)}}purgeStale(){let t=!1;for(let e of this.#z({allowStale:!0}))this.#p(e)&&(this.#v(this.#i[e],"expire"),t=!0);return t}info(t){let e=this.#s.get(t);if(e===void 0)return;let i=this.#t[e],s=this.#e(i)?i.__staleWhileFetching:i;if(s===void 0)return;let n={value:s};if(this.#d&&this.#F){let o=this.#d[e],l=this.#F[e];if(o&&l){let h=o-(this.#w.now()-l);n.ttl=h,n.start=Date.now()}}return this.#y&&(n.size=this.#y[e]),n}dump(){let t=[];for(let e of this.#A({allowStale:!0})){let i=this.#i[e],s=this.#t[e],n=this.#e(s)?s.__staleWhileFetching:s;if(n===void 0||i===void 0)continue;let o={value:n};if(this.#d&&this.#F){o.ttl=this.#d[e];let l=this.#w.now()-this.#F[e];o.start=Math.floor(Date.now()-l)}this.#y&&(o.size=this.#y[e]),t.unshift([i,o])}return t}load(t){this.clear();for(let[e,i]of t){if(i.start){let s=Date.now()-i.start;i.start=this.#w.now()-s}this.#O(e,i.value,i)}}set(t,e,i={}){let{status:s=g.metrics.hasSubscribers?{}:void 0}=i;i.status=s,s&&(s.op="set",s.key=t,e!==void 0&&(s.value=e),s.cache=this);let n=this.#O(t,e,i);return s&&g.metrics.hasSubscribers&&g.metrics.publish(s),n}#O(t,e,i,s){let{ttl:n=this.ttl,start:o,noDisposeOnSet:l=this.noDisposeOnSet,sizeCalculation:h=this.sizeCalculation,status:r}=i,c=this.#e(e);if(e===void 0)return r&&(r.set="deleted"),this.delete(t),this;let{noUpdateTTL:w=this.noUpdateTTL}=i;r&&!c&&(r.value=e);let y=this.#N(t,e,i.size||0,h,r);if(this.maxEntrySize&&y>this.maxEntrySize)return this.#v(t,"set"),r&&(r.set="miss",r.maxEntrySizeExceeded=!0),this;let d=this.#n===0?void 0:this.#s.get(t);if(d===void 0)d=this.#n===0?this.#h:this.#_.length!==0?this.#_.pop():this.#n===this.#o?this.#P(!1):this.#n,this.#i[d]=t,this.#t[d]=e,this.#s.set(t,d),this.#l[this.#h]=d,this.#u[d]=this.#h,this.#h=d,this.#n++,this.#I(d,y,r),r&&(r.set="add"),w=!1,this.#R&&!c&&this.#W?.(e,t,"add");else{this.#M(d);let p=this.#t[d];if(e!==p){if(!l)if(this.#e(p)){p!==s&&p.__abortController.abort(new Error("replaced"));let{__staleWhileFetching:f}=p;f!==void 0&&f!==e&&(this.#T&&this.#m?.(f,t,"set"),this.#f&&this.#r?.push([f,t,"set"]))}else this.#T&&this.#m?.(p,t,"set"),this.#f&&this.#r?.push([p,t,"set"]);if(this.#C(d),this.#I(d,y,r),this.#t[d]=e,!c){let f=p&&this.#e(p)?p.__staleWhileFetching:p,_=f===void 0?"add":e!==f?"replace":"update";r&&(r.set=_,f!==void 0&&(r.oldValue=f)),this.#R&&this.onInsert?.(e,t,_)}}else c||(r&&(r.set="update"),this.#R&&this.onInsert?.(e,t,"update"))}if(n!==0&&!this.#d&&this.#k(),this.#d&&(w||this.#H(d,n,o),r&&this.#E(r,d)),!l&&this.#f&&this.#r){let p=this.#r,f;for(;f=p?.shift();)this.#S?.(...f)}return this}pop(){try{for(;this.#n;){let t=this.#t[this.#a];if(this.#P(!0),this.#e(t)){if(t.__staleWhileFetching)return t.__staleWhileFetching}else if(t!==void 0)return t}}finally{if(this.#f&&this.#r){let t=this.#r,e;for(;e=t?.shift();)this.#S?.(...e)}}}#P(t){let e=this.#a,i=this.#i[e],s=this.#t[e],n=this.#e(s);n&&s.__abortController.abort(new Error("evicted"));let o=n?s.__staleWhileFetching:s;return(this.#T||this.#f)&&o!==void 0&&(this.#T&&this.#m?.(o,i,"evict"),this.#f&&this.#r?.push([o,i,"evict"])),this.#C(e),this.#g?.[e]&&(clearTimeout(this.#g[e]),this.#g[e]=void 0),t&&(this.#i[e]=void 0,this.#t[e]=void 0,this.#_.push(e)),this.#n===1?(this.#a=this.#h=0,this.#_.length=0):this.#a=this.#l[e],this.#s.delete(i),this.#n--,e}has(t,e={}){let{status:i=g.metrics.hasSubscribers?{}:void 0}=e;e.status=i,i&&(i.op="has",i.key=t,i.cache=this);let s=this.#Y(t,e);return g.metrics.hasSubscribers&&g.metrics.publish(i),s}#Y(t,e={}){let{updateAgeOnHas:i=this.updateAgeOnHas,status:s}=e,n=this.#s.get(t);if(n!==void 0){let o=this.#t[n];if(this.#e(o)&&o.__staleWhileFetching===void 0)return!1;if(this.#p(n))s&&(s.has="stale",this.#E(s,n));else return i&&this.#D(n),s&&(s.has="hit",this.#E(s,n)),!0}else s&&(s.has="miss");return!1}peek(t,e={}){let{status:i=C()?{}:void 0}=e;i&&(i.op="peek",i.key=t,i.cache=this),e.status=i;let s=this.#J(t,e);return g.metrics.hasSubscribers&&g.metrics.publish(i),s}#J(t,e){let{status:i,allowStale:s=this.allowStale}=e,n=this.#s.get(t);if(n===void 0||!s&&this.#p(n)){i&&(i.peek=n===void 0?"miss":"stale");return}let o=this.#t[n],l=this.#e(o)?o.__staleWhileFetching:o;return i&&(l!==void 0?(i.peek="hit",i.value=l):i.peek="miss"),l}#G(t,e,i,s){let n=e===void 0?void 0:this.#t[e];if(this.#e(n))return n;let o=new AbortController,{signal:l}=i;l?.addEventListener("abort",()=>o.abort(l.reason),{signal:o.signal});let h={signal:o.signal,options:i,context:s},r=(f,_=!1)=>{let{aborted:a}=o.signal,S=i.ignoreFetchAbort&&f!==void 0,F=i.ignoreFetchAbort||!!(i.allowStaleOnFetchAbort&&f!==void 0);if(i.status&&(a&&!_?(i.status.fetchAborted=!0,i.status.fetchError=o.signal.reason,S&&(i.status.fetchAbortIgnored=!0)):i.status.fetchResolved=!0),a&&!S&&!_)return w(o.signal.reason,F);let b=d,m=this.#t[e];return(m===d||m===void 0&&S&&_)&&(f===void 0?b.__staleWhileFetching!==void 0?this.#t[e]=b.__staleWhileFetching:this.#v(t,"fetch"):(i.status&&(i.status.fetchUpdated=!0),this.#O(t,f,h.options,b))),f},c=f=>(i.status&&(i.status.fetchRejected=!0,i.status.fetchError=f),w(f,!1)),w=(f,_)=>{let{aborted:a}=o.signal,S=a&&i.allowStaleOnFetchAbort,F=S||i.allowStaleOnFetchRejection,b=F||i.noDeleteOnFetchRejection,m=d;if(this.#t[e]===d&&(!b||!_&&m.__staleWhileFetching===void 0?this.#v(t,"fetch"):S||(this.#t[e]=m.__staleWhileFetching)),F)return i.status&&m.__staleWhileFetching!==void 0&&(i.status.returnedStale=!0),m.__staleWhileFetching;if(m.__returned===m)throw f},y=(f,_)=>{let a=this.#x?.(t,n,h);o.signal.addEventListener("abort",()=>{(!i.ignoreFetchAbort||i.allowStaleOnFetchAbort)&&(f(void 0),i.allowStaleOnFetchAbort&&(f=S=>r(S,!0)))}),a&&a instanceof Promise?a.then(S=>f(S===void 0?void 0:S),_):a!==void 0&&f(a)};i.status&&(i.status.fetchDispatched=!0);let d=new Promise(y).then(r,c),p=Object.assign(d,{__abortController:o,__staleWhileFetching:n,__returned:void 0});return e===void 0?(this.#O(t,p,{...h.options,status:void 0}),e=this.#s.get(t)):this.#t[e]=p,p}#e(t){if(!this.#U)return!1;let e=t;return!!e&&e instanceof Promise&&e.hasOwnProperty("__staleWhileFetching")&&e.__abortController instanceof AbortController}fetch(t,e={}){let i=g.tracing.hasSubscribers,{status:s=C()?{}:void 0}=e;e.status=s,s&&e.context&&(s.context=e.context);let n=this.#q(t,e);return s&&i&&(s.trace=!0,g.tracing.tracePromise(()=>n,s).catch(()=>{})),n}async#q(t,e={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,ttl:o=this.ttl,noDisposeOnSet:l=this.noDisposeOnSet,size:h=0,sizeCalculation:r=this.sizeCalculation,noUpdateTTL:c=this.noUpdateTTL,noDeleteOnFetchRejection:w=this.noDeleteOnFetchRejection,allowStaleOnFetchRejection:y=this.allowStaleOnFetchRejection,ignoreFetchAbort:d=this.ignoreFetchAbort,allowStaleOnFetchAbort:p=this.allowStaleOnFetchAbort,context:f,forceRefresh:_=!1,status:a,signal:S}=e;if(a&&(a.op="fetch",a.key=t,_&&(a.forceRefresh=!0),a.cache=this),!this.#U)return a&&(a.fetch="get"),this.#L(t,{allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,status:a});let F={allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,ttl:o,noDisposeOnSet:l,size:h,sizeCalculation:r,noUpdateTTL:c,noDeleteOnFetchRejection:w,allowStaleOnFetchRejection:y,allowStaleOnFetchAbort:p,ignoreFetchAbort:d,status:a,signal:S},b=this.#s.get(t);if(b===void 0){a&&(a.fetch="miss");let m=this.#G(t,b,F,f);return m.__returned=m}else{let m=this.#t[b];if(this.#e(m)){let E=i&&m.__staleWhileFetching!==void 0;return a&&(a.fetch="inflight",E&&(a.returnedStale=!0)),E?m.__staleWhileFetching:m.__returned=m}let A=this.#p(b);if(!_&&!A)return a&&(a.fetch="hit"),this.#M(b),s&&this.#D(b),a&&this.#E(a,b),m;let z=this.#G(t,b,F,f),v=z.__staleWhileFetching!==void 0&&i;return a&&(a.fetch=A?"stale":"refresh",v&&A&&(a.returnedStale=!0)),v?z.__staleWhileFetching:z.__returned=z}}forceFetch(t,e={}){let i=g.tracing.hasSubscribers,{status:s=C()?{}:void 0}=e;e.status=s,s&&e.context&&(s.context=e.context);let n=this.#K(t,e);return s&&i&&(s.trace=!0,g.tracing.tracePromise(()=>n,s).catch(()=>{})),n}async#K(t,e={}){let i=await this.#q(t,e);if(i===void 0)throw new Error("fetch() returned undefined");return i}memo(t,e={}){let{status:i=g.metrics.hasSubscribers?{}:void 0}=e;e.status=i,i&&(i.op="memo",i.key=t,e.context&&(i.context=e.context),i.cache=this);let s=this.#Q(t,e);return i&&(i.value=s),g.metrics.hasSubscribers&&g.metrics.publish(i),s}#Q(t,e={}){let i=this.#j;if(!i)throw new Error("no memoMethod provided to constructor");let{context:s,status:n,forceRefresh:o,...l}=e;n&&o&&(n.forceRefresh=!0);let h=this.#L(t,l),r=o||h===void 0;if(n&&(n.memo=r?"miss":"hit",r||(n.value=h)),!r)return h;let c=i(t,h,{options:l,context:s});return n&&(n.value=c),this.#O(t,c,l),c}get(t,e={}){let{status:i=g.metrics.hasSubscribers?{}:void 0}=e;e.status=i,i&&(i.op="get",i.key=t,i.cache=this);let s=this.#L(t,e);return i&&(s!==void 0&&(i.value=s),g.metrics.hasSubscribers&&g.metrics.publish(i)),s}#L(t,e={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,status:o}=e,l=this.#s.get(t);if(l===void 0){o&&(o.get="miss");return}let h=this.#t[l],r=this.#e(h);return o&&this.#E(o,l),this.#p(l)?r?(o&&(o.get="stale-fetching"),i&&h.__staleWhileFetching!==void 0?(o&&(o.returnedStale=!0),h.__staleWhileFetching):void 0):(n||this.#v(t,"expire"),o&&(o.get="stale"),i?(o&&(o.returnedStale=!0),h):void 0):(o&&(o.get=r?"fetching":"hit"),this.#M(l),s&&this.#D(l),r?h.__staleWhileFetching:h)}#B(t,e){this.#u[e]=t,this.#l[t]=e}#M(t){t!==this.#h&&(t===this.#a?this.#a=this.#l[t]:this.#B(this.#u[t],this.#l[t]),this.#B(this.#h,t),this.#h=t)}delete(t){return this.#v(t,"delete")}#v(t,e){g.metrics.hasSubscribers&&g.metrics.publish({op:"delete",delete:e,key:t,cache:this});let i=!1;if(this.#n!==0){let s=this.#s.get(t);if(s!==void 0)if(this.#g?.[s]&&(clearTimeout(this.#g[s]),this.#g[s]=void 0),i=!0,this.#n===1)this.#$(e);else{this.#C(s);let n=this.#t[s];if(this.#e(n)?n.__abortController.abort(new Error("deleted")):(this.#T||this.#f)&&(this.#T&&this.#m?.(n,t,e),this.#f&&this.#r?.push([n,t,e])),this.#s.delete(t),this.#i[s]=void 0,this.#t[s]=void 0,s===this.#h)this.#h=this.#u[s];else if(s===this.#a)this.#a=this.#l[s];else{let o=this.#u[s];this.#l[o]=this.#l[s];let l=this.#l[s];this.#u[l]=this.#u[s]}this.#n--,this.#_.push(s)}}if(this.#f&&this.#r?.length){let s=this.#r,n;for(;n=s?.shift();)this.#S?.(...n)}return i}clear(){return this.#$("delete")}#$(t){for(let e of this.#z({allowStale:!0})){let i=this.#t[e];if(this.#e(i))i.__abortController.abort(new Error("deleted"));else{let s=this.#i[e];this.#T&&this.#m?.(i,s,t),this.#f&&this.#r?.push([i,s,t])}}if(this.#s.clear(),this.#t.fill(void 0),this.#i.fill(void 0),this.#d&&this.#F){this.#d.fill(0),this.#F.fill(0);for(let e of this.#g??[])e!==void 0&&clearTimeout(e);this.#g?.fill(void 0)}if(this.#y&&this.#y.fill(0),this.#a=0,this.#h=0,this.#_.length=0,this.#b=0,this.#n=0,this.#f&&this.#r){let e=this.#r,i;for(;i=e?.shift();)this.#S?.(...i)}}};exports.LRUCache=M;
//# sourceMappingURL=index.min.js.map
diff --git a/deps/npm/node_modules/lru-cache/dist/esm/browser/index.js b/deps/npm/node_modules/lru-cache/dist/esm/browser/index.js
index 114a4e99083..c0fbe78aa7b 100644
--- a/deps/npm/node_modules/lru-cache/dist/esm/browser/index.js
+++ b/deps/npm/node_modules/lru-cache/dist/esm/browser/index.js
@@ -409,17 +409,17 @@ export class LRUCache {
this.#setItemTTL = (index, ttl, start = this.#perf.now()) => {
starts[index] = ttl !== 0 ? start : 0;
ttls[index] = ttl;
- setPurgetTimer(index, ttl);
+ setPurgeTimer(index, ttl);
};
this.#updateItemAge = index => {
starts[index] = ttls[index] !== 0 ? this.#perf.now() : 0;
- setPurgetTimer(index, ttls[index]);
+ setPurgeTimer(index, ttls[index]);
};
// clear out the purge timer if we're setting TTL to 0, and
// previously had a ttl purge timer running, so it doesn't
// fire unnecessarily. Don't need to do this if we're not doing
// autopurge.
- const setPurgetTimer = !this.ttlAutopurge ?
+ const setPurgeTimer = !this.ttlAutopurge ?
() => { }
: (index, ttl) => {
if (purgeTimers?.[index]) {
@@ -430,6 +430,10 @@ export class LRUCache {
const t = setTimeout(() => {
if (this.#isStale(index)) {
this.#delete(this.#keyList[index], 'expire');
+ purgeTimers[index] = undefined;
+ }
+ else {
+ setPurgeTimer(index, getRemainingTTL(index));
}
}, ttl + 1);
// unref() not supported on all platforms
@@ -479,6 +483,9 @@ export class LRUCache {
if (index === undefined) {
return 0;
}
+ return getRemainingTTL(index);
+ };
+ const getRemainingTTL = (index) => {
const ttl = ttls[index];
const start = starts[index];
if (!ttl || !start) {
@@ -1618,7 +1625,7 @@ export class LRUCache {
const index = this.#keyMap.get(k);
if (index !== undefined) {
if (this.#autopurgeTimers?.[index]) {
- clearTimeout(this.#autopurgeTimers?.[index]);
+ clearTimeout(this.#autopurgeTimers[index]);
this.#autopurgeTimers[index] = undefined;
}
deleted = true;
diff --git a/deps/npm/node_modules/lru-cache/dist/esm/browser/index.min.js b/deps/npm/node_modules/lru-cache/dist/esm/browser/index.min.js
index 86618ad212c..f5898157bc4 100644
--- a/deps/npm/node_modules/lru-cache/dist/esm/browser/index.min.js
+++ b/deps/npm/node_modules/lru-cache/dist/esm/browser/index.min.js
@@ -1,2 +1,2 @@
-var L={hasSubscribers:!1},S=L,W=L;var M=typeof performance=="object"&&performance&&typeof performance.now=="function"?performance:Date;var D=()=>S.hasSubscribers||W.hasSubscribers,j=new Set,I=typeof process=="object"&&process?process:{},P=(u,e,t,i)=>{typeof I.emitWarning=="function"?I.emitWarning(u,e,t,i):console.error(`[${t}] ${e}: ${u}`)},k=u=>!j.has(u);var T=u=>!!u&&u===Math.floor(u)&&u>0&&isFinite(u),G=u=>T(u)?u<=Math.pow(2,8)?Uint8Array:u<=Math.pow(2,16)?Uint16Array:u<=Math.pow(2,32)?Uint32Array:u<=Number.MAX_SAFE_INTEGER?O:null:null,O=class extends Array{constructor(e){super(e),this.fill(0)}},R=class u{heap;length;static#o=!1;static create(e){let t=G(e);if(!t)return[];u.#o=!0;let i=new u(e,t);return u.#o=!1,i}constructor(e,t){if(!u.#o)throw new TypeError("instantiate Stack using Stack.create(n)");this.heap=new t(e),this.length=0}push(e){this.heap[this.length++]=e}pop(){return this.heap[--this.length]}},U=class u{#o;#c;#S;#O;#w;#M;#I;#m;get perf(){return this.#m}ttl;ttlResolution;ttlAutopurge;updateAgeOnGet;updateAgeOnHas;allowStale;noDisposeOnSet;noUpdateTTL;maxEntrySize;sizeCalculation;noDeleteOnFetchRejection;noDeleteOnStaleGet;allowStaleOnFetchAbort;allowStaleOnFetchRejection;ignoreFetchAbort;backgroundFetchSize;#n;#b;#s;#i;#t;#l;#u;#a;#h;#y;#r;#_;#F;#d;#g;#T;#U;#f;#x;static unsafeExposeInternals(e){return{starts:e.#F,ttls:e.#d,autopurgeTimers:e.#g,sizes:e.#_,keyMap:e.#s,keyList:e.#i,valList:e.#t,next:e.#l,prev:e.#u,get head(){return e.#a},get tail(){return e.#h},free:e.#y,isBackgroundFetch:t=>e.#e(t),backgroundFetch:(t,i,s,n)=>e.#P(t,i,s,n),moveToTail:t=>e.#L(t),indexes:t=>e.#A(t),rindexes:t=>e.#z(t),isStale:t=>e.#p(t)}}get max(){return this.#o}get maxSize(){return this.#c}get calculatedSize(){return this.#b}get size(){return this.#n}get fetchMethod(){return this.#M}get memoMethod(){return this.#I}get dispose(){return this.#S}get onInsert(){return this.#O}get disposeAfter(){return this.#w}constructor(e){let{max:t=0,ttl:i,ttlResolution:s=1,ttlAutopurge:n,updateAgeOnGet:r,updateAgeOnHas:h,allowStale:a,dispose:o,onInsert:d,disposeAfter:y,noDisposeOnSet:_,noUpdateTTL:c,maxSize:g=0,maxEntrySize:f=0,sizeCalculation:b,fetchMethod:l,memoMethod:w,noDeleteOnFetchRejection:F,noDeleteOnStaleGet:m,allowStaleOnFetchRejection:p,allowStaleOnFetchAbort:A,ignoreFetchAbort:z,backgroundFetchSize:C=1,perf:E}=e;if(this.backgroundFetchSize=C,E!==void 0&&typeof E?.now!="function")throw new TypeError("perf option must have a now() method if specified");if(this.#m=E??M,t!==0&&!T(t))throw new TypeError("max option must be a nonnegative integer");let v=t?G(t):Array;if(!v)throw new Error("invalid max value: "+t);if(this.#o=t,this.#c=g,this.maxEntrySize=f||this.#c,this.sizeCalculation=b,this.sizeCalculation){if(!this.#c&&!this.maxEntrySize)throw new TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");if(typeof this.sizeCalculation!="function")throw new TypeError("sizeCalculation set to non-function")}if(w!==void 0&&typeof w!="function")throw new TypeError("memoMethod must be a function if defined");if(this.#I=w,l!==void 0&&typeof l!="function")throw new TypeError("fetchMethod must be a function if specified");if(this.#M=l,this.#U=!!l,this.#s=new Map,this.#i=Array.from({length:t}).fill(void 0),this.#t=Array.from({length:t}).fill(void 0),this.#l=new v(t),this.#u=new v(t),this.#a=0,this.#h=0,this.#y=R.create(t),this.#n=0,this.#b=0,typeof o=="function"&&(this.#S=o),typeof d=="function"&&(this.#O=d),typeof y=="function"?(this.#w=y,this.#r=[]):(this.#w=void 0,this.#r=void 0),this.#T=!!this.#S,this.#x=!!this.#O,this.#f=!!this.#w,this.noDisposeOnSet=!!_,this.noUpdateTTL=!!c,this.noDeleteOnFetchRejection=!!F,this.allowStaleOnFetchRejection=!!p,this.allowStaleOnFetchAbort=!!A,this.ignoreFetchAbort=!!z,this.maxEntrySize!==0){if(this.#c!==0&&!T(this.#c))throw new TypeError("maxSize must be a positive integer if specified");if(!T(this.maxEntrySize))throw new TypeError("maxEntrySize must be a positive integer if specified");this.#X()}if(this.allowStale=!!a,this.noDeleteOnStaleGet=!!m,this.updateAgeOnGet=!!r,this.updateAgeOnHas=!!h,this.ttlResolution=T(s)||s===0?s:1,this.ttlAutopurge=!!n,this.ttl=i||0,this.ttl){if(!T(this.ttl))throw new TypeError("ttl must be a positive integer if specified");this.#k()}if(this.#o===0&&this.ttl===0&&this.#c===0)throw new TypeError("At least one of max, maxSize, or ttl is required");if(!this.ttlAutopurge&&!this.#o&&!this.#c){let x="LRU_CACHE_UNBOUNDED";k(x)&&(j.add(x),P("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.","UnboundedCacheWarning",x,u))}}getRemainingTTL(e){return this.#s.has(e)?1/0:0}#k(){let e=new O(this.#o),t=new O(this.#o);this.#d=e,this.#F=t;let i=this.ttlAutopurge?Array.from({length:this.#o}):void 0;this.#g=i,this.#H=(h,a,o=this.#m.now())=>{t[h]=a!==0?o:0,e[h]=a,s(h,a)},this.#D=h=>{t[h]=e[h]!==0?this.#m.now():0,s(h,e[h])};let s=this.ttlAutopurge?(h,a)=>{if(i?.[h]&&(clearTimeout(i[h]),i[h]=void 0),a&&a!==0&&i){let o=setTimeout(()=>{this.#p(h)&&this.#E(this.#i[h],"expire")},a+1);o.unref&&o.unref(),i[h]=o}}:()=>{};this.#v=(h,a)=>{if(e[a]){let o=e[a],d=t[a];if(!o||!d)return;h.ttl=o,h.start=d,h.now=n||r();let y=h.now-d;h.remainingTTL=o-y}};let n=0,r=()=>{let h=this.#m.now();if(this.ttlResolution>0){n=h;let a=setTimeout(()=>n=0,this.ttlResolution);a.unref&&a.unref()}return h};this.getRemainingTTL=h=>{let a=this.#s.get(h);if(a===void 0)return 0;let o=e[a],d=t[a];if(!o||!d)return 1/0;let y=(n||r())-d;return o-y},this.#p=h=>{let a=t[h],o=e[h];return!!o&&!!a&&(n||r())-a>o}}#D=()=>{};#v=()=>{};#H=()=>{};#p=()=>!1;#X(){let e=new O(this.#o);this.#b=0,this.#_=e,this.#R=t=>{this.#b-=e[t],e[t]=0},this.#N=(t,i,s,n)=>{if(!T(s)){if(this.#e(i))return this.backgroundFetchSize;if(n){if(typeof n!="function")throw new TypeError("sizeCalculation must be a function");if(s=n(i,t),!T(s))throw new TypeError("sizeCalculation return invalid (expect positive integer)")}else throw new TypeError("invalid size value (must be positive integer). When maxSize or maxEntrySize is used, sizeCalculation or size must be set.")}return s},this.#j=(t,i,s)=>{if(e[t]=i,this.#c){let n=this.#c-e[t];for(;this.#b>n;)this.#G(!0)}this.#b+=e[t],s&&(s.entrySize=i,s.totalCalculatedSize=this.#b)}}#R=e=>{};#j=(e,t,i)=>{};#N=(e,t,i,s)=>{if(i||s)throw new TypeError("cannot set size without setting maxSize or maxEntrySize on cache");return 0};*#A({allowStale:e=this.allowStale}={}){if(this.#n)for(let t=this.#h;this.#V(t)&&((e||!this.#p(t))&&(yield t),t!==this.#a);)t=this.#u[t]}*#z({allowStale:e=this.allowStale}={}){if(this.#n)for(let t=this.#a;this.#V(t)&&((e||!this.#p(t))&&(yield t),t!==this.#h);)t=this.#l[t]}#V(e){return e!==void 0&&this.#s.get(this.#i[e])===e}*entries(){for(let e of this.#A())this.#t[e]!==void 0&&this.#i[e]!==void 0&&!this.#e(this.#t[e])&&(yield[this.#i[e],this.#t[e]])}*rentries(){for(let e of this.#z())this.#t[e]!==void 0&&this.#i[e]!==void 0&&!this.#e(this.#t[e])&&(yield[this.#i[e],this.#t[e]])}*keys(){for(let e of this.#A()){let t=this.#i[e];t!==void 0&&!this.#e(this.#t[e])&&(yield t)}}*rkeys(){for(let e of this.#z()){let t=this.#i[e];t!==void 0&&!this.#e(this.#t[e])&&(yield t)}}*values(){for(let e of this.#A())this.#t[e]!==void 0&&!this.#e(this.#t[e])&&(yield this.#t[e])}*rvalues(){for(let e of this.#z())this.#t[e]!==void 0&&!this.#e(this.#t[e])&&(yield this.#t[e])}[Symbol.iterator](){return this.entries()}[Symbol.toStringTag]="LRUCache";find(e,t={}){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;if(n!==void 0&&e(n,this.#i[i],this))return this.#C(this.#i[i],t)}}forEach(e,t=this){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&e.call(t,n,this.#i[i],this)}}rforEach(e,t=this){for(let i of this.#z()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&e.call(t,n,this.#i[i],this)}}purgeStale(){let e=!1;for(let t of this.#z({allowStale:!0}))this.#p(t)&&(this.#E(this.#i[t],"expire"),e=!0);return e}info(e){let t=this.#s.get(e);if(t===void 0)return;let i=this.#t[t],s=this.#e(i)?i.__staleWhileFetching:i;if(s===void 0)return;let n={value:s};if(this.#d&&this.#F){let r=this.#d[t],h=this.#F[t];if(r&&h){let a=r-(this.#m.now()-h);n.ttl=a,n.start=Date.now()}}return this.#_&&(n.size=this.#_[t]),n}dump(){let e=[];for(let t of this.#A({allowStale:!0})){let i=this.#i[t],s=this.#t[t],n=this.#e(s)?s.__staleWhileFetching:s;if(n===void 0||i===void 0)continue;let r={value:n};if(this.#d&&this.#F){r.ttl=this.#d[t];let h=this.#m.now()-this.#F[t];r.start=Math.floor(Date.now()-h)}this.#_&&(r.size=this.#_[t]),e.unshift([i,r])}return e}load(e){this.clear();for(let[t,i]of e){if(i.start){let s=Date.now()-i.start;i.start=this.#m.now()-s}this.#W(t,i.value,i)}}set(e,t,i={}){let{status:s=S.hasSubscribers?{}:void 0}=i;i.status=s,s&&(s.op="set",s.key=e,t!==void 0&&(s.value=t),s.cache=this);let n=this.#W(e,t,i);return s&&S.hasSubscribers&&S.publish(s),n}#W(e,t,i,s){let{ttl:n=this.ttl,start:r,noDisposeOnSet:h=this.noDisposeOnSet,sizeCalculation:a=this.sizeCalculation,status:o}=i,d=this.#e(t);if(t===void 0)return o&&(o.set="deleted"),this.delete(e),this;let{noUpdateTTL:y=this.noUpdateTTL}=i;o&&!d&&(o.value=t);let _=this.#N(e,t,i.size||0,a,o);if(this.maxEntrySize&&_>this.maxEntrySize)return this.#E(e,"set"),o&&(o.set="miss",o.maxEntrySizeExceeded=!0),this;let c=this.#n===0?void 0:this.#s.get(e);if(c===void 0)c=this.#n===0?this.#h:this.#y.length!==0?this.#y.pop():this.#n===this.#o?this.#G(!1):this.#n,this.#i[c]=e,this.#t[c]=t,this.#s.set(e,c),this.#l[this.#h]=c,this.#u[c]=this.#h,this.#h=c,this.#n++,this.#j(c,_,o),o&&(o.set="add"),y=!1,this.#x&&!d&&this.#O?.(t,e,"add");else{this.#L(c);let g=this.#t[c];if(t!==g){if(!h)if(this.#e(g)){g!==s&&g.__abortController.abort(new Error("replaced"));let{__staleWhileFetching:f}=g;f!==void 0&&f!==t&&(this.#T&&this.#S?.(f,e,"set"),this.#f&&this.#r?.push([f,e,"set"]))}else this.#T&&this.#S?.(g,e,"set"),this.#f&&this.#r?.push([g,e,"set"]);if(this.#R(c),this.#j(c,_,o),this.#t[c]=t,!d){let f=g&&this.#e(g)?g.__staleWhileFetching:g,b=f===void 0?"add":t!==f?"replace":"update";o&&(o.set=b,f!==void 0&&(o.oldValue=f)),this.#x&&this.onInsert?.(t,e,b)}}else d||(o&&(o.set="update"),this.#x&&this.onInsert?.(t,e,"update"))}if(n!==0&&!this.#d&&this.#k(),this.#d&&(y||this.#H(c,n,r),o&&this.#v(o,c)),!h&&this.#f&&this.#r){let g=this.#r,f;for(;f=g?.shift();)this.#w?.(...f)}return this}pop(){try{for(;this.#n;){let e=this.#t[this.#a];if(this.#G(!0),this.#e(e)){if(e.__staleWhileFetching)return e.__staleWhileFetching}else if(e!==void 0)return e}}finally{if(this.#f&&this.#r){let e=this.#r,t;for(;t=e?.shift();)this.#w?.(...t)}}}#G(e){let t=this.#a,i=this.#i[t],s=this.#t[t],n=this.#e(s);n&&s.__abortController.abort(new Error("evicted"));let r=n?s.__staleWhileFetching:s;return(this.#T||this.#f)&&r!==void 0&&(this.#T&&this.#S?.(r,i,"evict"),this.#f&&this.#r?.push([r,i,"evict"])),this.#R(t),this.#g?.[t]&&(clearTimeout(this.#g[t]),this.#g[t]=void 0),e&&(this.#i[t]=void 0,this.#t[t]=void 0,this.#y.push(t)),this.#n===1?(this.#a=this.#h=0,this.#y.length=0):this.#a=this.#l[t],this.#s.delete(i),this.#n--,t}has(e,t={}){let{status:i=S.hasSubscribers?{}:void 0}=t;t.status=i,i&&(i.op="has",i.key=e,i.cache=this);let s=this.#Y(e,t);return S.hasSubscribers&&S.publish(i),s}#Y(e,t={}){let{updateAgeOnHas:i=this.updateAgeOnHas,status:s}=t,n=this.#s.get(e);if(n!==void 0){let r=this.#t[n];if(this.#e(r)&&r.__staleWhileFetching===void 0)return!1;if(this.#p(n))s&&(s.has="stale",this.#v(s,n));else return i&&this.#D(n),s&&(s.has="hit",this.#v(s,n)),!0}else s&&(s.has="miss");return!1}peek(e,t={}){let{status:i=D()?{}:void 0}=t;i&&(i.op="peek",i.key=e,i.cache=this),t.status=i;let s=this.#J(e,t);return S.hasSubscribers&&S.publish(i),s}#J(e,t){let{status:i,allowStale:s=this.allowStale}=t,n=this.#s.get(e);if(n===void 0||!s&&this.#p(n)){i&&(i.peek=n===void 0?"miss":"stale");return}let r=this.#t[n],h=this.#e(r)?r.__staleWhileFetching:r;return i&&(h!==void 0?(i.peek="hit",i.value=h):i.peek="miss"),h}#P(e,t,i,s){let n=t===void 0?void 0:this.#t[t];if(this.#e(n))return n;let r=new AbortController,{signal:h}=i;h?.addEventListener("abort",()=>r.abort(h.reason),{signal:r.signal});let a={signal:r.signal,options:i,context:s},o=(f,b=!1)=>{let{aborted:l}=r.signal,w=i.ignoreFetchAbort&&f!==void 0,F=i.ignoreFetchAbort||!!(i.allowStaleOnFetchAbort&&f!==void 0);if(i.status&&(l&&!b?(i.status.fetchAborted=!0,i.status.fetchError=r.signal.reason,w&&(i.status.fetchAbortIgnored=!0)):i.status.fetchResolved=!0),l&&!w&&!b)return y(r.signal.reason,F);let m=c,p=this.#t[t];return(p===c||p===void 0&&w&&b)&&(f===void 0?m.__staleWhileFetching!==void 0?this.#t[t]=m.__staleWhileFetching:this.#E(e,"fetch"):(i.status&&(i.status.fetchUpdated=!0),this.#W(e,f,a.options,m))),f},d=f=>(i.status&&(i.status.fetchRejected=!0,i.status.fetchError=f),y(f,!1)),y=(f,b)=>{let{aborted:l}=r.signal,w=l&&i.allowStaleOnFetchAbort,F=w||i.allowStaleOnFetchRejection,m=F||i.noDeleteOnFetchRejection,p=c;if(this.#t[t]===c&&(!m||!b&&p.__staleWhileFetching===void 0?this.#E(e,"fetch"):w||(this.#t[t]=p.__staleWhileFetching)),F)return i.status&&p.__staleWhileFetching!==void 0&&(i.status.returnedStale=!0),p.__staleWhileFetching;if(p.__returned===p)throw f},_=(f,b)=>{let l=this.#M?.(e,n,a);r.signal.addEventListener("abort",()=>{(!i.ignoreFetchAbort||i.allowStaleOnFetchAbort)&&(f(void 0),i.allowStaleOnFetchAbort&&(f=w=>o(w,!0)))}),l&&l instanceof Promise?l.then(w=>f(w===void 0?void 0:w),b):l!==void 0&&f(l)};i.status&&(i.status.fetchDispatched=!0);let c=new Promise(_).then(o,d),g=Object.assign(c,{__abortController:r,__staleWhileFetching:n,__returned:void 0});return t===void 0?(this.#W(e,g,{...a.options,status:void 0}),t=this.#s.get(e)):this.#t[t]=g,g}#e(e){if(!this.#U)return!1;let t=e;return!!t&&t instanceof Promise&&t.hasOwnProperty("__staleWhileFetching")&&t.__abortController instanceof AbortController}fetch(e,t={}){let i=W.hasSubscribers,{status:s=D()?{}:void 0}=t;t.status=s,s&&t.context&&(s.context=t.context);let n=this.#B(e,t);return s&&i&&(s.trace=!0,W.tracePromise(()=>n,s).catch(()=>{})),n}async#B(e,t={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,ttl:r=this.ttl,noDisposeOnSet:h=this.noDisposeOnSet,size:a=0,sizeCalculation:o=this.sizeCalculation,noUpdateTTL:d=this.noUpdateTTL,noDeleteOnFetchRejection:y=this.noDeleteOnFetchRejection,allowStaleOnFetchRejection:_=this.allowStaleOnFetchRejection,ignoreFetchAbort:c=this.ignoreFetchAbort,allowStaleOnFetchAbort:g=this.allowStaleOnFetchAbort,context:f,forceRefresh:b=!1,status:l,signal:w}=t;if(l&&(l.op="fetch",l.key=e,b&&(l.forceRefresh=!0),l.cache=this),!this.#U)return l&&(l.fetch="get"),this.#C(e,{allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,status:l});let F={allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,ttl:r,noDisposeOnSet:h,size:a,sizeCalculation:o,noUpdateTTL:d,noDeleteOnFetchRejection:y,allowStaleOnFetchRejection:_,allowStaleOnFetchAbort:g,ignoreFetchAbort:c,status:l,signal:w},m=this.#s.get(e);if(m===void 0){l&&(l.fetch="miss");let p=this.#P(e,m,F,f);return p.__returned=p}else{let p=this.#t[m];if(this.#e(p)){let v=i&&p.__staleWhileFetching!==void 0;return l&&(l.fetch="inflight",v&&(l.returnedStale=!0)),v?p.__staleWhileFetching:p.__returned=p}let A=this.#p(m);if(!b&&!A)return l&&(l.fetch="hit"),this.#L(m),s&&this.#D(m),l&&this.#v(l,m),p;let z=this.#P(e,m,F,f),E=z.__staleWhileFetching!==void 0&&i;return l&&(l.fetch=A?"stale":"refresh",E&&A&&(l.returnedStale=!0)),E?z.__staleWhileFetching:z.__returned=z}}forceFetch(e,t={}){let i=W.hasSubscribers,{status:s=D()?{}:void 0}=t;t.status=s,s&&t.context&&(s.context=t.context);let n=this.#K(e,t);return s&&i&&(s.trace=!0,W.tracePromise(()=>n,s).catch(()=>{})),n}async#K(e,t={}){let i=await this.#B(e,t);if(i===void 0)throw new Error("fetch() returned undefined");return i}memo(e,t={}){let{status:i=S.hasSubscribers?{}:void 0}=t;t.status=i,i&&(i.op="memo",i.key=e,t.context&&(i.context=t.context),i.cache=this);let s=this.#Q(e,t);return i&&(i.value=s),S.hasSubscribers&&S.publish(i),s}#Q(e,t={}){let i=this.#I;if(!i)throw new Error("no memoMethod provided to constructor");let{context:s,status:n,forceRefresh:r,...h}=t;n&&r&&(n.forceRefresh=!0);let a=this.#C(e,h),o=r||a===void 0;if(n&&(n.memo=o?"miss":"hit",o||(n.value=a)),!o)return a;let d=i(e,a,{options:h,context:s});return n&&(n.value=d),this.#W(e,d,h),d}get(e,t={}){let{status:i=S.hasSubscribers?{}:void 0}=t;t.status=i,i&&(i.op="get",i.key=e,i.cache=this);let s=this.#C(e,t);return i&&(s!==void 0&&(i.value=s),S.hasSubscribers&&S.publish(i)),s}#C(e,t={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,status:r}=t,h=this.#s.get(e);if(h===void 0){r&&(r.get="miss");return}let a=this.#t[h],o=this.#e(a);return r&&this.#v(r,h),this.#p(h)?o?(r&&(r.get="stale-fetching"),i&&a.__staleWhileFetching!==void 0?(r&&(r.returnedStale=!0),a.__staleWhileFetching):void 0):(n||this.#E(e,"expire"),r&&(r.get="stale"),i?(r&&(r.returnedStale=!0),a):void 0):(r&&(r.get=o?"fetching":"hit"),this.#L(h),s&&this.#D(h),o?a.__staleWhileFetching:a)}#$(e,t){this.#u[t]=e,this.#l[e]=t}#L(e){e!==this.#h&&(e===this.#a?this.#a=this.#l[e]:this.#$(this.#u[e],this.#l[e]),this.#$(this.#h,e),this.#h=e)}delete(e){return this.#E(e,"delete")}#E(e,t){S.hasSubscribers&&S.publish({op:"delete",delete:t,key:e,cache:this});let i=!1;if(this.#n!==0){let s=this.#s.get(e);if(s!==void 0)if(this.#g?.[s]&&(clearTimeout(this.#g?.[s]),this.#g[s]=void 0),i=!0,this.#n===1)this.#q(t);else{this.#R(s);let n=this.#t[s];if(this.#e(n)?n.__abortController.abort(new Error("deleted")):(this.#T||this.#f)&&(this.#T&&this.#S?.(n,e,t),this.#f&&this.#r?.push([n,e,t])),this.#s.delete(e),this.#i[s]=void 0,this.#t[s]=void 0,s===this.#h)this.#h=this.#u[s];else if(s===this.#a)this.#a=this.#l[s];else{let r=this.#u[s];this.#l[r]=this.#l[s];let h=this.#l[s];this.#u[h]=this.#u[s]}this.#n--,this.#y.push(s)}}if(this.#f&&this.#r?.length){let s=this.#r,n;for(;n=s?.shift();)this.#w?.(...n)}return i}clear(){return this.#q("delete")}#q(e){for(let t of this.#z({allowStale:!0})){let i=this.#t[t];if(this.#e(i))i.__abortController.abort(new Error("deleted"));else{let s=this.#i[t];this.#T&&this.#S?.(i,s,e),this.#f&&this.#r?.push([i,s,e])}}if(this.#s.clear(),this.#t.fill(void 0),this.#i.fill(void 0),this.#d&&this.#F){this.#d.fill(0),this.#F.fill(0);for(let t of this.#g??[])t!==void 0&&clearTimeout(t);this.#g?.fill(void 0)}if(this.#_&&this.#_.fill(0),this.#a=0,this.#h=0,this.#y.length=0,this.#b=0,this.#n=0,this.#f&&this.#r){let t=this.#r,i;for(;i=t?.shift();)this.#w?.(...i)}}};export{U as LRUCache};
+var L={hasSubscribers:!1},S=L,W=L;var M=typeof performance=="object"&&performance&&typeof performance.now=="function"?performance:Date;var R=()=>S.hasSubscribers||W.hasSubscribers,j=new Set,I=typeof process=="object"&&process?process:{},P=(d,e,t,i)=>{typeof I.emitWarning=="function"?I.emitWarning(d,e,t,i):console.error(`[${t}] ${e}: ${d}`)},k=d=>!j.has(d);var T=d=>!!d&&d===Math.floor(d)&&d>0&&isFinite(d),G=d=>T(d)?d<=Math.pow(2,8)?Uint8Array:d<=Math.pow(2,16)?Uint16Array:d<=Math.pow(2,32)?Uint32Array:d<=Number.MAX_SAFE_INTEGER?O:null:null,O=class extends Array{constructor(e){super(e),this.fill(0)}},x=class d{heap;length;static#o=!1;static create(e){let t=G(e);if(!t)return[];d.#o=!0;let i=new d(e,t);return d.#o=!1,i}constructor(e,t){if(!d.#o)throw new TypeError("instantiate Stack using Stack.create(n)");this.heap=new t(e),this.length=0}push(e){this.heap[this.length++]=e}pop(){return this.heap[--this.length]}},U=class d{#o;#c;#S;#O;#w;#M;#I;#m;get perf(){return this.#m}ttl;ttlResolution;ttlAutopurge;updateAgeOnGet;updateAgeOnHas;allowStale;noDisposeOnSet;noUpdateTTL;maxEntrySize;sizeCalculation;noDeleteOnFetchRejection;noDeleteOnStaleGet;allowStaleOnFetchAbort;allowStaleOnFetchRejection;ignoreFetchAbort;backgroundFetchSize;#n;#b;#s;#i;#t;#l;#u;#a;#h;#y;#r;#_;#F;#d;#g;#T;#U;#f;#D;static unsafeExposeInternals(e){return{starts:e.#F,ttls:e.#d,autopurgeTimers:e.#g,sizes:e.#_,keyMap:e.#s,keyList:e.#i,valList:e.#t,next:e.#l,prev:e.#u,get head(){return e.#a},get tail(){return e.#h},free:e.#y,isBackgroundFetch:t=>e.#e(t),backgroundFetch:(t,i,s,n)=>e.#P(t,i,s,n),moveToTail:t=>e.#L(t),indexes:t=>e.#A(t),rindexes:t=>e.#z(t),isStale:t=>e.#p(t)}}get max(){return this.#o}get maxSize(){return this.#c}get calculatedSize(){return this.#b}get size(){return this.#n}get fetchMethod(){return this.#M}get memoMethod(){return this.#I}get dispose(){return this.#S}get onInsert(){return this.#O}get disposeAfter(){return this.#w}constructor(e){let{max:t=0,ttl:i,ttlResolution:s=1,ttlAutopurge:n,updateAgeOnGet:o,updateAgeOnHas:l,allowStale:h,dispose:r,onInsert:c,disposeAfter:m,noDisposeOnSet:_,noUpdateTTL:u,maxSize:g=0,maxEntrySize:f=0,sizeCalculation:y,fetchMethod:a,memoMethod:w,noDeleteOnFetchRejection:F,noDeleteOnStaleGet:b,allowStaleOnFetchRejection:p,allowStaleOnFetchAbort:A,ignoreFetchAbort:z,backgroundFetchSize:C=1,perf:E}=e;if(this.backgroundFetchSize=C,E!==void 0&&typeof E?.now!="function")throw new TypeError("perf option must have a now() method if specified");if(this.#m=E??M,t!==0&&!T(t))throw new TypeError("max option must be a nonnegative integer");let v=t?G(t):Array;if(!v)throw new Error("invalid max value: "+t);if(this.#o=t,this.#c=g,this.maxEntrySize=f||this.#c,this.sizeCalculation=y,this.sizeCalculation){if(!this.#c&&!this.maxEntrySize)throw new TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");if(typeof this.sizeCalculation!="function")throw new TypeError("sizeCalculation set to non-function")}if(w!==void 0&&typeof w!="function")throw new TypeError("memoMethod must be a function if defined");if(this.#I=w,a!==void 0&&typeof a!="function")throw new TypeError("fetchMethod must be a function if specified");if(this.#M=a,this.#U=!!a,this.#s=new Map,this.#i=Array.from({length:t}).fill(void 0),this.#t=Array.from({length:t}).fill(void 0),this.#l=new v(t),this.#u=new v(t),this.#a=0,this.#h=0,this.#y=x.create(t),this.#n=0,this.#b=0,typeof r=="function"&&(this.#S=r),typeof c=="function"&&(this.#O=c),typeof m=="function"?(this.#w=m,this.#r=[]):(this.#w=void 0,this.#r=void 0),this.#T=!!this.#S,this.#D=!!this.#O,this.#f=!!this.#w,this.noDisposeOnSet=!!_,this.noUpdateTTL=!!u,this.noDeleteOnFetchRejection=!!F,this.allowStaleOnFetchRejection=!!p,this.allowStaleOnFetchAbort=!!A,this.ignoreFetchAbort=!!z,this.maxEntrySize!==0){if(this.#c!==0&&!T(this.#c))throw new TypeError("maxSize must be a positive integer if specified");if(!T(this.maxEntrySize))throw new TypeError("maxEntrySize must be a positive integer if specified");this.#X()}if(this.allowStale=!!h,this.noDeleteOnStaleGet=!!b,this.updateAgeOnGet=!!o,this.updateAgeOnHas=!!l,this.ttlResolution=T(s)||s===0?s:1,this.ttlAutopurge=!!n,this.ttl=i||0,this.ttl){if(!T(this.ttl))throw new TypeError("ttl must be a positive integer if specified");this.#k()}if(this.#o===0&&this.ttl===0&&this.#c===0)throw new TypeError("At least one of max, maxSize, or ttl is required");if(!this.ttlAutopurge&&!this.#o&&!this.#c){let D="LRU_CACHE_UNBOUNDED";k(D)&&(j.add(D),P("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.","UnboundedCacheWarning",D,d))}}getRemainingTTL(e){return this.#s.has(e)?1/0:0}#k(){let e=new O(this.#o),t=new O(this.#o);this.#d=e,this.#F=t;let i=this.ttlAutopurge?Array.from({length:this.#o}):void 0;this.#g=i,this.#H=(h,r,c=this.#m.now())=>{t[h]=r!==0?c:0,e[h]=r,s(h,r)},this.#R=h=>{t[h]=e[h]!==0?this.#m.now():0,s(h,e[h])};let s=this.ttlAutopurge?(h,r)=>{if(i?.[h]&&(clearTimeout(i[h]),i[h]=void 0),r&&r!==0&&i){let c=setTimeout(()=>{this.#p(h)?(this.#E(this.#i[h],"expire"),i[h]=void 0):s(h,l(h))},r+1);c.unref&&c.unref(),i[h]=c}}:()=>{};this.#v=(h,r)=>{if(e[r]){let c=e[r],m=t[r];if(!c||!m)return;h.ttl=c,h.start=m,h.now=n||o();let _=h.now-m;h.remainingTTL=c-_}};let n=0,o=()=>{let h=this.#m.now();if(this.ttlResolution>0){n=h;let r=setTimeout(()=>n=0,this.ttlResolution);r.unref&&r.unref()}return h};this.getRemainingTTL=h=>{let r=this.#s.get(h);return r===void 0?0:l(r)};let l=h=>{let r=e[h],c=t[h];if(!r||!c)return 1/0;let m=(n||o())-c;return r-m};this.#p=h=>{let r=t[h],c=e[h];return!!c&&!!r&&(n||o())-r>c}}#R=()=>{};#v=()=>{};#H=()=>{};#p=()=>!1;#X(){let e=new O(this.#o);this.#b=0,this.#_=e,this.#x=t=>{this.#b-=e[t],e[t]=0},this.#N=(t,i,s,n)=>{if(!T(s)){if(this.#e(i))return this.backgroundFetchSize;if(n){if(typeof n!="function")throw new TypeError("sizeCalculation must be a function");if(s=n(i,t),!T(s))throw new TypeError("sizeCalculation return invalid (expect positive integer)")}else throw new TypeError("invalid size value (must be positive integer). When maxSize or maxEntrySize is used, sizeCalculation or size must be set.")}return s},this.#j=(t,i,s)=>{if(e[t]=i,this.#c){let n=this.#c-e[t];for(;this.#b>n;)this.#G(!0)}this.#b+=e[t],s&&(s.entrySize=i,s.totalCalculatedSize=this.#b)}}#x=e=>{};#j=(e,t,i)=>{};#N=(e,t,i,s)=>{if(i||s)throw new TypeError("cannot set size without setting maxSize or maxEntrySize on cache");return 0};*#A({allowStale:e=this.allowStale}={}){if(this.#n)for(let t=this.#h;this.#V(t)&&((e||!this.#p(t))&&(yield t),t!==this.#a);)t=this.#u[t]}*#z({allowStale:e=this.allowStale}={}){if(this.#n)for(let t=this.#a;this.#V(t)&&((e||!this.#p(t))&&(yield t),t!==this.#h);)t=this.#l[t]}#V(e){return e!==void 0&&this.#s.get(this.#i[e])===e}*entries(){for(let e of this.#A())this.#t[e]!==void 0&&this.#i[e]!==void 0&&!this.#e(this.#t[e])&&(yield[this.#i[e],this.#t[e]])}*rentries(){for(let e of this.#z())this.#t[e]!==void 0&&this.#i[e]!==void 0&&!this.#e(this.#t[e])&&(yield[this.#i[e],this.#t[e]])}*keys(){for(let e of this.#A()){let t=this.#i[e];t!==void 0&&!this.#e(this.#t[e])&&(yield t)}}*rkeys(){for(let e of this.#z()){let t=this.#i[e];t!==void 0&&!this.#e(this.#t[e])&&(yield t)}}*values(){for(let e of this.#A())this.#t[e]!==void 0&&!this.#e(this.#t[e])&&(yield this.#t[e])}*rvalues(){for(let e of this.#z())this.#t[e]!==void 0&&!this.#e(this.#t[e])&&(yield this.#t[e])}[Symbol.iterator](){return this.entries()}[Symbol.toStringTag]="LRUCache";find(e,t={}){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;if(n!==void 0&&e(n,this.#i[i],this))return this.#C(this.#i[i],t)}}forEach(e,t=this){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&e.call(t,n,this.#i[i],this)}}rforEach(e,t=this){for(let i of this.#z()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&e.call(t,n,this.#i[i],this)}}purgeStale(){let e=!1;for(let t of this.#z({allowStale:!0}))this.#p(t)&&(this.#E(this.#i[t],"expire"),e=!0);return e}info(e){let t=this.#s.get(e);if(t===void 0)return;let i=this.#t[t],s=this.#e(i)?i.__staleWhileFetching:i;if(s===void 0)return;let n={value:s};if(this.#d&&this.#F){let o=this.#d[t],l=this.#F[t];if(o&&l){let h=o-(this.#m.now()-l);n.ttl=h,n.start=Date.now()}}return this.#_&&(n.size=this.#_[t]),n}dump(){let e=[];for(let t of this.#A({allowStale:!0})){let i=this.#i[t],s=this.#t[t],n=this.#e(s)?s.__staleWhileFetching:s;if(n===void 0||i===void 0)continue;let o={value:n};if(this.#d&&this.#F){o.ttl=this.#d[t];let l=this.#m.now()-this.#F[t];o.start=Math.floor(Date.now()-l)}this.#_&&(o.size=this.#_[t]),e.unshift([i,o])}return e}load(e){this.clear();for(let[t,i]of e){if(i.start){let s=Date.now()-i.start;i.start=this.#m.now()-s}this.#W(t,i.value,i)}}set(e,t,i={}){let{status:s=S.hasSubscribers?{}:void 0}=i;i.status=s,s&&(s.op="set",s.key=e,t!==void 0&&(s.value=t),s.cache=this);let n=this.#W(e,t,i);return s&&S.hasSubscribers&&S.publish(s),n}#W(e,t,i,s){let{ttl:n=this.ttl,start:o,noDisposeOnSet:l=this.noDisposeOnSet,sizeCalculation:h=this.sizeCalculation,status:r}=i,c=this.#e(t);if(t===void 0)return r&&(r.set="deleted"),this.delete(e),this;let{noUpdateTTL:m=this.noUpdateTTL}=i;r&&!c&&(r.value=t);let _=this.#N(e,t,i.size||0,h,r);if(this.maxEntrySize&&_>this.maxEntrySize)return this.#E(e,"set"),r&&(r.set="miss",r.maxEntrySizeExceeded=!0),this;let u=this.#n===0?void 0:this.#s.get(e);if(u===void 0)u=this.#n===0?this.#h:this.#y.length!==0?this.#y.pop():this.#n===this.#o?this.#G(!1):this.#n,this.#i[u]=e,this.#t[u]=t,this.#s.set(e,u),this.#l[this.#h]=u,this.#u[u]=this.#h,this.#h=u,this.#n++,this.#j(u,_,r),r&&(r.set="add"),m=!1,this.#D&&!c&&this.#O?.(t,e,"add");else{this.#L(u);let g=this.#t[u];if(t!==g){if(!l)if(this.#e(g)){g!==s&&g.__abortController.abort(new Error("replaced"));let{__staleWhileFetching:f}=g;f!==void 0&&f!==t&&(this.#T&&this.#S?.(f,e,"set"),this.#f&&this.#r?.push([f,e,"set"]))}else this.#T&&this.#S?.(g,e,"set"),this.#f&&this.#r?.push([g,e,"set"]);if(this.#x(u),this.#j(u,_,r),this.#t[u]=t,!c){let f=g&&this.#e(g)?g.__staleWhileFetching:g,y=f===void 0?"add":t!==f?"replace":"update";r&&(r.set=y,f!==void 0&&(r.oldValue=f)),this.#D&&this.onInsert?.(t,e,y)}}else c||(r&&(r.set="update"),this.#D&&this.onInsert?.(t,e,"update"))}if(n!==0&&!this.#d&&this.#k(),this.#d&&(m||this.#H(u,n,o),r&&this.#v(r,u)),!l&&this.#f&&this.#r){let g=this.#r,f;for(;f=g?.shift();)this.#w?.(...f)}return this}pop(){try{for(;this.#n;){let e=this.#t[this.#a];if(this.#G(!0),this.#e(e)){if(e.__staleWhileFetching)return e.__staleWhileFetching}else if(e!==void 0)return e}}finally{if(this.#f&&this.#r){let e=this.#r,t;for(;t=e?.shift();)this.#w?.(...t)}}}#G(e){let t=this.#a,i=this.#i[t],s=this.#t[t],n=this.#e(s);n&&s.__abortController.abort(new Error("evicted"));let o=n?s.__staleWhileFetching:s;return(this.#T||this.#f)&&o!==void 0&&(this.#T&&this.#S?.(o,i,"evict"),this.#f&&this.#r?.push([o,i,"evict"])),this.#x(t),this.#g?.[t]&&(clearTimeout(this.#g[t]),this.#g[t]=void 0),e&&(this.#i[t]=void 0,this.#t[t]=void 0,this.#y.push(t)),this.#n===1?(this.#a=this.#h=0,this.#y.length=0):this.#a=this.#l[t],this.#s.delete(i),this.#n--,t}has(e,t={}){let{status:i=S.hasSubscribers?{}:void 0}=t;t.status=i,i&&(i.op="has",i.key=e,i.cache=this);let s=this.#Y(e,t);return S.hasSubscribers&&S.publish(i),s}#Y(e,t={}){let{updateAgeOnHas:i=this.updateAgeOnHas,status:s}=t,n=this.#s.get(e);if(n!==void 0){let o=this.#t[n];if(this.#e(o)&&o.__staleWhileFetching===void 0)return!1;if(this.#p(n))s&&(s.has="stale",this.#v(s,n));else return i&&this.#R(n),s&&(s.has="hit",this.#v(s,n)),!0}else s&&(s.has="miss");return!1}peek(e,t={}){let{status:i=R()?{}:void 0}=t;i&&(i.op="peek",i.key=e,i.cache=this),t.status=i;let s=this.#J(e,t);return S.hasSubscribers&&S.publish(i),s}#J(e,t){let{status:i,allowStale:s=this.allowStale}=t,n=this.#s.get(e);if(n===void 0||!s&&this.#p(n)){i&&(i.peek=n===void 0?"miss":"stale");return}let o=this.#t[n],l=this.#e(o)?o.__staleWhileFetching:o;return i&&(l!==void 0?(i.peek="hit",i.value=l):i.peek="miss"),l}#P(e,t,i,s){let n=t===void 0?void 0:this.#t[t];if(this.#e(n))return n;let o=new AbortController,{signal:l}=i;l?.addEventListener("abort",()=>o.abort(l.reason),{signal:o.signal});let h={signal:o.signal,options:i,context:s},r=(f,y=!1)=>{let{aborted:a}=o.signal,w=i.ignoreFetchAbort&&f!==void 0,F=i.ignoreFetchAbort||!!(i.allowStaleOnFetchAbort&&f!==void 0);if(i.status&&(a&&!y?(i.status.fetchAborted=!0,i.status.fetchError=o.signal.reason,w&&(i.status.fetchAbortIgnored=!0)):i.status.fetchResolved=!0),a&&!w&&!y)return m(o.signal.reason,F);let b=u,p=this.#t[t];return(p===u||p===void 0&&w&&y)&&(f===void 0?b.__staleWhileFetching!==void 0?this.#t[t]=b.__staleWhileFetching:this.#E(e,"fetch"):(i.status&&(i.status.fetchUpdated=!0),this.#W(e,f,h.options,b))),f},c=f=>(i.status&&(i.status.fetchRejected=!0,i.status.fetchError=f),m(f,!1)),m=(f,y)=>{let{aborted:a}=o.signal,w=a&&i.allowStaleOnFetchAbort,F=w||i.allowStaleOnFetchRejection,b=F||i.noDeleteOnFetchRejection,p=u;if(this.#t[t]===u&&(!b||!y&&p.__staleWhileFetching===void 0?this.#E(e,"fetch"):w||(this.#t[t]=p.__staleWhileFetching)),F)return i.status&&p.__staleWhileFetching!==void 0&&(i.status.returnedStale=!0),p.__staleWhileFetching;if(p.__returned===p)throw f},_=(f,y)=>{let a=this.#M?.(e,n,h);o.signal.addEventListener("abort",()=>{(!i.ignoreFetchAbort||i.allowStaleOnFetchAbort)&&(f(void 0),i.allowStaleOnFetchAbort&&(f=w=>r(w,!0)))}),a&&a instanceof Promise?a.then(w=>f(w===void 0?void 0:w),y):a!==void 0&&f(a)};i.status&&(i.status.fetchDispatched=!0);let u=new Promise(_).then(r,c),g=Object.assign(u,{__abortController:o,__staleWhileFetching:n,__returned:void 0});return t===void 0?(this.#W(e,g,{...h.options,status:void 0}),t=this.#s.get(e)):this.#t[t]=g,g}#e(e){if(!this.#U)return!1;let t=e;return!!t&&t instanceof Promise&&t.hasOwnProperty("__staleWhileFetching")&&t.__abortController instanceof AbortController}fetch(e,t={}){let i=W.hasSubscribers,{status:s=R()?{}:void 0}=t;t.status=s,s&&t.context&&(s.context=t.context);let n=this.#B(e,t);return s&&i&&(s.trace=!0,W.tracePromise(()=>n,s).catch(()=>{})),n}async#B(e,t={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,ttl:o=this.ttl,noDisposeOnSet:l=this.noDisposeOnSet,size:h=0,sizeCalculation:r=this.sizeCalculation,noUpdateTTL:c=this.noUpdateTTL,noDeleteOnFetchRejection:m=this.noDeleteOnFetchRejection,allowStaleOnFetchRejection:_=this.allowStaleOnFetchRejection,ignoreFetchAbort:u=this.ignoreFetchAbort,allowStaleOnFetchAbort:g=this.allowStaleOnFetchAbort,context:f,forceRefresh:y=!1,status:a,signal:w}=t;if(a&&(a.op="fetch",a.key=e,y&&(a.forceRefresh=!0),a.cache=this),!this.#U)return a&&(a.fetch="get"),this.#C(e,{allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,status:a});let F={allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,ttl:o,noDisposeOnSet:l,size:h,sizeCalculation:r,noUpdateTTL:c,noDeleteOnFetchRejection:m,allowStaleOnFetchRejection:_,allowStaleOnFetchAbort:g,ignoreFetchAbort:u,status:a,signal:w},b=this.#s.get(e);if(b===void 0){a&&(a.fetch="miss");let p=this.#P(e,b,F,f);return p.__returned=p}else{let p=this.#t[b];if(this.#e(p)){let v=i&&p.__staleWhileFetching!==void 0;return a&&(a.fetch="inflight",v&&(a.returnedStale=!0)),v?p.__staleWhileFetching:p.__returned=p}let A=this.#p(b);if(!y&&!A)return a&&(a.fetch="hit"),this.#L(b),s&&this.#R(b),a&&this.#v(a,b),p;let z=this.#P(e,b,F,f),E=z.__staleWhileFetching!==void 0&&i;return a&&(a.fetch=A?"stale":"refresh",E&&A&&(a.returnedStale=!0)),E?z.__staleWhileFetching:z.__returned=z}}forceFetch(e,t={}){let i=W.hasSubscribers,{status:s=R()?{}:void 0}=t;t.status=s,s&&t.context&&(s.context=t.context);let n=this.#K(e,t);return s&&i&&(s.trace=!0,W.tracePromise(()=>n,s).catch(()=>{})),n}async#K(e,t={}){let i=await this.#B(e,t);if(i===void 0)throw new Error("fetch() returned undefined");return i}memo(e,t={}){let{status:i=S.hasSubscribers?{}:void 0}=t;t.status=i,i&&(i.op="memo",i.key=e,t.context&&(i.context=t.context),i.cache=this);let s=this.#Q(e,t);return i&&(i.value=s),S.hasSubscribers&&S.publish(i),s}#Q(e,t={}){let i=this.#I;if(!i)throw new Error("no memoMethod provided to constructor");let{context:s,status:n,forceRefresh:o,...l}=t;n&&o&&(n.forceRefresh=!0);let h=this.#C(e,l),r=o||h===void 0;if(n&&(n.memo=r?"miss":"hit",r||(n.value=h)),!r)return h;let c=i(e,h,{options:l,context:s});return n&&(n.value=c),this.#W(e,c,l),c}get(e,t={}){let{status:i=S.hasSubscribers?{}:void 0}=t;t.status=i,i&&(i.op="get",i.key=e,i.cache=this);let s=this.#C(e,t);return i&&(s!==void 0&&(i.value=s),S.hasSubscribers&&S.publish(i)),s}#C(e,t={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,status:o}=t,l=this.#s.get(e);if(l===void 0){o&&(o.get="miss");return}let h=this.#t[l],r=this.#e(h);return o&&this.#v(o,l),this.#p(l)?r?(o&&(o.get="stale-fetching"),i&&h.__staleWhileFetching!==void 0?(o&&(o.returnedStale=!0),h.__staleWhileFetching):void 0):(n||this.#E(e,"expire"),o&&(o.get="stale"),i?(o&&(o.returnedStale=!0),h):void 0):(o&&(o.get=r?"fetching":"hit"),this.#L(l),s&&this.#R(l),r?h.__staleWhileFetching:h)}#$(e,t){this.#u[t]=e,this.#l[e]=t}#L(e){e!==this.#h&&(e===this.#a?this.#a=this.#l[e]:this.#$(this.#u[e],this.#l[e]),this.#$(this.#h,e),this.#h=e)}delete(e){return this.#E(e,"delete")}#E(e,t){S.hasSubscribers&&S.publish({op:"delete",delete:t,key:e,cache:this});let i=!1;if(this.#n!==0){let s=this.#s.get(e);if(s!==void 0)if(this.#g?.[s]&&(clearTimeout(this.#g[s]),this.#g[s]=void 0),i=!0,this.#n===1)this.#q(t);else{this.#x(s);let n=this.#t[s];if(this.#e(n)?n.__abortController.abort(new Error("deleted")):(this.#T||this.#f)&&(this.#T&&this.#S?.(n,e,t),this.#f&&this.#r?.push([n,e,t])),this.#s.delete(e),this.#i[s]=void 0,this.#t[s]=void 0,s===this.#h)this.#h=this.#u[s];else if(s===this.#a)this.#a=this.#l[s];else{let o=this.#u[s];this.#l[o]=this.#l[s];let l=this.#l[s];this.#u[l]=this.#u[s]}this.#n--,this.#y.push(s)}}if(this.#f&&this.#r?.length){let s=this.#r,n;for(;n=s?.shift();)this.#w?.(...n)}return i}clear(){return this.#q("delete")}#q(e){for(let t of this.#z({allowStale:!0})){let i=this.#t[t];if(this.#e(i))i.__abortController.abort(new Error("deleted"));else{let s=this.#i[t];this.#T&&this.#S?.(i,s,e),this.#f&&this.#r?.push([i,s,e])}}if(this.#s.clear(),this.#t.fill(void 0),this.#i.fill(void 0),this.#d&&this.#F){this.#d.fill(0),this.#F.fill(0);for(let t of this.#g??[])t!==void 0&&clearTimeout(t);this.#g?.fill(void 0)}if(this.#_&&this.#_.fill(0),this.#a=0,this.#h=0,this.#y.length=0,this.#b=0,this.#n=0,this.#f&&this.#r){let t=this.#r,i;for(;i=t?.shift();)this.#w?.(...i)}}};export{U as LRUCache};
//# sourceMappingURL=index.min.js.map
diff --git a/deps/npm/node_modules/lru-cache/dist/esm/index.js b/deps/npm/node_modules/lru-cache/dist/esm/index.js
index 114a4e99083..c0fbe78aa7b 100644
--- a/deps/npm/node_modules/lru-cache/dist/esm/index.js
+++ b/deps/npm/node_modules/lru-cache/dist/esm/index.js
@@ -409,17 +409,17 @@ export class LRUCache {
this.#setItemTTL = (index, ttl, start = this.#perf.now()) => {
starts[index] = ttl !== 0 ? start : 0;
ttls[index] = ttl;
- setPurgetTimer(index, ttl);
+ setPurgeTimer(index, ttl);
};
this.#updateItemAge = index => {
starts[index] = ttls[index] !== 0 ? this.#perf.now() : 0;
- setPurgetTimer(index, ttls[index]);
+ setPurgeTimer(index, ttls[index]);
};
// clear out the purge timer if we're setting TTL to 0, and
// previously had a ttl purge timer running, so it doesn't
// fire unnecessarily. Don't need to do this if we're not doing
// autopurge.
- const setPurgetTimer = !this.ttlAutopurge ?
+ const setPurgeTimer = !this.ttlAutopurge ?
() => { }
: (index, ttl) => {
if (purgeTimers?.[index]) {
@@ -430,6 +430,10 @@ export class LRUCache {
const t = setTimeout(() => {
if (this.#isStale(index)) {
this.#delete(this.#keyList[index], 'expire');
+ purgeTimers[index] = undefined;
+ }
+ else {
+ setPurgeTimer(index, getRemainingTTL(index));
}
}, ttl + 1);
// unref() not supported on all platforms
@@ -479,6 +483,9 @@ export class LRUCache {
if (index === undefined) {
return 0;
}
+ return getRemainingTTL(index);
+ };
+ const getRemainingTTL = (index) => {
const ttl = ttls[index];
const start = starts[index];
if (!ttl || !start) {
@@ -1618,7 +1625,7 @@ export class LRUCache {
const index = this.#keyMap.get(k);
if (index !== undefined) {
if (this.#autopurgeTimers?.[index]) {
- clearTimeout(this.#autopurgeTimers?.[index]);
+ clearTimeout(this.#autopurgeTimers[index]);
this.#autopurgeTimers[index] = undefined;
}
deleted = true;
diff --git a/deps/npm/node_modules/lru-cache/dist/esm/index.min.js b/deps/npm/node_modules/lru-cache/dist/esm/index.min.js
index 5715ef55079..8914cef567c 100644
--- a/deps/npm/node_modules/lru-cache/dist/esm/index.min.js
+++ b/deps/npm/node_modules/lru-cache/dist/esm/index.min.js
@@ -1,2 +1,2 @@
-var L={hasSubscribers:!1},S=L,A=L;import("node:diagnostics_channel").then(c=>{S=c.channel("lru-cache:metrics"),A=c.tracingChannel("lru-cache")}).catch(()=>{});var M=typeof performance=="object"&&performance&&typeof performance.now=="function"?performance:Date;var D=()=>S.hasSubscribers||A.hasSubscribers,j=new Set,I=typeof process=="object"&&process?process:{},P=(c,e,t,i)=>{typeof I.emitWarning=="function"?I.emitWarning(c,e,t,i):console.error(`[${t}] ${e}: ${c}`)},k=c=>!j.has(c);var T=c=>!!c&&c===Math.floor(c)&&c>0&&isFinite(c),G=c=>T(c)?c<=Math.pow(2,8)?Uint8Array:c<=Math.pow(2,16)?Uint16Array:c<=Math.pow(2,32)?Uint32Array:c<=Number.MAX_SAFE_INTEGER?O:null:null,O=class extends Array{constructor(e){super(e),this.fill(0)}},R=class c{heap;length;static#o=!1;static create(e){let t=G(e);if(!t)return[];c.#o=!0;let i=new c(e,t);return c.#o=!1,i}constructor(e,t){if(!c.#o)throw new TypeError("instantiate Stack using Stack.create(n)");this.heap=new t(e),this.length=0}push(e){this.heap[this.length++]=e}pop(){return this.heap[--this.length]}},U=class c{#o;#c;#S;#O;#w;#M;#I;#m;get perf(){return this.#m}ttl;ttlResolution;ttlAutopurge;updateAgeOnGet;updateAgeOnHas;allowStale;noDisposeOnSet;noUpdateTTL;maxEntrySize;sizeCalculation;noDeleteOnFetchRejection;noDeleteOnStaleGet;allowStaleOnFetchAbort;allowStaleOnFetchRejection;ignoreFetchAbort;backgroundFetchSize;#n;#b;#s;#i;#t;#l;#u;#a;#h;#y;#r;#_;#F;#d;#g;#T;#U;#f;#x;static unsafeExposeInternals(e){return{starts:e.#F,ttls:e.#d,autopurgeTimers:e.#g,sizes:e.#_,keyMap:e.#s,keyList:e.#i,valList:e.#t,next:e.#l,prev:e.#u,get head(){return e.#a},get tail(){return e.#h},free:e.#y,isBackgroundFetch:t=>e.#e(t),backgroundFetch:(t,i,s,n)=>e.#P(t,i,s,n),moveToTail:t=>e.#L(t),indexes:t=>e.#A(t),rindexes:t=>e.#z(t),isStale:t=>e.#p(t)}}get max(){return this.#o}get maxSize(){return this.#c}get calculatedSize(){return this.#b}get size(){return this.#n}get fetchMethod(){return this.#M}get memoMethod(){return this.#I}get dispose(){return this.#S}get onInsert(){return this.#O}get disposeAfter(){return this.#w}constructor(e){let{max:t=0,ttl:i,ttlResolution:s=1,ttlAutopurge:n,updateAgeOnGet:r,updateAgeOnHas:h,allowStale:a,dispose:o,onInsert:d,disposeAfter:y,noDisposeOnSet:_,noUpdateTTL:u,maxSize:g=0,maxEntrySize:f=0,sizeCalculation:b,fetchMethod:l,memoMethod:w,noDeleteOnFetchRejection:F,noDeleteOnStaleGet:m,allowStaleOnFetchRejection:p,allowStaleOnFetchAbort:z,ignoreFetchAbort:E,backgroundFetchSize:C=1,perf:v}=e;if(this.backgroundFetchSize=C,v!==void 0&&typeof v?.now!="function")throw new TypeError("perf option must have a now() method if specified");if(this.#m=v??M,t!==0&&!T(t))throw new TypeError("max option must be a nonnegative integer");let W=t?G(t):Array;if(!W)throw new Error("invalid max value: "+t);if(this.#o=t,this.#c=g,this.maxEntrySize=f||this.#c,this.sizeCalculation=b,this.sizeCalculation){if(!this.#c&&!this.maxEntrySize)throw new TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");if(typeof this.sizeCalculation!="function")throw new TypeError("sizeCalculation set to non-function")}if(w!==void 0&&typeof w!="function")throw new TypeError("memoMethod must be a function if defined");if(this.#I=w,l!==void 0&&typeof l!="function")throw new TypeError("fetchMethod must be a function if specified");if(this.#M=l,this.#U=!!l,this.#s=new Map,this.#i=Array.from({length:t}).fill(void 0),this.#t=Array.from({length:t}).fill(void 0),this.#l=new W(t),this.#u=new W(t),this.#a=0,this.#h=0,this.#y=R.create(t),this.#n=0,this.#b=0,typeof o=="function"&&(this.#S=o),typeof d=="function"&&(this.#O=d),typeof y=="function"?(this.#w=y,this.#r=[]):(this.#w=void 0,this.#r=void 0),this.#T=!!this.#S,this.#x=!!this.#O,this.#f=!!this.#w,this.noDisposeOnSet=!!_,this.noUpdateTTL=!!u,this.noDeleteOnFetchRejection=!!F,this.allowStaleOnFetchRejection=!!p,this.allowStaleOnFetchAbort=!!z,this.ignoreFetchAbort=!!E,this.maxEntrySize!==0){if(this.#c!==0&&!T(this.#c))throw new TypeError("maxSize must be a positive integer if specified");if(!T(this.maxEntrySize))throw new TypeError("maxEntrySize must be a positive integer if specified");this.#X()}if(this.allowStale=!!a,this.noDeleteOnStaleGet=!!m,this.updateAgeOnGet=!!r,this.updateAgeOnHas=!!h,this.ttlResolution=T(s)||s===0?s:1,this.ttlAutopurge=!!n,this.ttl=i||0,this.ttl){if(!T(this.ttl))throw new TypeError("ttl must be a positive integer if specified");this.#k()}if(this.#o===0&&this.ttl===0&&this.#c===0)throw new TypeError("At least one of max, maxSize, or ttl is required");if(!this.ttlAutopurge&&!this.#o&&!this.#c){let x="LRU_CACHE_UNBOUNDED";k(x)&&(j.add(x),P("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.","UnboundedCacheWarning",x,c))}}getRemainingTTL(e){return this.#s.has(e)?1/0:0}#k(){let e=new O(this.#o),t=new O(this.#o);this.#d=e,this.#F=t;let i=this.ttlAutopurge?Array.from({length:this.#o}):void 0;this.#g=i,this.#H=(h,a,o=this.#m.now())=>{t[h]=a!==0?o:0,e[h]=a,s(h,a)},this.#D=h=>{t[h]=e[h]!==0?this.#m.now():0,s(h,e[h])};let s=this.ttlAutopurge?(h,a)=>{if(i?.[h]&&(clearTimeout(i[h]),i[h]=void 0),a&&a!==0&&i){let o=setTimeout(()=>{this.#p(h)&&this.#E(this.#i[h],"expire")},a+1);o.unref&&o.unref(),i[h]=o}}:()=>{};this.#v=(h,a)=>{if(e[a]){let o=e[a],d=t[a];if(!o||!d)return;h.ttl=o,h.start=d,h.now=n||r();let y=h.now-d;h.remainingTTL=o-y}};let n=0,r=()=>{let h=this.#m.now();if(this.ttlResolution>0){n=h;let a=setTimeout(()=>n=0,this.ttlResolution);a.unref&&a.unref()}return h};this.getRemainingTTL=h=>{let a=this.#s.get(h);if(a===void 0)return 0;let o=e[a],d=t[a];if(!o||!d)return 1/0;let y=(n||r())-d;return o-y},this.#p=h=>{let a=t[h],o=e[h];return!!o&&!!a&&(n||r())-a>o}}#D=()=>{};#v=()=>{};#H=()=>{};#p=()=>!1;#X(){let e=new O(this.#o);this.#b=0,this.#_=e,this.#R=t=>{this.#b-=e[t],e[t]=0},this.#N=(t,i,s,n)=>{if(!T(s)){if(this.#e(i))return this.backgroundFetchSize;if(n){if(typeof n!="function")throw new TypeError("sizeCalculation must be a function");if(s=n(i,t),!T(s))throw new TypeError("sizeCalculation return invalid (expect positive integer)")}else throw new TypeError("invalid size value (must be positive integer). When maxSize or maxEntrySize is used, sizeCalculation or size must be set.")}return s},this.#j=(t,i,s)=>{if(e[t]=i,this.#c){let n=this.#c-e[t];for(;this.#b>n;)this.#G(!0)}this.#b+=e[t],s&&(s.entrySize=i,s.totalCalculatedSize=this.#b)}}#R=e=>{};#j=(e,t,i)=>{};#N=(e,t,i,s)=>{if(i||s)throw new TypeError("cannot set size without setting maxSize or maxEntrySize on cache");return 0};*#A({allowStale:e=this.allowStale}={}){if(this.#n)for(let t=this.#h;this.#V(t)&&((e||!this.#p(t))&&(yield t),t!==this.#a);)t=this.#u[t]}*#z({allowStale:e=this.allowStale}={}){if(this.#n)for(let t=this.#a;this.#V(t)&&((e||!this.#p(t))&&(yield t),t!==this.#h);)t=this.#l[t]}#V(e){return e!==void 0&&this.#s.get(this.#i[e])===e}*entries(){for(let e of this.#A())this.#t[e]!==void 0&&this.#i[e]!==void 0&&!this.#e(this.#t[e])&&(yield[this.#i[e],this.#t[e]])}*rentries(){for(let e of this.#z())this.#t[e]!==void 0&&this.#i[e]!==void 0&&!this.#e(this.#t[e])&&(yield[this.#i[e],this.#t[e]])}*keys(){for(let e of this.#A()){let t=this.#i[e];t!==void 0&&!this.#e(this.#t[e])&&(yield t)}}*rkeys(){for(let e of this.#z()){let t=this.#i[e];t!==void 0&&!this.#e(this.#t[e])&&(yield t)}}*values(){for(let e of this.#A())this.#t[e]!==void 0&&!this.#e(this.#t[e])&&(yield this.#t[e])}*rvalues(){for(let e of this.#z())this.#t[e]!==void 0&&!this.#e(this.#t[e])&&(yield this.#t[e])}[Symbol.iterator](){return this.entries()}[Symbol.toStringTag]="LRUCache";find(e,t={}){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;if(n!==void 0&&e(n,this.#i[i],this))return this.#C(this.#i[i],t)}}forEach(e,t=this){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&e.call(t,n,this.#i[i],this)}}rforEach(e,t=this){for(let i of this.#z()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&e.call(t,n,this.#i[i],this)}}purgeStale(){let e=!1;for(let t of this.#z({allowStale:!0}))this.#p(t)&&(this.#E(this.#i[t],"expire"),e=!0);return e}info(e){let t=this.#s.get(e);if(t===void 0)return;let i=this.#t[t],s=this.#e(i)?i.__staleWhileFetching:i;if(s===void 0)return;let n={value:s};if(this.#d&&this.#F){let r=this.#d[t],h=this.#F[t];if(r&&h){let a=r-(this.#m.now()-h);n.ttl=a,n.start=Date.now()}}return this.#_&&(n.size=this.#_[t]),n}dump(){let e=[];for(let t of this.#A({allowStale:!0})){let i=this.#i[t],s=this.#t[t],n=this.#e(s)?s.__staleWhileFetching:s;if(n===void 0||i===void 0)continue;let r={value:n};if(this.#d&&this.#F){r.ttl=this.#d[t];let h=this.#m.now()-this.#F[t];r.start=Math.floor(Date.now()-h)}this.#_&&(r.size=this.#_[t]),e.unshift([i,r])}return e}load(e){this.clear();for(let[t,i]of e){if(i.start){let s=Date.now()-i.start;i.start=this.#m.now()-s}this.#W(t,i.value,i)}}set(e,t,i={}){let{status:s=S.hasSubscribers?{}:void 0}=i;i.status=s,s&&(s.op="set",s.key=e,t!==void 0&&(s.value=t),s.cache=this);let n=this.#W(e,t,i);return s&&S.hasSubscribers&&S.publish(s),n}#W(e,t,i,s){let{ttl:n=this.ttl,start:r,noDisposeOnSet:h=this.noDisposeOnSet,sizeCalculation:a=this.sizeCalculation,status:o}=i,d=this.#e(t);if(t===void 0)return o&&(o.set="deleted"),this.delete(e),this;let{noUpdateTTL:y=this.noUpdateTTL}=i;o&&!d&&(o.value=t);let _=this.#N(e,t,i.size||0,a,o);if(this.maxEntrySize&&_>this.maxEntrySize)return this.#E(e,"set"),o&&(o.set="miss",o.maxEntrySizeExceeded=!0),this;let u=this.#n===0?void 0:this.#s.get(e);if(u===void 0)u=this.#n===0?this.#h:this.#y.length!==0?this.#y.pop():this.#n===this.#o?this.#G(!1):this.#n,this.#i[u]=e,this.#t[u]=t,this.#s.set(e,u),this.#l[this.#h]=u,this.#u[u]=this.#h,this.#h=u,this.#n++,this.#j(u,_,o),o&&(o.set="add"),y=!1,this.#x&&!d&&this.#O?.(t,e,"add");else{this.#L(u);let g=this.#t[u];if(t!==g){if(!h)if(this.#e(g)){g!==s&&g.__abortController.abort(new Error("replaced"));let{__staleWhileFetching:f}=g;f!==void 0&&f!==t&&(this.#T&&this.#S?.(f,e,"set"),this.#f&&this.#r?.push([f,e,"set"]))}else this.#T&&this.#S?.(g,e,"set"),this.#f&&this.#r?.push([g,e,"set"]);if(this.#R(u),this.#j(u,_,o),this.#t[u]=t,!d){let f=g&&this.#e(g)?g.__staleWhileFetching:g,b=f===void 0?"add":t!==f?"replace":"update";o&&(o.set=b,f!==void 0&&(o.oldValue=f)),this.#x&&this.onInsert?.(t,e,b)}}else d||(o&&(o.set="update"),this.#x&&this.onInsert?.(t,e,"update"))}if(n!==0&&!this.#d&&this.#k(),this.#d&&(y||this.#H(u,n,r),o&&this.#v(o,u)),!h&&this.#f&&this.#r){let g=this.#r,f;for(;f=g?.shift();)this.#w?.(...f)}return this}pop(){try{for(;this.#n;){let e=this.#t[this.#a];if(this.#G(!0),this.#e(e)){if(e.__staleWhileFetching)return e.__staleWhileFetching}else if(e!==void 0)return e}}finally{if(this.#f&&this.#r){let e=this.#r,t;for(;t=e?.shift();)this.#w?.(...t)}}}#G(e){let t=this.#a,i=this.#i[t],s=this.#t[t],n=this.#e(s);n&&s.__abortController.abort(new Error("evicted"));let r=n?s.__staleWhileFetching:s;return(this.#T||this.#f)&&r!==void 0&&(this.#T&&this.#S?.(r,i,"evict"),this.#f&&this.#r?.push([r,i,"evict"])),this.#R(t),this.#g?.[t]&&(clearTimeout(this.#g[t]),this.#g[t]=void 0),e&&(this.#i[t]=void 0,this.#t[t]=void 0,this.#y.push(t)),this.#n===1?(this.#a=this.#h=0,this.#y.length=0):this.#a=this.#l[t],this.#s.delete(i),this.#n--,t}has(e,t={}){let{status:i=S.hasSubscribers?{}:void 0}=t;t.status=i,i&&(i.op="has",i.key=e,i.cache=this);let s=this.#Y(e,t);return S.hasSubscribers&&S.publish(i),s}#Y(e,t={}){let{updateAgeOnHas:i=this.updateAgeOnHas,status:s}=t,n=this.#s.get(e);if(n!==void 0){let r=this.#t[n];if(this.#e(r)&&r.__staleWhileFetching===void 0)return!1;if(this.#p(n))s&&(s.has="stale",this.#v(s,n));else return i&&this.#D(n),s&&(s.has="hit",this.#v(s,n)),!0}else s&&(s.has="miss");return!1}peek(e,t={}){let{status:i=D()?{}:void 0}=t;i&&(i.op="peek",i.key=e,i.cache=this),t.status=i;let s=this.#J(e,t);return S.hasSubscribers&&S.publish(i),s}#J(e,t){let{status:i,allowStale:s=this.allowStale}=t,n=this.#s.get(e);if(n===void 0||!s&&this.#p(n)){i&&(i.peek=n===void 0?"miss":"stale");return}let r=this.#t[n],h=this.#e(r)?r.__staleWhileFetching:r;return i&&(h!==void 0?(i.peek="hit",i.value=h):i.peek="miss"),h}#P(e,t,i,s){let n=t===void 0?void 0:this.#t[t];if(this.#e(n))return n;let r=new AbortController,{signal:h}=i;h?.addEventListener("abort",()=>r.abort(h.reason),{signal:r.signal});let a={signal:r.signal,options:i,context:s},o=(f,b=!1)=>{let{aborted:l}=r.signal,w=i.ignoreFetchAbort&&f!==void 0,F=i.ignoreFetchAbort||!!(i.allowStaleOnFetchAbort&&f!==void 0);if(i.status&&(l&&!b?(i.status.fetchAborted=!0,i.status.fetchError=r.signal.reason,w&&(i.status.fetchAbortIgnored=!0)):i.status.fetchResolved=!0),l&&!w&&!b)return y(r.signal.reason,F);let m=u,p=this.#t[t];return(p===u||p===void 0&&w&&b)&&(f===void 0?m.__staleWhileFetching!==void 0?this.#t[t]=m.__staleWhileFetching:this.#E(e,"fetch"):(i.status&&(i.status.fetchUpdated=!0),this.#W(e,f,a.options,m))),f},d=f=>(i.status&&(i.status.fetchRejected=!0,i.status.fetchError=f),y(f,!1)),y=(f,b)=>{let{aborted:l}=r.signal,w=l&&i.allowStaleOnFetchAbort,F=w||i.allowStaleOnFetchRejection,m=F||i.noDeleteOnFetchRejection,p=u;if(this.#t[t]===u&&(!m||!b&&p.__staleWhileFetching===void 0?this.#E(e,"fetch"):w||(this.#t[t]=p.__staleWhileFetching)),F)return i.status&&p.__staleWhileFetching!==void 0&&(i.status.returnedStale=!0),p.__staleWhileFetching;if(p.__returned===p)throw f},_=(f,b)=>{let l=this.#M?.(e,n,a);r.signal.addEventListener("abort",()=>{(!i.ignoreFetchAbort||i.allowStaleOnFetchAbort)&&(f(void 0),i.allowStaleOnFetchAbort&&(f=w=>o(w,!0)))}),l&&l instanceof Promise?l.then(w=>f(w===void 0?void 0:w),b):l!==void 0&&f(l)};i.status&&(i.status.fetchDispatched=!0);let u=new Promise(_).then(o,d),g=Object.assign(u,{__abortController:r,__staleWhileFetching:n,__returned:void 0});return t===void 0?(this.#W(e,g,{...a.options,status:void 0}),t=this.#s.get(e)):this.#t[t]=g,g}#e(e){if(!this.#U)return!1;let t=e;return!!t&&t instanceof Promise&&t.hasOwnProperty("__staleWhileFetching")&&t.__abortController instanceof AbortController}fetch(e,t={}){let i=A.hasSubscribers,{status:s=D()?{}:void 0}=t;t.status=s,s&&t.context&&(s.context=t.context);let n=this.#B(e,t);return s&&i&&(s.trace=!0,A.tracePromise(()=>n,s).catch(()=>{})),n}async#B(e,t={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,ttl:r=this.ttl,noDisposeOnSet:h=this.noDisposeOnSet,size:a=0,sizeCalculation:o=this.sizeCalculation,noUpdateTTL:d=this.noUpdateTTL,noDeleteOnFetchRejection:y=this.noDeleteOnFetchRejection,allowStaleOnFetchRejection:_=this.allowStaleOnFetchRejection,ignoreFetchAbort:u=this.ignoreFetchAbort,allowStaleOnFetchAbort:g=this.allowStaleOnFetchAbort,context:f,forceRefresh:b=!1,status:l,signal:w}=t;if(l&&(l.op="fetch",l.key=e,b&&(l.forceRefresh=!0),l.cache=this),!this.#U)return l&&(l.fetch="get"),this.#C(e,{allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,status:l});let F={allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,ttl:r,noDisposeOnSet:h,size:a,sizeCalculation:o,noUpdateTTL:d,noDeleteOnFetchRejection:y,allowStaleOnFetchRejection:_,allowStaleOnFetchAbort:g,ignoreFetchAbort:u,status:l,signal:w},m=this.#s.get(e);if(m===void 0){l&&(l.fetch="miss");let p=this.#P(e,m,F,f);return p.__returned=p}else{let p=this.#t[m];if(this.#e(p)){let W=i&&p.__staleWhileFetching!==void 0;return l&&(l.fetch="inflight",W&&(l.returnedStale=!0)),W?p.__staleWhileFetching:p.__returned=p}let z=this.#p(m);if(!b&&!z)return l&&(l.fetch="hit"),this.#L(m),s&&this.#D(m),l&&this.#v(l,m),p;let E=this.#P(e,m,F,f),v=E.__staleWhileFetching!==void 0&&i;return l&&(l.fetch=z?"stale":"refresh",v&&z&&(l.returnedStale=!0)),v?E.__staleWhileFetching:E.__returned=E}}forceFetch(e,t={}){let i=A.hasSubscribers,{status:s=D()?{}:void 0}=t;t.status=s,s&&t.context&&(s.context=t.context);let n=this.#K(e,t);return s&&i&&(s.trace=!0,A.tracePromise(()=>n,s).catch(()=>{})),n}async#K(e,t={}){let i=await this.#B(e,t);if(i===void 0)throw new Error("fetch() returned undefined");return i}memo(e,t={}){let{status:i=S.hasSubscribers?{}:void 0}=t;t.status=i,i&&(i.op="memo",i.key=e,t.context&&(i.context=t.context),i.cache=this);let s=this.#Q(e,t);return i&&(i.value=s),S.hasSubscribers&&S.publish(i),s}#Q(e,t={}){let i=this.#I;if(!i)throw new Error("no memoMethod provided to constructor");let{context:s,status:n,forceRefresh:r,...h}=t;n&&r&&(n.forceRefresh=!0);let a=this.#C(e,h),o=r||a===void 0;if(n&&(n.memo=o?"miss":"hit",o||(n.value=a)),!o)return a;let d=i(e,a,{options:h,context:s});return n&&(n.value=d),this.#W(e,d,h),d}get(e,t={}){let{status:i=S.hasSubscribers?{}:void 0}=t;t.status=i,i&&(i.op="get",i.key=e,i.cache=this);let s=this.#C(e,t);return i&&(s!==void 0&&(i.value=s),S.hasSubscribers&&S.publish(i)),s}#C(e,t={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,status:r}=t,h=this.#s.get(e);if(h===void 0){r&&(r.get="miss");return}let a=this.#t[h],o=this.#e(a);return r&&this.#v(r,h),this.#p(h)?o?(r&&(r.get="stale-fetching"),i&&a.__staleWhileFetching!==void 0?(r&&(r.returnedStale=!0),a.__staleWhileFetching):void 0):(n||this.#E(e,"expire"),r&&(r.get="stale"),i?(r&&(r.returnedStale=!0),a):void 0):(r&&(r.get=o?"fetching":"hit"),this.#L(h),s&&this.#D(h),o?a.__staleWhileFetching:a)}#$(e,t){this.#u[t]=e,this.#l[e]=t}#L(e){e!==this.#h&&(e===this.#a?this.#a=this.#l[e]:this.#$(this.#u[e],this.#l[e]),this.#$(this.#h,e),this.#h=e)}delete(e){return this.#E(e,"delete")}#E(e,t){S.hasSubscribers&&S.publish({op:"delete",delete:t,key:e,cache:this});let i=!1;if(this.#n!==0){let s=this.#s.get(e);if(s!==void 0)if(this.#g?.[s]&&(clearTimeout(this.#g?.[s]),this.#g[s]=void 0),i=!0,this.#n===1)this.#q(t);else{this.#R(s);let n=this.#t[s];if(this.#e(n)?n.__abortController.abort(new Error("deleted")):(this.#T||this.#f)&&(this.#T&&this.#S?.(n,e,t),this.#f&&this.#r?.push([n,e,t])),this.#s.delete(e),this.#i[s]=void 0,this.#t[s]=void 0,s===this.#h)this.#h=this.#u[s];else if(s===this.#a)this.#a=this.#l[s];else{let r=this.#u[s];this.#l[r]=this.#l[s];let h=this.#l[s];this.#u[h]=this.#u[s]}this.#n--,this.#y.push(s)}}if(this.#f&&this.#r?.length){let s=this.#r,n;for(;n=s?.shift();)this.#w?.(...n)}return i}clear(){return this.#q("delete")}#q(e){for(let t of this.#z({allowStale:!0})){let i=this.#t[t];if(this.#e(i))i.__abortController.abort(new Error("deleted"));else{let s=this.#i[t];this.#T&&this.#S?.(i,s,e),this.#f&&this.#r?.push([i,s,e])}}if(this.#s.clear(),this.#t.fill(void 0),this.#i.fill(void 0),this.#d&&this.#F){this.#d.fill(0),this.#F.fill(0);for(let t of this.#g??[])t!==void 0&&clearTimeout(t);this.#g?.fill(void 0)}if(this.#_&&this.#_.fill(0),this.#a=0,this.#h=0,this.#y.length=0,this.#b=0,this.#n=0,this.#f&&this.#r){let t=this.#r,i;for(;i=t?.shift();)this.#w?.(...i)}}};export{U as LRUCache};
+var L={hasSubscribers:!1},S=L,A=L;import("node:diagnostics_channel").then(u=>{S=u.channel("lru-cache:metrics"),A=u.tracingChannel("lru-cache")}).catch(()=>{});var M=typeof performance=="object"&&performance&&typeof performance.now=="function"?performance:Date;var R=()=>S.hasSubscribers||A.hasSubscribers,j=new Set,I=typeof process=="object"&&process?process:{},P=(u,e,t,i)=>{typeof I.emitWarning=="function"?I.emitWarning(u,e,t,i):console.error(`[${t}] ${e}: ${u}`)},k=u=>!j.has(u);var T=u=>!!u&&u===Math.floor(u)&&u>0&&isFinite(u),G=u=>T(u)?u<=Math.pow(2,8)?Uint8Array:u<=Math.pow(2,16)?Uint16Array:u<=Math.pow(2,32)?Uint32Array:u<=Number.MAX_SAFE_INTEGER?O:null:null,O=class extends Array{constructor(e){super(e),this.fill(0)}},x=class u{heap;length;static#o=!1;static create(e){let t=G(e);if(!t)return[];u.#o=!0;let i=new u(e,t);return u.#o=!1,i}constructor(e,t){if(!u.#o)throw new TypeError("instantiate Stack using Stack.create(n)");this.heap=new t(e),this.length=0}push(e){this.heap[this.length++]=e}pop(){return this.heap[--this.length]}},U=class u{#o;#c;#S;#O;#w;#M;#I;#m;get perf(){return this.#m}ttl;ttlResolution;ttlAutopurge;updateAgeOnGet;updateAgeOnHas;allowStale;noDisposeOnSet;noUpdateTTL;maxEntrySize;sizeCalculation;noDeleteOnFetchRejection;noDeleteOnStaleGet;allowStaleOnFetchAbort;allowStaleOnFetchRejection;ignoreFetchAbort;backgroundFetchSize;#n;#b;#s;#i;#t;#l;#u;#a;#h;#y;#r;#_;#F;#d;#g;#T;#U;#f;#D;static unsafeExposeInternals(e){return{starts:e.#F,ttls:e.#d,autopurgeTimers:e.#g,sizes:e.#_,keyMap:e.#s,keyList:e.#i,valList:e.#t,next:e.#l,prev:e.#u,get head(){return e.#a},get tail(){return e.#h},free:e.#y,isBackgroundFetch:t=>e.#e(t),backgroundFetch:(t,i,s,n)=>e.#P(t,i,s,n),moveToTail:t=>e.#L(t),indexes:t=>e.#A(t),rindexes:t=>e.#z(t),isStale:t=>e.#p(t)}}get max(){return this.#o}get maxSize(){return this.#c}get calculatedSize(){return this.#b}get size(){return this.#n}get fetchMethod(){return this.#M}get memoMethod(){return this.#I}get dispose(){return this.#S}get onInsert(){return this.#O}get disposeAfter(){return this.#w}constructor(e){let{max:t=0,ttl:i,ttlResolution:s=1,ttlAutopurge:n,updateAgeOnGet:o,updateAgeOnHas:l,allowStale:h,dispose:r,onInsert:c,disposeAfter:m,noDisposeOnSet:_,noUpdateTTL:d,maxSize:g=0,maxEntrySize:f=0,sizeCalculation:y,fetchMethod:a,memoMethod:w,noDeleteOnFetchRejection:F,noDeleteOnStaleGet:b,allowStaleOnFetchRejection:p,allowStaleOnFetchAbort:z,ignoreFetchAbort:E,backgroundFetchSize:C=1,perf:v}=e;if(this.backgroundFetchSize=C,v!==void 0&&typeof v?.now!="function")throw new TypeError("perf option must have a now() method if specified");if(this.#m=v??M,t!==0&&!T(t))throw new TypeError("max option must be a nonnegative integer");let W=t?G(t):Array;if(!W)throw new Error("invalid max value: "+t);if(this.#o=t,this.#c=g,this.maxEntrySize=f||this.#c,this.sizeCalculation=y,this.sizeCalculation){if(!this.#c&&!this.maxEntrySize)throw new TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");if(typeof this.sizeCalculation!="function")throw new TypeError("sizeCalculation set to non-function")}if(w!==void 0&&typeof w!="function")throw new TypeError("memoMethod must be a function if defined");if(this.#I=w,a!==void 0&&typeof a!="function")throw new TypeError("fetchMethod must be a function if specified");if(this.#M=a,this.#U=!!a,this.#s=new Map,this.#i=Array.from({length:t}).fill(void 0),this.#t=Array.from({length:t}).fill(void 0),this.#l=new W(t),this.#u=new W(t),this.#a=0,this.#h=0,this.#y=x.create(t),this.#n=0,this.#b=0,typeof r=="function"&&(this.#S=r),typeof c=="function"&&(this.#O=c),typeof m=="function"?(this.#w=m,this.#r=[]):(this.#w=void 0,this.#r=void 0),this.#T=!!this.#S,this.#D=!!this.#O,this.#f=!!this.#w,this.noDisposeOnSet=!!_,this.noUpdateTTL=!!d,this.noDeleteOnFetchRejection=!!F,this.allowStaleOnFetchRejection=!!p,this.allowStaleOnFetchAbort=!!z,this.ignoreFetchAbort=!!E,this.maxEntrySize!==0){if(this.#c!==0&&!T(this.#c))throw new TypeError("maxSize must be a positive integer if specified");if(!T(this.maxEntrySize))throw new TypeError("maxEntrySize must be a positive integer if specified");this.#X()}if(this.allowStale=!!h,this.noDeleteOnStaleGet=!!b,this.updateAgeOnGet=!!o,this.updateAgeOnHas=!!l,this.ttlResolution=T(s)||s===0?s:1,this.ttlAutopurge=!!n,this.ttl=i||0,this.ttl){if(!T(this.ttl))throw new TypeError("ttl must be a positive integer if specified");this.#k()}if(this.#o===0&&this.ttl===0&&this.#c===0)throw new TypeError("At least one of max, maxSize, or ttl is required");if(!this.ttlAutopurge&&!this.#o&&!this.#c){let D="LRU_CACHE_UNBOUNDED";k(D)&&(j.add(D),P("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.","UnboundedCacheWarning",D,u))}}getRemainingTTL(e){return this.#s.has(e)?1/0:0}#k(){let e=new O(this.#o),t=new O(this.#o);this.#d=e,this.#F=t;let i=this.ttlAutopurge?Array.from({length:this.#o}):void 0;this.#g=i,this.#H=(h,r,c=this.#m.now())=>{t[h]=r!==0?c:0,e[h]=r,s(h,r)},this.#R=h=>{t[h]=e[h]!==0?this.#m.now():0,s(h,e[h])};let s=this.ttlAutopurge?(h,r)=>{if(i?.[h]&&(clearTimeout(i[h]),i[h]=void 0),r&&r!==0&&i){let c=setTimeout(()=>{this.#p(h)?(this.#E(this.#i[h],"expire"),i[h]=void 0):s(h,l(h))},r+1);c.unref&&c.unref(),i[h]=c}}:()=>{};this.#v=(h,r)=>{if(e[r]){let c=e[r],m=t[r];if(!c||!m)return;h.ttl=c,h.start=m,h.now=n||o();let _=h.now-m;h.remainingTTL=c-_}};let n=0,o=()=>{let h=this.#m.now();if(this.ttlResolution>0){n=h;let r=setTimeout(()=>n=0,this.ttlResolution);r.unref&&r.unref()}return h};this.getRemainingTTL=h=>{let r=this.#s.get(h);return r===void 0?0:l(r)};let l=h=>{let r=e[h],c=t[h];if(!r||!c)return 1/0;let m=(n||o())-c;return r-m};this.#p=h=>{let r=t[h],c=e[h];return!!c&&!!r&&(n||o())-r>c}}#R=()=>{};#v=()=>{};#H=()=>{};#p=()=>!1;#X(){let e=new O(this.#o);this.#b=0,this.#_=e,this.#x=t=>{this.#b-=e[t],e[t]=0},this.#N=(t,i,s,n)=>{if(!T(s)){if(this.#e(i))return this.backgroundFetchSize;if(n){if(typeof n!="function")throw new TypeError("sizeCalculation must be a function");if(s=n(i,t),!T(s))throw new TypeError("sizeCalculation return invalid (expect positive integer)")}else throw new TypeError("invalid size value (must be positive integer). When maxSize or maxEntrySize is used, sizeCalculation or size must be set.")}return s},this.#j=(t,i,s)=>{if(e[t]=i,this.#c){let n=this.#c-e[t];for(;this.#b>n;)this.#G(!0)}this.#b+=e[t],s&&(s.entrySize=i,s.totalCalculatedSize=this.#b)}}#x=e=>{};#j=(e,t,i)=>{};#N=(e,t,i,s)=>{if(i||s)throw new TypeError("cannot set size without setting maxSize or maxEntrySize on cache");return 0};*#A({allowStale:e=this.allowStale}={}){if(this.#n)for(let t=this.#h;this.#V(t)&&((e||!this.#p(t))&&(yield t),t!==this.#a);)t=this.#u[t]}*#z({allowStale:e=this.allowStale}={}){if(this.#n)for(let t=this.#a;this.#V(t)&&((e||!this.#p(t))&&(yield t),t!==this.#h);)t=this.#l[t]}#V(e){return e!==void 0&&this.#s.get(this.#i[e])===e}*entries(){for(let e of this.#A())this.#t[e]!==void 0&&this.#i[e]!==void 0&&!this.#e(this.#t[e])&&(yield[this.#i[e],this.#t[e]])}*rentries(){for(let e of this.#z())this.#t[e]!==void 0&&this.#i[e]!==void 0&&!this.#e(this.#t[e])&&(yield[this.#i[e],this.#t[e]])}*keys(){for(let e of this.#A()){let t=this.#i[e];t!==void 0&&!this.#e(this.#t[e])&&(yield t)}}*rkeys(){for(let e of this.#z()){let t=this.#i[e];t!==void 0&&!this.#e(this.#t[e])&&(yield t)}}*values(){for(let e of this.#A())this.#t[e]!==void 0&&!this.#e(this.#t[e])&&(yield this.#t[e])}*rvalues(){for(let e of this.#z())this.#t[e]!==void 0&&!this.#e(this.#t[e])&&(yield this.#t[e])}[Symbol.iterator](){return this.entries()}[Symbol.toStringTag]="LRUCache";find(e,t={}){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;if(n!==void 0&&e(n,this.#i[i],this))return this.#C(this.#i[i],t)}}forEach(e,t=this){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&e.call(t,n,this.#i[i],this)}}rforEach(e,t=this){for(let i of this.#z()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&e.call(t,n,this.#i[i],this)}}purgeStale(){let e=!1;for(let t of this.#z({allowStale:!0}))this.#p(t)&&(this.#E(this.#i[t],"expire"),e=!0);return e}info(e){let t=this.#s.get(e);if(t===void 0)return;let i=this.#t[t],s=this.#e(i)?i.__staleWhileFetching:i;if(s===void 0)return;let n={value:s};if(this.#d&&this.#F){let o=this.#d[t],l=this.#F[t];if(o&&l){let h=o-(this.#m.now()-l);n.ttl=h,n.start=Date.now()}}return this.#_&&(n.size=this.#_[t]),n}dump(){let e=[];for(let t of this.#A({allowStale:!0})){let i=this.#i[t],s=this.#t[t],n=this.#e(s)?s.__staleWhileFetching:s;if(n===void 0||i===void 0)continue;let o={value:n};if(this.#d&&this.#F){o.ttl=this.#d[t];let l=this.#m.now()-this.#F[t];o.start=Math.floor(Date.now()-l)}this.#_&&(o.size=this.#_[t]),e.unshift([i,o])}return e}load(e){this.clear();for(let[t,i]of e){if(i.start){let s=Date.now()-i.start;i.start=this.#m.now()-s}this.#W(t,i.value,i)}}set(e,t,i={}){let{status:s=S.hasSubscribers?{}:void 0}=i;i.status=s,s&&(s.op="set",s.key=e,t!==void 0&&(s.value=t),s.cache=this);let n=this.#W(e,t,i);return s&&S.hasSubscribers&&S.publish(s),n}#W(e,t,i,s){let{ttl:n=this.ttl,start:o,noDisposeOnSet:l=this.noDisposeOnSet,sizeCalculation:h=this.sizeCalculation,status:r}=i,c=this.#e(t);if(t===void 0)return r&&(r.set="deleted"),this.delete(e),this;let{noUpdateTTL:m=this.noUpdateTTL}=i;r&&!c&&(r.value=t);let _=this.#N(e,t,i.size||0,h,r);if(this.maxEntrySize&&_>this.maxEntrySize)return this.#E(e,"set"),r&&(r.set="miss",r.maxEntrySizeExceeded=!0),this;let d=this.#n===0?void 0:this.#s.get(e);if(d===void 0)d=this.#n===0?this.#h:this.#y.length!==0?this.#y.pop():this.#n===this.#o?this.#G(!1):this.#n,this.#i[d]=e,this.#t[d]=t,this.#s.set(e,d),this.#l[this.#h]=d,this.#u[d]=this.#h,this.#h=d,this.#n++,this.#j(d,_,r),r&&(r.set="add"),m=!1,this.#D&&!c&&this.#O?.(t,e,"add");else{this.#L(d);let g=this.#t[d];if(t!==g){if(!l)if(this.#e(g)){g!==s&&g.__abortController.abort(new Error("replaced"));let{__staleWhileFetching:f}=g;f!==void 0&&f!==t&&(this.#T&&this.#S?.(f,e,"set"),this.#f&&this.#r?.push([f,e,"set"]))}else this.#T&&this.#S?.(g,e,"set"),this.#f&&this.#r?.push([g,e,"set"]);if(this.#x(d),this.#j(d,_,r),this.#t[d]=t,!c){let f=g&&this.#e(g)?g.__staleWhileFetching:g,y=f===void 0?"add":t!==f?"replace":"update";r&&(r.set=y,f!==void 0&&(r.oldValue=f)),this.#D&&this.onInsert?.(t,e,y)}}else c||(r&&(r.set="update"),this.#D&&this.onInsert?.(t,e,"update"))}if(n!==0&&!this.#d&&this.#k(),this.#d&&(m||this.#H(d,n,o),r&&this.#v(r,d)),!l&&this.#f&&this.#r){let g=this.#r,f;for(;f=g?.shift();)this.#w?.(...f)}return this}pop(){try{for(;this.#n;){let e=this.#t[this.#a];if(this.#G(!0),this.#e(e)){if(e.__staleWhileFetching)return e.__staleWhileFetching}else if(e!==void 0)return e}}finally{if(this.#f&&this.#r){let e=this.#r,t;for(;t=e?.shift();)this.#w?.(...t)}}}#G(e){let t=this.#a,i=this.#i[t],s=this.#t[t],n=this.#e(s);n&&s.__abortController.abort(new Error("evicted"));let o=n?s.__staleWhileFetching:s;return(this.#T||this.#f)&&o!==void 0&&(this.#T&&this.#S?.(o,i,"evict"),this.#f&&this.#r?.push([o,i,"evict"])),this.#x(t),this.#g?.[t]&&(clearTimeout(this.#g[t]),this.#g[t]=void 0),e&&(this.#i[t]=void 0,this.#t[t]=void 0,this.#y.push(t)),this.#n===1?(this.#a=this.#h=0,this.#y.length=0):this.#a=this.#l[t],this.#s.delete(i),this.#n--,t}has(e,t={}){let{status:i=S.hasSubscribers?{}:void 0}=t;t.status=i,i&&(i.op="has",i.key=e,i.cache=this);let s=this.#Y(e,t);return S.hasSubscribers&&S.publish(i),s}#Y(e,t={}){let{updateAgeOnHas:i=this.updateAgeOnHas,status:s}=t,n=this.#s.get(e);if(n!==void 0){let o=this.#t[n];if(this.#e(o)&&o.__staleWhileFetching===void 0)return!1;if(this.#p(n))s&&(s.has="stale",this.#v(s,n));else return i&&this.#R(n),s&&(s.has="hit",this.#v(s,n)),!0}else s&&(s.has="miss");return!1}peek(e,t={}){let{status:i=R()?{}:void 0}=t;i&&(i.op="peek",i.key=e,i.cache=this),t.status=i;let s=this.#J(e,t);return S.hasSubscribers&&S.publish(i),s}#J(e,t){let{status:i,allowStale:s=this.allowStale}=t,n=this.#s.get(e);if(n===void 0||!s&&this.#p(n)){i&&(i.peek=n===void 0?"miss":"stale");return}let o=this.#t[n],l=this.#e(o)?o.__staleWhileFetching:o;return i&&(l!==void 0?(i.peek="hit",i.value=l):i.peek="miss"),l}#P(e,t,i,s){let n=t===void 0?void 0:this.#t[t];if(this.#e(n))return n;let o=new AbortController,{signal:l}=i;l?.addEventListener("abort",()=>o.abort(l.reason),{signal:o.signal});let h={signal:o.signal,options:i,context:s},r=(f,y=!1)=>{let{aborted:a}=o.signal,w=i.ignoreFetchAbort&&f!==void 0,F=i.ignoreFetchAbort||!!(i.allowStaleOnFetchAbort&&f!==void 0);if(i.status&&(a&&!y?(i.status.fetchAborted=!0,i.status.fetchError=o.signal.reason,w&&(i.status.fetchAbortIgnored=!0)):i.status.fetchResolved=!0),a&&!w&&!y)return m(o.signal.reason,F);let b=d,p=this.#t[t];return(p===d||p===void 0&&w&&y)&&(f===void 0?b.__staleWhileFetching!==void 0?this.#t[t]=b.__staleWhileFetching:this.#E(e,"fetch"):(i.status&&(i.status.fetchUpdated=!0),this.#W(e,f,h.options,b))),f},c=f=>(i.status&&(i.status.fetchRejected=!0,i.status.fetchError=f),m(f,!1)),m=(f,y)=>{let{aborted:a}=o.signal,w=a&&i.allowStaleOnFetchAbort,F=w||i.allowStaleOnFetchRejection,b=F||i.noDeleteOnFetchRejection,p=d;if(this.#t[t]===d&&(!b||!y&&p.__staleWhileFetching===void 0?this.#E(e,"fetch"):w||(this.#t[t]=p.__staleWhileFetching)),F)return i.status&&p.__staleWhileFetching!==void 0&&(i.status.returnedStale=!0),p.__staleWhileFetching;if(p.__returned===p)throw f},_=(f,y)=>{let a=this.#M?.(e,n,h);o.signal.addEventListener("abort",()=>{(!i.ignoreFetchAbort||i.allowStaleOnFetchAbort)&&(f(void 0),i.allowStaleOnFetchAbort&&(f=w=>r(w,!0)))}),a&&a instanceof Promise?a.then(w=>f(w===void 0?void 0:w),y):a!==void 0&&f(a)};i.status&&(i.status.fetchDispatched=!0);let d=new Promise(_).then(r,c),g=Object.assign(d,{__abortController:o,__staleWhileFetching:n,__returned:void 0});return t===void 0?(this.#W(e,g,{...h.options,status:void 0}),t=this.#s.get(e)):this.#t[t]=g,g}#e(e){if(!this.#U)return!1;let t=e;return!!t&&t instanceof Promise&&t.hasOwnProperty("__staleWhileFetching")&&t.__abortController instanceof AbortController}fetch(e,t={}){let i=A.hasSubscribers,{status:s=R()?{}:void 0}=t;t.status=s,s&&t.context&&(s.context=t.context);let n=this.#B(e,t);return s&&i&&(s.trace=!0,A.tracePromise(()=>n,s).catch(()=>{})),n}async#B(e,t={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,ttl:o=this.ttl,noDisposeOnSet:l=this.noDisposeOnSet,size:h=0,sizeCalculation:r=this.sizeCalculation,noUpdateTTL:c=this.noUpdateTTL,noDeleteOnFetchRejection:m=this.noDeleteOnFetchRejection,allowStaleOnFetchRejection:_=this.allowStaleOnFetchRejection,ignoreFetchAbort:d=this.ignoreFetchAbort,allowStaleOnFetchAbort:g=this.allowStaleOnFetchAbort,context:f,forceRefresh:y=!1,status:a,signal:w}=t;if(a&&(a.op="fetch",a.key=e,y&&(a.forceRefresh=!0),a.cache=this),!this.#U)return a&&(a.fetch="get"),this.#C(e,{allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,status:a});let F={allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,ttl:o,noDisposeOnSet:l,size:h,sizeCalculation:r,noUpdateTTL:c,noDeleteOnFetchRejection:m,allowStaleOnFetchRejection:_,allowStaleOnFetchAbort:g,ignoreFetchAbort:d,status:a,signal:w},b=this.#s.get(e);if(b===void 0){a&&(a.fetch="miss");let p=this.#P(e,b,F,f);return p.__returned=p}else{let p=this.#t[b];if(this.#e(p)){let W=i&&p.__staleWhileFetching!==void 0;return a&&(a.fetch="inflight",W&&(a.returnedStale=!0)),W?p.__staleWhileFetching:p.__returned=p}let z=this.#p(b);if(!y&&!z)return a&&(a.fetch="hit"),this.#L(b),s&&this.#R(b),a&&this.#v(a,b),p;let E=this.#P(e,b,F,f),v=E.__staleWhileFetching!==void 0&&i;return a&&(a.fetch=z?"stale":"refresh",v&&z&&(a.returnedStale=!0)),v?E.__staleWhileFetching:E.__returned=E}}forceFetch(e,t={}){let i=A.hasSubscribers,{status:s=R()?{}:void 0}=t;t.status=s,s&&t.context&&(s.context=t.context);let n=this.#K(e,t);return s&&i&&(s.trace=!0,A.tracePromise(()=>n,s).catch(()=>{})),n}async#K(e,t={}){let i=await this.#B(e,t);if(i===void 0)throw new Error("fetch() returned undefined");return i}memo(e,t={}){let{status:i=S.hasSubscribers?{}:void 0}=t;t.status=i,i&&(i.op="memo",i.key=e,t.context&&(i.context=t.context),i.cache=this);let s=this.#Q(e,t);return i&&(i.value=s),S.hasSubscribers&&S.publish(i),s}#Q(e,t={}){let i=this.#I;if(!i)throw new Error("no memoMethod provided to constructor");let{context:s,status:n,forceRefresh:o,...l}=t;n&&o&&(n.forceRefresh=!0);let h=this.#C(e,l),r=o||h===void 0;if(n&&(n.memo=r?"miss":"hit",r||(n.value=h)),!r)return h;let c=i(e,h,{options:l,context:s});return n&&(n.value=c),this.#W(e,c,l),c}get(e,t={}){let{status:i=S.hasSubscribers?{}:void 0}=t;t.status=i,i&&(i.op="get",i.key=e,i.cache=this);let s=this.#C(e,t);return i&&(s!==void 0&&(i.value=s),S.hasSubscribers&&S.publish(i)),s}#C(e,t={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,status:o}=t,l=this.#s.get(e);if(l===void 0){o&&(o.get="miss");return}let h=this.#t[l],r=this.#e(h);return o&&this.#v(o,l),this.#p(l)?r?(o&&(o.get="stale-fetching"),i&&h.__staleWhileFetching!==void 0?(o&&(o.returnedStale=!0),h.__staleWhileFetching):void 0):(n||this.#E(e,"expire"),o&&(o.get="stale"),i?(o&&(o.returnedStale=!0),h):void 0):(o&&(o.get=r?"fetching":"hit"),this.#L(l),s&&this.#R(l),r?h.__staleWhileFetching:h)}#$(e,t){this.#u[t]=e,this.#l[e]=t}#L(e){e!==this.#h&&(e===this.#a?this.#a=this.#l[e]:this.#$(this.#u[e],this.#l[e]),this.#$(this.#h,e),this.#h=e)}delete(e){return this.#E(e,"delete")}#E(e,t){S.hasSubscribers&&S.publish({op:"delete",delete:t,key:e,cache:this});let i=!1;if(this.#n!==0){let s=this.#s.get(e);if(s!==void 0)if(this.#g?.[s]&&(clearTimeout(this.#g[s]),this.#g[s]=void 0),i=!0,this.#n===1)this.#q(t);else{this.#x(s);let n=this.#t[s];if(this.#e(n)?n.__abortController.abort(new Error("deleted")):(this.#T||this.#f)&&(this.#T&&this.#S?.(n,e,t),this.#f&&this.#r?.push([n,e,t])),this.#s.delete(e),this.#i[s]=void 0,this.#t[s]=void 0,s===this.#h)this.#h=this.#u[s];else if(s===this.#a)this.#a=this.#l[s];else{let o=this.#u[s];this.#l[o]=this.#l[s];let l=this.#l[s];this.#u[l]=this.#u[s]}this.#n--,this.#y.push(s)}}if(this.#f&&this.#r?.length){let s=this.#r,n;for(;n=s?.shift();)this.#w?.(...n)}return i}clear(){return this.#q("delete")}#q(e){for(let t of this.#z({allowStale:!0})){let i=this.#t[t];if(this.#e(i))i.__abortController.abort(new Error("deleted"));else{let s=this.#i[t];this.#T&&this.#S?.(i,s,e),this.#f&&this.#r?.push([i,s,e])}}if(this.#s.clear(),this.#t.fill(void 0),this.#i.fill(void 0),this.#d&&this.#F){this.#d.fill(0),this.#F.fill(0);for(let t of this.#g??[])t!==void 0&&clearTimeout(t);this.#g?.fill(void 0)}if(this.#_&&this.#_.fill(0),this.#a=0,this.#h=0,this.#y.length=0,this.#b=0,this.#n=0,this.#f&&this.#r){let t=this.#r,i;for(;i=t?.shift();)this.#w?.(...i)}}};export{U as LRUCache};
//# sourceMappingURL=index.min.js.map
diff --git a/deps/npm/node_modules/lru-cache/dist/esm/node/index.js b/deps/npm/node_modules/lru-cache/dist/esm/node/index.js
index 114a4e99083..c0fbe78aa7b 100644
--- a/deps/npm/node_modules/lru-cache/dist/esm/node/index.js
+++ b/deps/npm/node_modules/lru-cache/dist/esm/node/index.js
@@ -409,17 +409,17 @@ export class LRUCache {
this.#setItemTTL = (index, ttl, start = this.#perf.now()) => {
starts[index] = ttl !== 0 ? start : 0;
ttls[index] = ttl;
- setPurgetTimer(index, ttl);
+ setPurgeTimer(index, ttl);
};
this.#updateItemAge = index => {
starts[index] = ttls[index] !== 0 ? this.#perf.now() : 0;
- setPurgetTimer(index, ttls[index]);
+ setPurgeTimer(index, ttls[index]);
};
// clear out the purge timer if we're setting TTL to 0, and
// previously had a ttl purge timer running, so it doesn't
// fire unnecessarily. Don't need to do this if we're not doing
// autopurge.
- const setPurgetTimer = !this.ttlAutopurge ?
+ const setPurgeTimer = !this.ttlAutopurge ?
() => { }
: (index, ttl) => {
if (purgeTimers?.[index]) {
@@ -430,6 +430,10 @@ export class LRUCache {
const t = setTimeout(() => {
if (this.#isStale(index)) {
this.#delete(this.#keyList[index], 'expire');
+ purgeTimers[index] = undefined;
+ }
+ else {
+ setPurgeTimer(index, getRemainingTTL(index));
}
}, ttl + 1);
// unref() not supported on all platforms
@@ -479,6 +483,9 @@ export class LRUCache {
if (index === undefined) {
return 0;
}
+ return getRemainingTTL(index);
+ };
+ const getRemainingTTL = (index) => {
const ttl = ttls[index];
const start = starts[index];
if (!ttl || !start) {
@@ -1618,7 +1625,7 @@ export class LRUCache {
const index = this.#keyMap.get(k);
if (index !== undefined) {
if (this.#autopurgeTimers?.[index]) {
- clearTimeout(this.#autopurgeTimers?.[index]);
+ clearTimeout(this.#autopurgeTimers[index]);
this.#autopurgeTimers[index] = undefined;
}
deleted = true;
diff --git a/deps/npm/node_modules/lru-cache/dist/esm/node/index.min.js b/deps/npm/node_modules/lru-cache/dist/esm/node/index.min.js
index 84c4c3ec14f..94b9204bdbd 100644
--- a/deps/npm/node_modules/lru-cache/dist/esm/node/index.min.js
+++ b/deps/npm/node_modules/lru-cache/dist/esm/node/index.min.js
@@ -1,2 +1,2 @@
-import{tracingChannel as G,channel as P}from"node:diagnostics_channel";var S=P("lru-cache:metrics"),W=G("lru-cache");var L=typeof performance=="object"&&performance&&typeof performance.now=="function"?performance:Date;var D=()=>S.hasSubscribers||W.hasSubscribers,U=new Set,M=typeof process=="object"&&process?process:{},k=(u,e,t,i)=>{typeof M.emitWarning=="function"?M.emitWarning(u,e,t,i):console.error(`[${t}] ${e}: ${u}`)},H=u=>!U.has(u);var T=u=>!!u&&u===Math.floor(u)&&u>0&&isFinite(u),j=u=>T(u)?u<=Math.pow(2,8)?Uint8Array:u<=Math.pow(2,16)?Uint16Array:u<=Math.pow(2,32)?Uint32Array:u<=Number.MAX_SAFE_INTEGER?O:null:null,O=class extends Array{constructor(e){super(e),this.fill(0)}},R=class u{heap;length;static#o=!1;static create(e){let t=j(e);if(!t)return[];u.#o=!0;let i=new u(e,t);return u.#o=!1,i}constructor(e,t){if(!u.#o)throw new TypeError("instantiate Stack using Stack.create(n)");this.heap=new t(e),this.length=0}push(e){this.heap[this.length++]=e}pop(){return this.heap[--this.length]}},I=class u{#o;#c;#S;#O;#w;#M;#I;#m;get perf(){return this.#m}ttl;ttlResolution;ttlAutopurge;updateAgeOnGet;updateAgeOnHas;allowStale;noDisposeOnSet;noUpdateTTL;maxEntrySize;sizeCalculation;noDeleteOnFetchRejection;noDeleteOnStaleGet;allowStaleOnFetchAbort;allowStaleOnFetchRejection;ignoreFetchAbort;backgroundFetchSize;#n;#b;#s;#i;#t;#l;#u;#a;#h;#y;#r;#_;#F;#d;#g;#T;#U;#f;#x;static unsafeExposeInternals(e){return{starts:e.#F,ttls:e.#d,autopurgeTimers:e.#g,sizes:e.#_,keyMap:e.#s,keyList:e.#i,valList:e.#t,next:e.#l,prev:e.#u,get head(){return e.#a},get tail(){return e.#h},free:e.#y,isBackgroundFetch:t=>e.#e(t),backgroundFetch:(t,i,s,n)=>e.#P(t,i,s,n),moveToTail:t=>e.#L(t),indexes:t=>e.#A(t),rindexes:t=>e.#z(t),isStale:t=>e.#p(t)}}get max(){return this.#o}get maxSize(){return this.#c}get calculatedSize(){return this.#b}get size(){return this.#n}get fetchMethod(){return this.#M}get memoMethod(){return this.#I}get dispose(){return this.#S}get onInsert(){return this.#O}get disposeAfter(){return this.#w}constructor(e){let{max:t=0,ttl:i,ttlResolution:s=1,ttlAutopurge:n,updateAgeOnGet:r,updateAgeOnHas:h,allowStale:a,dispose:o,onInsert:d,disposeAfter:y,noDisposeOnSet:_,noUpdateTTL:c,maxSize:g=0,maxEntrySize:f=0,sizeCalculation:b,fetchMethod:l,memoMethod:w,noDeleteOnFetchRejection:F,noDeleteOnStaleGet:m,allowStaleOnFetchRejection:p,allowStaleOnFetchAbort:A,ignoreFetchAbort:z,backgroundFetchSize:C=1,perf:E}=e;if(this.backgroundFetchSize=C,E!==void 0&&typeof E?.now!="function")throw new TypeError("perf option must have a now() method if specified");if(this.#m=E??L,t!==0&&!T(t))throw new TypeError("max option must be a nonnegative integer");let v=t?j(t):Array;if(!v)throw new Error("invalid max value: "+t);if(this.#o=t,this.#c=g,this.maxEntrySize=f||this.#c,this.sizeCalculation=b,this.sizeCalculation){if(!this.#c&&!this.maxEntrySize)throw new TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");if(typeof this.sizeCalculation!="function")throw new TypeError("sizeCalculation set to non-function")}if(w!==void 0&&typeof w!="function")throw new TypeError("memoMethod must be a function if defined");if(this.#I=w,l!==void 0&&typeof l!="function")throw new TypeError("fetchMethod must be a function if specified");if(this.#M=l,this.#U=!!l,this.#s=new Map,this.#i=Array.from({length:t}).fill(void 0),this.#t=Array.from({length:t}).fill(void 0),this.#l=new v(t),this.#u=new v(t),this.#a=0,this.#h=0,this.#y=R.create(t),this.#n=0,this.#b=0,typeof o=="function"&&(this.#S=o),typeof d=="function"&&(this.#O=d),typeof y=="function"?(this.#w=y,this.#r=[]):(this.#w=void 0,this.#r=void 0),this.#T=!!this.#S,this.#x=!!this.#O,this.#f=!!this.#w,this.noDisposeOnSet=!!_,this.noUpdateTTL=!!c,this.noDeleteOnFetchRejection=!!F,this.allowStaleOnFetchRejection=!!p,this.allowStaleOnFetchAbort=!!A,this.ignoreFetchAbort=!!z,this.maxEntrySize!==0){if(this.#c!==0&&!T(this.#c))throw new TypeError("maxSize must be a positive integer if specified");if(!T(this.maxEntrySize))throw new TypeError("maxEntrySize must be a positive integer if specified");this.#X()}if(this.allowStale=!!a,this.noDeleteOnStaleGet=!!m,this.updateAgeOnGet=!!r,this.updateAgeOnHas=!!h,this.ttlResolution=T(s)||s===0?s:1,this.ttlAutopurge=!!n,this.ttl=i||0,this.ttl){if(!T(this.ttl))throw new TypeError("ttl must be a positive integer if specified");this.#k()}if(this.#o===0&&this.ttl===0&&this.#c===0)throw new TypeError("At least one of max, maxSize, or ttl is required");if(!this.ttlAutopurge&&!this.#o&&!this.#c){let x="LRU_CACHE_UNBOUNDED";H(x)&&(U.add(x),k("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.","UnboundedCacheWarning",x,u))}}getRemainingTTL(e){return this.#s.has(e)?1/0:0}#k(){let e=new O(this.#o),t=new O(this.#o);this.#d=e,this.#F=t;let i=this.ttlAutopurge?Array.from({length:this.#o}):void 0;this.#g=i,this.#H=(h,a,o=this.#m.now())=>{t[h]=a!==0?o:0,e[h]=a,s(h,a)},this.#D=h=>{t[h]=e[h]!==0?this.#m.now():0,s(h,e[h])};let s=this.ttlAutopurge?(h,a)=>{if(i?.[h]&&(clearTimeout(i[h]),i[h]=void 0),a&&a!==0&&i){let o=setTimeout(()=>{this.#p(h)&&this.#E(this.#i[h],"expire")},a+1);o.unref&&o.unref(),i[h]=o}}:()=>{};this.#v=(h,a)=>{if(e[a]){let o=e[a],d=t[a];if(!o||!d)return;h.ttl=o,h.start=d,h.now=n||r();let y=h.now-d;h.remainingTTL=o-y}};let n=0,r=()=>{let h=this.#m.now();if(this.ttlResolution>0){n=h;let a=setTimeout(()=>n=0,this.ttlResolution);a.unref&&a.unref()}return h};this.getRemainingTTL=h=>{let a=this.#s.get(h);if(a===void 0)return 0;let o=e[a],d=t[a];if(!o||!d)return 1/0;let y=(n||r())-d;return o-y},this.#p=h=>{let a=t[h],o=e[h];return!!o&&!!a&&(n||r())-a>o}}#D=()=>{};#v=()=>{};#H=()=>{};#p=()=>!1;#X(){let e=new O(this.#o);this.#b=0,this.#_=e,this.#R=t=>{this.#b-=e[t],e[t]=0},this.#N=(t,i,s,n)=>{if(!T(s)){if(this.#e(i))return this.backgroundFetchSize;if(n){if(typeof n!="function")throw new TypeError("sizeCalculation must be a function");if(s=n(i,t),!T(s))throw new TypeError("sizeCalculation return invalid (expect positive integer)")}else throw new TypeError("invalid size value (must be positive integer). When maxSize or maxEntrySize is used, sizeCalculation or size must be set.")}return s},this.#j=(t,i,s)=>{if(e[t]=i,this.#c){let n=this.#c-e[t];for(;this.#b>n;)this.#G(!0)}this.#b+=e[t],s&&(s.entrySize=i,s.totalCalculatedSize=this.#b)}}#R=e=>{};#j=(e,t,i)=>{};#N=(e,t,i,s)=>{if(i||s)throw new TypeError("cannot set size without setting maxSize or maxEntrySize on cache");return 0};*#A({allowStale:e=this.allowStale}={}){if(this.#n)for(let t=this.#h;this.#V(t)&&((e||!this.#p(t))&&(yield t),t!==this.#a);)t=this.#u[t]}*#z({allowStale:e=this.allowStale}={}){if(this.#n)for(let t=this.#a;this.#V(t)&&((e||!this.#p(t))&&(yield t),t!==this.#h);)t=this.#l[t]}#V(e){return e!==void 0&&this.#s.get(this.#i[e])===e}*entries(){for(let e of this.#A())this.#t[e]!==void 0&&this.#i[e]!==void 0&&!this.#e(this.#t[e])&&(yield[this.#i[e],this.#t[e]])}*rentries(){for(let e of this.#z())this.#t[e]!==void 0&&this.#i[e]!==void 0&&!this.#e(this.#t[e])&&(yield[this.#i[e],this.#t[e]])}*keys(){for(let e of this.#A()){let t=this.#i[e];t!==void 0&&!this.#e(this.#t[e])&&(yield t)}}*rkeys(){for(let e of this.#z()){let t=this.#i[e];t!==void 0&&!this.#e(this.#t[e])&&(yield t)}}*values(){for(let e of this.#A())this.#t[e]!==void 0&&!this.#e(this.#t[e])&&(yield this.#t[e])}*rvalues(){for(let e of this.#z())this.#t[e]!==void 0&&!this.#e(this.#t[e])&&(yield this.#t[e])}[Symbol.iterator](){return this.entries()}[Symbol.toStringTag]="LRUCache";find(e,t={}){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;if(n!==void 0&&e(n,this.#i[i],this))return this.#C(this.#i[i],t)}}forEach(e,t=this){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&e.call(t,n,this.#i[i],this)}}rforEach(e,t=this){for(let i of this.#z()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&e.call(t,n,this.#i[i],this)}}purgeStale(){let e=!1;for(let t of this.#z({allowStale:!0}))this.#p(t)&&(this.#E(this.#i[t],"expire"),e=!0);return e}info(e){let t=this.#s.get(e);if(t===void 0)return;let i=this.#t[t],s=this.#e(i)?i.__staleWhileFetching:i;if(s===void 0)return;let n={value:s};if(this.#d&&this.#F){let r=this.#d[t],h=this.#F[t];if(r&&h){let a=r-(this.#m.now()-h);n.ttl=a,n.start=Date.now()}}return this.#_&&(n.size=this.#_[t]),n}dump(){let e=[];for(let t of this.#A({allowStale:!0})){let i=this.#i[t],s=this.#t[t],n=this.#e(s)?s.__staleWhileFetching:s;if(n===void 0||i===void 0)continue;let r={value:n};if(this.#d&&this.#F){r.ttl=this.#d[t];let h=this.#m.now()-this.#F[t];r.start=Math.floor(Date.now()-h)}this.#_&&(r.size=this.#_[t]),e.unshift([i,r])}return e}load(e){this.clear();for(let[t,i]of e){if(i.start){let s=Date.now()-i.start;i.start=this.#m.now()-s}this.#W(t,i.value,i)}}set(e,t,i={}){let{status:s=S.hasSubscribers?{}:void 0}=i;i.status=s,s&&(s.op="set",s.key=e,t!==void 0&&(s.value=t),s.cache=this);let n=this.#W(e,t,i);return s&&S.hasSubscribers&&S.publish(s),n}#W(e,t,i,s){let{ttl:n=this.ttl,start:r,noDisposeOnSet:h=this.noDisposeOnSet,sizeCalculation:a=this.sizeCalculation,status:o}=i,d=this.#e(t);if(t===void 0)return o&&(o.set="deleted"),this.delete(e),this;let{noUpdateTTL:y=this.noUpdateTTL}=i;o&&!d&&(o.value=t);let _=this.#N(e,t,i.size||0,a,o);if(this.maxEntrySize&&_>this.maxEntrySize)return this.#E(e,"set"),o&&(o.set="miss",o.maxEntrySizeExceeded=!0),this;let c=this.#n===0?void 0:this.#s.get(e);if(c===void 0)c=this.#n===0?this.#h:this.#y.length!==0?this.#y.pop():this.#n===this.#o?this.#G(!1):this.#n,this.#i[c]=e,this.#t[c]=t,this.#s.set(e,c),this.#l[this.#h]=c,this.#u[c]=this.#h,this.#h=c,this.#n++,this.#j(c,_,o),o&&(o.set="add"),y=!1,this.#x&&!d&&this.#O?.(t,e,"add");else{this.#L(c);let g=this.#t[c];if(t!==g){if(!h)if(this.#e(g)){g!==s&&g.__abortController.abort(new Error("replaced"));let{__staleWhileFetching:f}=g;f!==void 0&&f!==t&&(this.#T&&this.#S?.(f,e,"set"),this.#f&&this.#r?.push([f,e,"set"]))}else this.#T&&this.#S?.(g,e,"set"),this.#f&&this.#r?.push([g,e,"set"]);if(this.#R(c),this.#j(c,_,o),this.#t[c]=t,!d){let f=g&&this.#e(g)?g.__staleWhileFetching:g,b=f===void 0?"add":t!==f?"replace":"update";o&&(o.set=b,f!==void 0&&(o.oldValue=f)),this.#x&&this.onInsert?.(t,e,b)}}else d||(o&&(o.set="update"),this.#x&&this.onInsert?.(t,e,"update"))}if(n!==0&&!this.#d&&this.#k(),this.#d&&(y||this.#H(c,n,r),o&&this.#v(o,c)),!h&&this.#f&&this.#r){let g=this.#r,f;for(;f=g?.shift();)this.#w?.(...f)}return this}pop(){try{for(;this.#n;){let e=this.#t[this.#a];if(this.#G(!0),this.#e(e)){if(e.__staleWhileFetching)return e.__staleWhileFetching}else if(e!==void 0)return e}}finally{if(this.#f&&this.#r){let e=this.#r,t;for(;t=e?.shift();)this.#w?.(...t)}}}#G(e){let t=this.#a,i=this.#i[t],s=this.#t[t],n=this.#e(s);n&&s.__abortController.abort(new Error("evicted"));let r=n?s.__staleWhileFetching:s;return(this.#T||this.#f)&&r!==void 0&&(this.#T&&this.#S?.(r,i,"evict"),this.#f&&this.#r?.push([r,i,"evict"])),this.#R(t),this.#g?.[t]&&(clearTimeout(this.#g[t]),this.#g[t]=void 0),e&&(this.#i[t]=void 0,this.#t[t]=void 0,this.#y.push(t)),this.#n===1?(this.#a=this.#h=0,this.#y.length=0):this.#a=this.#l[t],this.#s.delete(i),this.#n--,t}has(e,t={}){let{status:i=S.hasSubscribers?{}:void 0}=t;t.status=i,i&&(i.op="has",i.key=e,i.cache=this);let s=this.#Y(e,t);return S.hasSubscribers&&S.publish(i),s}#Y(e,t={}){let{updateAgeOnHas:i=this.updateAgeOnHas,status:s}=t,n=this.#s.get(e);if(n!==void 0){let r=this.#t[n];if(this.#e(r)&&r.__staleWhileFetching===void 0)return!1;if(this.#p(n))s&&(s.has="stale",this.#v(s,n));else return i&&this.#D(n),s&&(s.has="hit",this.#v(s,n)),!0}else s&&(s.has="miss");return!1}peek(e,t={}){let{status:i=D()?{}:void 0}=t;i&&(i.op="peek",i.key=e,i.cache=this),t.status=i;let s=this.#J(e,t);return S.hasSubscribers&&S.publish(i),s}#J(e,t){let{status:i,allowStale:s=this.allowStale}=t,n=this.#s.get(e);if(n===void 0||!s&&this.#p(n)){i&&(i.peek=n===void 0?"miss":"stale");return}let r=this.#t[n],h=this.#e(r)?r.__staleWhileFetching:r;return i&&(h!==void 0?(i.peek="hit",i.value=h):i.peek="miss"),h}#P(e,t,i,s){let n=t===void 0?void 0:this.#t[t];if(this.#e(n))return n;let r=new AbortController,{signal:h}=i;h?.addEventListener("abort",()=>r.abort(h.reason),{signal:r.signal});let a={signal:r.signal,options:i,context:s},o=(f,b=!1)=>{let{aborted:l}=r.signal,w=i.ignoreFetchAbort&&f!==void 0,F=i.ignoreFetchAbort||!!(i.allowStaleOnFetchAbort&&f!==void 0);if(i.status&&(l&&!b?(i.status.fetchAborted=!0,i.status.fetchError=r.signal.reason,w&&(i.status.fetchAbortIgnored=!0)):i.status.fetchResolved=!0),l&&!w&&!b)return y(r.signal.reason,F);let m=c,p=this.#t[t];return(p===c||p===void 0&&w&&b)&&(f===void 0?m.__staleWhileFetching!==void 0?this.#t[t]=m.__staleWhileFetching:this.#E(e,"fetch"):(i.status&&(i.status.fetchUpdated=!0),this.#W(e,f,a.options,m))),f},d=f=>(i.status&&(i.status.fetchRejected=!0,i.status.fetchError=f),y(f,!1)),y=(f,b)=>{let{aborted:l}=r.signal,w=l&&i.allowStaleOnFetchAbort,F=w||i.allowStaleOnFetchRejection,m=F||i.noDeleteOnFetchRejection,p=c;if(this.#t[t]===c&&(!m||!b&&p.__staleWhileFetching===void 0?this.#E(e,"fetch"):w||(this.#t[t]=p.__staleWhileFetching)),F)return i.status&&p.__staleWhileFetching!==void 0&&(i.status.returnedStale=!0),p.__staleWhileFetching;if(p.__returned===p)throw f},_=(f,b)=>{let l=this.#M?.(e,n,a);r.signal.addEventListener("abort",()=>{(!i.ignoreFetchAbort||i.allowStaleOnFetchAbort)&&(f(void 0),i.allowStaleOnFetchAbort&&(f=w=>o(w,!0)))}),l&&l instanceof Promise?l.then(w=>f(w===void 0?void 0:w),b):l!==void 0&&f(l)};i.status&&(i.status.fetchDispatched=!0);let c=new Promise(_).then(o,d),g=Object.assign(c,{__abortController:r,__staleWhileFetching:n,__returned:void 0});return t===void 0?(this.#W(e,g,{...a.options,status:void 0}),t=this.#s.get(e)):this.#t[t]=g,g}#e(e){if(!this.#U)return!1;let t=e;return!!t&&t instanceof Promise&&t.hasOwnProperty("__staleWhileFetching")&&t.__abortController instanceof AbortController}fetch(e,t={}){let i=W.hasSubscribers,{status:s=D()?{}:void 0}=t;t.status=s,s&&t.context&&(s.context=t.context);let n=this.#B(e,t);return s&&i&&(s.trace=!0,W.tracePromise(()=>n,s).catch(()=>{})),n}async#B(e,t={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,ttl:r=this.ttl,noDisposeOnSet:h=this.noDisposeOnSet,size:a=0,sizeCalculation:o=this.sizeCalculation,noUpdateTTL:d=this.noUpdateTTL,noDeleteOnFetchRejection:y=this.noDeleteOnFetchRejection,allowStaleOnFetchRejection:_=this.allowStaleOnFetchRejection,ignoreFetchAbort:c=this.ignoreFetchAbort,allowStaleOnFetchAbort:g=this.allowStaleOnFetchAbort,context:f,forceRefresh:b=!1,status:l,signal:w}=t;if(l&&(l.op="fetch",l.key=e,b&&(l.forceRefresh=!0),l.cache=this),!this.#U)return l&&(l.fetch="get"),this.#C(e,{allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,status:l});let F={allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,ttl:r,noDisposeOnSet:h,size:a,sizeCalculation:o,noUpdateTTL:d,noDeleteOnFetchRejection:y,allowStaleOnFetchRejection:_,allowStaleOnFetchAbort:g,ignoreFetchAbort:c,status:l,signal:w},m=this.#s.get(e);if(m===void 0){l&&(l.fetch="miss");let p=this.#P(e,m,F,f);return p.__returned=p}else{let p=this.#t[m];if(this.#e(p)){let v=i&&p.__staleWhileFetching!==void 0;return l&&(l.fetch="inflight",v&&(l.returnedStale=!0)),v?p.__staleWhileFetching:p.__returned=p}let A=this.#p(m);if(!b&&!A)return l&&(l.fetch="hit"),this.#L(m),s&&this.#D(m),l&&this.#v(l,m),p;let z=this.#P(e,m,F,f),E=z.__staleWhileFetching!==void 0&&i;return l&&(l.fetch=A?"stale":"refresh",E&&A&&(l.returnedStale=!0)),E?z.__staleWhileFetching:z.__returned=z}}forceFetch(e,t={}){let i=W.hasSubscribers,{status:s=D()?{}:void 0}=t;t.status=s,s&&t.context&&(s.context=t.context);let n=this.#K(e,t);return s&&i&&(s.trace=!0,W.tracePromise(()=>n,s).catch(()=>{})),n}async#K(e,t={}){let i=await this.#B(e,t);if(i===void 0)throw new Error("fetch() returned undefined");return i}memo(e,t={}){let{status:i=S.hasSubscribers?{}:void 0}=t;t.status=i,i&&(i.op="memo",i.key=e,t.context&&(i.context=t.context),i.cache=this);let s=this.#Q(e,t);return i&&(i.value=s),S.hasSubscribers&&S.publish(i),s}#Q(e,t={}){let i=this.#I;if(!i)throw new Error("no memoMethod provided to constructor");let{context:s,status:n,forceRefresh:r,...h}=t;n&&r&&(n.forceRefresh=!0);let a=this.#C(e,h),o=r||a===void 0;if(n&&(n.memo=o?"miss":"hit",o||(n.value=a)),!o)return a;let d=i(e,a,{options:h,context:s});return n&&(n.value=d),this.#W(e,d,h),d}get(e,t={}){let{status:i=S.hasSubscribers?{}:void 0}=t;t.status=i,i&&(i.op="get",i.key=e,i.cache=this);let s=this.#C(e,t);return i&&(s!==void 0&&(i.value=s),S.hasSubscribers&&S.publish(i)),s}#C(e,t={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,status:r}=t,h=this.#s.get(e);if(h===void 0){r&&(r.get="miss");return}let a=this.#t[h],o=this.#e(a);return r&&this.#v(r,h),this.#p(h)?o?(r&&(r.get="stale-fetching"),i&&a.__staleWhileFetching!==void 0?(r&&(r.returnedStale=!0),a.__staleWhileFetching):void 0):(n||this.#E(e,"expire"),r&&(r.get="stale"),i?(r&&(r.returnedStale=!0),a):void 0):(r&&(r.get=o?"fetching":"hit"),this.#L(h),s&&this.#D(h),o?a.__staleWhileFetching:a)}#$(e,t){this.#u[t]=e,this.#l[e]=t}#L(e){e!==this.#h&&(e===this.#a?this.#a=this.#l[e]:this.#$(this.#u[e],this.#l[e]),this.#$(this.#h,e),this.#h=e)}delete(e){return this.#E(e,"delete")}#E(e,t){S.hasSubscribers&&S.publish({op:"delete",delete:t,key:e,cache:this});let i=!1;if(this.#n!==0){let s=this.#s.get(e);if(s!==void 0)if(this.#g?.[s]&&(clearTimeout(this.#g?.[s]),this.#g[s]=void 0),i=!0,this.#n===1)this.#q(t);else{this.#R(s);let n=this.#t[s];if(this.#e(n)?n.__abortController.abort(new Error("deleted")):(this.#T||this.#f)&&(this.#T&&this.#S?.(n,e,t),this.#f&&this.#r?.push([n,e,t])),this.#s.delete(e),this.#i[s]=void 0,this.#t[s]=void 0,s===this.#h)this.#h=this.#u[s];else if(s===this.#a)this.#a=this.#l[s];else{let r=this.#u[s];this.#l[r]=this.#l[s];let h=this.#l[s];this.#u[h]=this.#u[s]}this.#n--,this.#y.push(s)}}if(this.#f&&this.#r?.length){let s=this.#r,n;for(;n=s?.shift();)this.#w?.(...n)}return i}clear(){return this.#q("delete")}#q(e){for(let t of this.#z({allowStale:!0})){let i=this.#t[t];if(this.#e(i))i.__abortController.abort(new Error("deleted"));else{let s=this.#i[t];this.#T&&this.#S?.(i,s,e),this.#f&&this.#r?.push([i,s,e])}}if(this.#s.clear(),this.#t.fill(void 0),this.#i.fill(void 0),this.#d&&this.#F){this.#d.fill(0),this.#F.fill(0);for(let t of this.#g??[])t!==void 0&&clearTimeout(t);this.#g?.fill(void 0)}if(this.#_&&this.#_.fill(0),this.#a=0,this.#h=0,this.#y.length=0,this.#b=0,this.#n=0,this.#f&&this.#r){let t=this.#r,i;for(;i=t?.shift();)this.#w?.(...i)}}};export{I as LRUCache};
+import{tracingChannel as G,channel as P}from"node:diagnostics_channel";var S=P("lru-cache:metrics"),W=G("lru-cache");var L=typeof performance=="object"&&performance&&typeof performance.now=="function"?performance:Date;var R=()=>S.hasSubscribers||W.hasSubscribers,U=new Set,M=typeof process=="object"&&process?process:{},k=(d,e,t,i)=>{typeof M.emitWarning=="function"?M.emitWarning(d,e,t,i):console.error(`[${t}] ${e}: ${d}`)},H=d=>!U.has(d);var T=d=>!!d&&d===Math.floor(d)&&d>0&&isFinite(d),j=d=>T(d)?d<=Math.pow(2,8)?Uint8Array:d<=Math.pow(2,16)?Uint16Array:d<=Math.pow(2,32)?Uint32Array:d<=Number.MAX_SAFE_INTEGER?O:null:null,O=class extends Array{constructor(e){super(e),this.fill(0)}},x=class d{heap;length;static#o=!1;static create(e){let t=j(e);if(!t)return[];d.#o=!0;let i=new d(e,t);return d.#o=!1,i}constructor(e,t){if(!d.#o)throw new TypeError("instantiate Stack using Stack.create(n)");this.heap=new t(e),this.length=0}push(e){this.heap[this.length++]=e}pop(){return this.heap[--this.length]}},I=class d{#o;#c;#S;#O;#w;#M;#I;#m;get perf(){return this.#m}ttl;ttlResolution;ttlAutopurge;updateAgeOnGet;updateAgeOnHas;allowStale;noDisposeOnSet;noUpdateTTL;maxEntrySize;sizeCalculation;noDeleteOnFetchRejection;noDeleteOnStaleGet;allowStaleOnFetchAbort;allowStaleOnFetchRejection;ignoreFetchAbort;backgroundFetchSize;#n;#b;#s;#i;#t;#l;#u;#a;#h;#y;#r;#_;#F;#d;#g;#T;#U;#f;#D;static unsafeExposeInternals(e){return{starts:e.#F,ttls:e.#d,autopurgeTimers:e.#g,sizes:e.#_,keyMap:e.#s,keyList:e.#i,valList:e.#t,next:e.#l,prev:e.#u,get head(){return e.#a},get tail(){return e.#h},free:e.#y,isBackgroundFetch:t=>e.#e(t),backgroundFetch:(t,i,s,n)=>e.#P(t,i,s,n),moveToTail:t=>e.#L(t),indexes:t=>e.#A(t),rindexes:t=>e.#z(t),isStale:t=>e.#p(t)}}get max(){return this.#o}get maxSize(){return this.#c}get calculatedSize(){return this.#b}get size(){return this.#n}get fetchMethod(){return this.#M}get memoMethod(){return this.#I}get dispose(){return this.#S}get onInsert(){return this.#O}get disposeAfter(){return this.#w}constructor(e){let{max:t=0,ttl:i,ttlResolution:s=1,ttlAutopurge:n,updateAgeOnGet:o,updateAgeOnHas:l,allowStale:h,dispose:r,onInsert:c,disposeAfter:m,noDisposeOnSet:_,noUpdateTTL:u,maxSize:g=0,maxEntrySize:f=0,sizeCalculation:y,fetchMethod:a,memoMethod:w,noDeleteOnFetchRejection:F,noDeleteOnStaleGet:b,allowStaleOnFetchRejection:p,allowStaleOnFetchAbort:A,ignoreFetchAbort:z,backgroundFetchSize:C=1,perf:E}=e;if(this.backgroundFetchSize=C,E!==void 0&&typeof E?.now!="function")throw new TypeError("perf option must have a now() method if specified");if(this.#m=E??L,t!==0&&!T(t))throw new TypeError("max option must be a nonnegative integer");let v=t?j(t):Array;if(!v)throw new Error("invalid max value: "+t);if(this.#o=t,this.#c=g,this.maxEntrySize=f||this.#c,this.sizeCalculation=y,this.sizeCalculation){if(!this.#c&&!this.maxEntrySize)throw new TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");if(typeof this.sizeCalculation!="function")throw new TypeError("sizeCalculation set to non-function")}if(w!==void 0&&typeof w!="function")throw new TypeError("memoMethod must be a function if defined");if(this.#I=w,a!==void 0&&typeof a!="function")throw new TypeError("fetchMethod must be a function if specified");if(this.#M=a,this.#U=!!a,this.#s=new Map,this.#i=Array.from({length:t}).fill(void 0),this.#t=Array.from({length:t}).fill(void 0),this.#l=new v(t),this.#u=new v(t),this.#a=0,this.#h=0,this.#y=x.create(t),this.#n=0,this.#b=0,typeof r=="function"&&(this.#S=r),typeof c=="function"&&(this.#O=c),typeof m=="function"?(this.#w=m,this.#r=[]):(this.#w=void 0,this.#r=void 0),this.#T=!!this.#S,this.#D=!!this.#O,this.#f=!!this.#w,this.noDisposeOnSet=!!_,this.noUpdateTTL=!!u,this.noDeleteOnFetchRejection=!!F,this.allowStaleOnFetchRejection=!!p,this.allowStaleOnFetchAbort=!!A,this.ignoreFetchAbort=!!z,this.maxEntrySize!==0){if(this.#c!==0&&!T(this.#c))throw new TypeError("maxSize must be a positive integer if specified");if(!T(this.maxEntrySize))throw new TypeError("maxEntrySize must be a positive integer if specified");this.#X()}if(this.allowStale=!!h,this.noDeleteOnStaleGet=!!b,this.updateAgeOnGet=!!o,this.updateAgeOnHas=!!l,this.ttlResolution=T(s)||s===0?s:1,this.ttlAutopurge=!!n,this.ttl=i||0,this.ttl){if(!T(this.ttl))throw new TypeError("ttl must be a positive integer if specified");this.#k()}if(this.#o===0&&this.ttl===0&&this.#c===0)throw new TypeError("At least one of max, maxSize, or ttl is required");if(!this.ttlAutopurge&&!this.#o&&!this.#c){let D="LRU_CACHE_UNBOUNDED";H(D)&&(U.add(D),k("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.","UnboundedCacheWarning",D,d))}}getRemainingTTL(e){return this.#s.has(e)?1/0:0}#k(){let e=new O(this.#o),t=new O(this.#o);this.#d=e,this.#F=t;let i=this.ttlAutopurge?Array.from({length:this.#o}):void 0;this.#g=i,this.#H=(h,r,c=this.#m.now())=>{t[h]=r!==0?c:0,e[h]=r,s(h,r)},this.#R=h=>{t[h]=e[h]!==0?this.#m.now():0,s(h,e[h])};let s=this.ttlAutopurge?(h,r)=>{if(i?.[h]&&(clearTimeout(i[h]),i[h]=void 0),r&&r!==0&&i){let c=setTimeout(()=>{this.#p(h)?(this.#E(this.#i[h],"expire"),i[h]=void 0):s(h,l(h))},r+1);c.unref&&c.unref(),i[h]=c}}:()=>{};this.#v=(h,r)=>{if(e[r]){let c=e[r],m=t[r];if(!c||!m)return;h.ttl=c,h.start=m,h.now=n||o();let _=h.now-m;h.remainingTTL=c-_}};let n=0,o=()=>{let h=this.#m.now();if(this.ttlResolution>0){n=h;let r=setTimeout(()=>n=0,this.ttlResolution);r.unref&&r.unref()}return h};this.getRemainingTTL=h=>{let r=this.#s.get(h);return r===void 0?0:l(r)};let l=h=>{let r=e[h],c=t[h];if(!r||!c)return 1/0;let m=(n||o())-c;return r-m};this.#p=h=>{let r=t[h],c=e[h];return!!c&&!!r&&(n||o())-r>c}}#R=()=>{};#v=()=>{};#H=()=>{};#p=()=>!1;#X(){let e=new O(this.#o);this.#b=0,this.#_=e,this.#x=t=>{this.#b-=e[t],e[t]=0},this.#N=(t,i,s,n)=>{if(!T(s)){if(this.#e(i))return this.backgroundFetchSize;if(n){if(typeof n!="function")throw new TypeError("sizeCalculation must be a function");if(s=n(i,t),!T(s))throw new TypeError("sizeCalculation return invalid (expect positive integer)")}else throw new TypeError("invalid size value (must be positive integer). When maxSize or maxEntrySize is used, sizeCalculation or size must be set.")}return s},this.#j=(t,i,s)=>{if(e[t]=i,this.#c){let n=this.#c-e[t];for(;this.#b>n;)this.#G(!0)}this.#b+=e[t],s&&(s.entrySize=i,s.totalCalculatedSize=this.#b)}}#x=e=>{};#j=(e,t,i)=>{};#N=(e,t,i,s)=>{if(i||s)throw new TypeError("cannot set size without setting maxSize or maxEntrySize on cache");return 0};*#A({allowStale:e=this.allowStale}={}){if(this.#n)for(let t=this.#h;this.#V(t)&&((e||!this.#p(t))&&(yield t),t!==this.#a);)t=this.#u[t]}*#z({allowStale:e=this.allowStale}={}){if(this.#n)for(let t=this.#a;this.#V(t)&&((e||!this.#p(t))&&(yield t),t!==this.#h);)t=this.#l[t]}#V(e){return e!==void 0&&this.#s.get(this.#i[e])===e}*entries(){for(let e of this.#A())this.#t[e]!==void 0&&this.#i[e]!==void 0&&!this.#e(this.#t[e])&&(yield[this.#i[e],this.#t[e]])}*rentries(){for(let e of this.#z())this.#t[e]!==void 0&&this.#i[e]!==void 0&&!this.#e(this.#t[e])&&(yield[this.#i[e],this.#t[e]])}*keys(){for(let e of this.#A()){let t=this.#i[e];t!==void 0&&!this.#e(this.#t[e])&&(yield t)}}*rkeys(){for(let e of this.#z()){let t=this.#i[e];t!==void 0&&!this.#e(this.#t[e])&&(yield t)}}*values(){for(let e of this.#A())this.#t[e]!==void 0&&!this.#e(this.#t[e])&&(yield this.#t[e])}*rvalues(){for(let e of this.#z())this.#t[e]!==void 0&&!this.#e(this.#t[e])&&(yield this.#t[e])}[Symbol.iterator](){return this.entries()}[Symbol.toStringTag]="LRUCache";find(e,t={}){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;if(n!==void 0&&e(n,this.#i[i],this))return this.#C(this.#i[i],t)}}forEach(e,t=this){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&e.call(t,n,this.#i[i],this)}}rforEach(e,t=this){for(let i of this.#z()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&e.call(t,n,this.#i[i],this)}}purgeStale(){let e=!1;for(let t of this.#z({allowStale:!0}))this.#p(t)&&(this.#E(this.#i[t],"expire"),e=!0);return e}info(e){let t=this.#s.get(e);if(t===void 0)return;let i=this.#t[t],s=this.#e(i)?i.__staleWhileFetching:i;if(s===void 0)return;let n={value:s};if(this.#d&&this.#F){let o=this.#d[t],l=this.#F[t];if(o&&l){let h=o-(this.#m.now()-l);n.ttl=h,n.start=Date.now()}}return this.#_&&(n.size=this.#_[t]),n}dump(){let e=[];for(let t of this.#A({allowStale:!0})){let i=this.#i[t],s=this.#t[t],n=this.#e(s)?s.__staleWhileFetching:s;if(n===void 0||i===void 0)continue;let o={value:n};if(this.#d&&this.#F){o.ttl=this.#d[t];let l=this.#m.now()-this.#F[t];o.start=Math.floor(Date.now()-l)}this.#_&&(o.size=this.#_[t]),e.unshift([i,o])}return e}load(e){this.clear();for(let[t,i]of e){if(i.start){let s=Date.now()-i.start;i.start=this.#m.now()-s}this.#W(t,i.value,i)}}set(e,t,i={}){let{status:s=S.hasSubscribers?{}:void 0}=i;i.status=s,s&&(s.op="set",s.key=e,t!==void 0&&(s.value=t),s.cache=this);let n=this.#W(e,t,i);return s&&S.hasSubscribers&&S.publish(s),n}#W(e,t,i,s){let{ttl:n=this.ttl,start:o,noDisposeOnSet:l=this.noDisposeOnSet,sizeCalculation:h=this.sizeCalculation,status:r}=i,c=this.#e(t);if(t===void 0)return r&&(r.set="deleted"),this.delete(e),this;let{noUpdateTTL:m=this.noUpdateTTL}=i;r&&!c&&(r.value=t);let _=this.#N(e,t,i.size||0,h,r);if(this.maxEntrySize&&_>this.maxEntrySize)return this.#E(e,"set"),r&&(r.set="miss",r.maxEntrySizeExceeded=!0),this;let u=this.#n===0?void 0:this.#s.get(e);if(u===void 0)u=this.#n===0?this.#h:this.#y.length!==0?this.#y.pop():this.#n===this.#o?this.#G(!1):this.#n,this.#i[u]=e,this.#t[u]=t,this.#s.set(e,u),this.#l[this.#h]=u,this.#u[u]=this.#h,this.#h=u,this.#n++,this.#j(u,_,r),r&&(r.set="add"),m=!1,this.#D&&!c&&this.#O?.(t,e,"add");else{this.#L(u);let g=this.#t[u];if(t!==g){if(!l)if(this.#e(g)){g!==s&&g.__abortController.abort(new Error("replaced"));let{__staleWhileFetching:f}=g;f!==void 0&&f!==t&&(this.#T&&this.#S?.(f,e,"set"),this.#f&&this.#r?.push([f,e,"set"]))}else this.#T&&this.#S?.(g,e,"set"),this.#f&&this.#r?.push([g,e,"set"]);if(this.#x(u),this.#j(u,_,r),this.#t[u]=t,!c){let f=g&&this.#e(g)?g.__staleWhileFetching:g,y=f===void 0?"add":t!==f?"replace":"update";r&&(r.set=y,f!==void 0&&(r.oldValue=f)),this.#D&&this.onInsert?.(t,e,y)}}else c||(r&&(r.set="update"),this.#D&&this.onInsert?.(t,e,"update"))}if(n!==0&&!this.#d&&this.#k(),this.#d&&(m||this.#H(u,n,o),r&&this.#v(r,u)),!l&&this.#f&&this.#r){let g=this.#r,f;for(;f=g?.shift();)this.#w?.(...f)}return this}pop(){try{for(;this.#n;){let e=this.#t[this.#a];if(this.#G(!0),this.#e(e)){if(e.__staleWhileFetching)return e.__staleWhileFetching}else if(e!==void 0)return e}}finally{if(this.#f&&this.#r){let e=this.#r,t;for(;t=e?.shift();)this.#w?.(...t)}}}#G(e){let t=this.#a,i=this.#i[t],s=this.#t[t],n=this.#e(s);n&&s.__abortController.abort(new Error("evicted"));let o=n?s.__staleWhileFetching:s;return(this.#T||this.#f)&&o!==void 0&&(this.#T&&this.#S?.(o,i,"evict"),this.#f&&this.#r?.push([o,i,"evict"])),this.#x(t),this.#g?.[t]&&(clearTimeout(this.#g[t]),this.#g[t]=void 0),e&&(this.#i[t]=void 0,this.#t[t]=void 0,this.#y.push(t)),this.#n===1?(this.#a=this.#h=0,this.#y.length=0):this.#a=this.#l[t],this.#s.delete(i),this.#n--,t}has(e,t={}){let{status:i=S.hasSubscribers?{}:void 0}=t;t.status=i,i&&(i.op="has",i.key=e,i.cache=this);let s=this.#Y(e,t);return S.hasSubscribers&&S.publish(i),s}#Y(e,t={}){let{updateAgeOnHas:i=this.updateAgeOnHas,status:s}=t,n=this.#s.get(e);if(n!==void 0){let o=this.#t[n];if(this.#e(o)&&o.__staleWhileFetching===void 0)return!1;if(this.#p(n))s&&(s.has="stale",this.#v(s,n));else return i&&this.#R(n),s&&(s.has="hit",this.#v(s,n)),!0}else s&&(s.has="miss");return!1}peek(e,t={}){let{status:i=R()?{}:void 0}=t;i&&(i.op="peek",i.key=e,i.cache=this),t.status=i;let s=this.#J(e,t);return S.hasSubscribers&&S.publish(i),s}#J(e,t){let{status:i,allowStale:s=this.allowStale}=t,n=this.#s.get(e);if(n===void 0||!s&&this.#p(n)){i&&(i.peek=n===void 0?"miss":"stale");return}let o=this.#t[n],l=this.#e(o)?o.__staleWhileFetching:o;return i&&(l!==void 0?(i.peek="hit",i.value=l):i.peek="miss"),l}#P(e,t,i,s){let n=t===void 0?void 0:this.#t[t];if(this.#e(n))return n;let o=new AbortController,{signal:l}=i;l?.addEventListener("abort",()=>o.abort(l.reason),{signal:o.signal});let h={signal:o.signal,options:i,context:s},r=(f,y=!1)=>{let{aborted:a}=o.signal,w=i.ignoreFetchAbort&&f!==void 0,F=i.ignoreFetchAbort||!!(i.allowStaleOnFetchAbort&&f!==void 0);if(i.status&&(a&&!y?(i.status.fetchAborted=!0,i.status.fetchError=o.signal.reason,w&&(i.status.fetchAbortIgnored=!0)):i.status.fetchResolved=!0),a&&!w&&!y)return m(o.signal.reason,F);let b=u,p=this.#t[t];return(p===u||p===void 0&&w&&y)&&(f===void 0?b.__staleWhileFetching!==void 0?this.#t[t]=b.__staleWhileFetching:this.#E(e,"fetch"):(i.status&&(i.status.fetchUpdated=!0),this.#W(e,f,h.options,b))),f},c=f=>(i.status&&(i.status.fetchRejected=!0,i.status.fetchError=f),m(f,!1)),m=(f,y)=>{let{aborted:a}=o.signal,w=a&&i.allowStaleOnFetchAbort,F=w||i.allowStaleOnFetchRejection,b=F||i.noDeleteOnFetchRejection,p=u;if(this.#t[t]===u&&(!b||!y&&p.__staleWhileFetching===void 0?this.#E(e,"fetch"):w||(this.#t[t]=p.__staleWhileFetching)),F)return i.status&&p.__staleWhileFetching!==void 0&&(i.status.returnedStale=!0),p.__staleWhileFetching;if(p.__returned===p)throw f},_=(f,y)=>{let a=this.#M?.(e,n,h);o.signal.addEventListener("abort",()=>{(!i.ignoreFetchAbort||i.allowStaleOnFetchAbort)&&(f(void 0),i.allowStaleOnFetchAbort&&(f=w=>r(w,!0)))}),a&&a instanceof Promise?a.then(w=>f(w===void 0?void 0:w),y):a!==void 0&&f(a)};i.status&&(i.status.fetchDispatched=!0);let u=new Promise(_).then(r,c),g=Object.assign(u,{__abortController:o,__staleWhileFetching:n,__returned:void 0});return t===void 0?(this.#W(e,g,{...h.options,status:void 0}),t=this.#s.get(e)):this.#t[t]=g,g}#e(e){if(!this.#U)return!1;let t=e;return!!t&&t instanceof Promise&&t.hasOwnProperty("__staleWhileFetching")&&t.__abortController instanceof AbortController}fetch(e,t={}){let i=W.hasSubscribers,{status:s=R()?{}:void 0}=t;t.status=s,s&&t.context&&(s.context=t.context);let n=this.#B(e,t);return s&&i&&(s.trace=!0,W.tracePromise(()=>n,s).catch(()=>{})),n}async#B(e,t={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,ttl:o=this.ttl,noDisposeOnSet:l=this.noDisposeOnSet,size:h=0,sizeCalculation:r=this.sizeCalculation,noUpdateTTL:c=this.noUpdateTTL,noDeleteOnFetchRejection:m=this.noDeleteOnFetchRejection,allowStaleOnFetchRejection:_=this.allowStaleOnFetchRejection,ignoreFetchAbort:u=this.ignoreFetchAbort,allowStaleOnFetchAbort:g=this.allowStaleOnFetchAbort,context:f,forceRefresh:y=!1,status:a,signal:w}=t;if(a&&(a.op="fetch",a.key=e,y&&(a.forceRefresh=!0),a.cache=this),!this.#U)return a&&(a.fetch="get"),this.#C(e,{allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,status:a});let F={allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,ttl:o,noDisposeOnSet:l,size:h,sizeCalculation:r,noUpdateTTL:c,noDeleteOnFetchRejection:m,allowStaleOnFetchRejection:_,allowStaleOnFetchAbort:g,ignoreFetchAbort:u,status:a,signal:w},b=this.#s.get(e);if(b===void 0){a&&(a.fetch="miss");let p=this.#P(e,b,F,f);return p.__returned=p}else{let p=this.#t[b];if(this.#e(p)){let v=i&&p.__staleWhileFetching!==void 0;return a&&(a.fetch="inflight",v&&(a.returnedStale=!0)),v?p.__staleWhileFetching:p.__returned=p}let A=this.#p(b);if(!y&&!A)return a&&(a.fetch="hit"),this.#L(b),s&&this.#R(b),a&&this.#v(a,b),p;let z=this.#P(e,b,F,f),E=z.__staleWhileFetching!==void 0&&i;return a&&(a.fetch=A?"stale":"refresh",E&&A&&(a.returnedStale=!0)),E?z.__staleWhileFetching:z.__returned=z}}forceFetch(e,t={}){let i=W.hasSubscribers,{status:s=R()?{}:void 0}=t;t.status=s,s&&t.context&&(s.context=t.context);let n=this.#K(e,t);return s&&i&&(s.trace=!0,W.tracePromise(()=>n,s).catch(()=>{})),n}async#K(e,t={}){let i=await this.#B(e,t);if(i===void 0)throw new Error("fetch() returned undefined");return i}memo(e,t={}){let{status:i=S.hasSubscribers?{}:void 0}=t;t.status=i,i&&(i.op="memo",i.key=e,t.context&&(i.context=t.context),i.cache=this);let s=this.#Q(e,t);return i&&(i.value=s),S.hasSubscribers&&S.publish(i),s}#Q(e,t={}){let i=this.#I;if(!i)throw new Error("no memoMethod provided to constructor");let{context:s,status:n,forceRefresh:o,...l}=t;n&&o&&(n.forceRefresh=!0);let h=this.#C(e,l),r=o||h===void 0;if(n&&(n.memo=r?"miss":"hit",r||(n.value=h)),!r)return h;let c=i(e,h,{options:l,context:s});return n&&(n.value=c),this.#W(e,c,l),c}get(e,t={}){let{status:i=S.hasSubscribers?{}:void 0}=t;t.status=i,i&&(i.op="get",i.key=e,i.cache=this);let s=this.#C(e,t);return i&&(s!==void 0&&(i.value=s),S.hasSubscribers&&S.publish(i)),s}#C(e,t={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,status:o}=t,l=this.#s.get(e);if(l===void 0){o&&(o.get="miss");return}let h=this.#t[l],r=this.#e(h);return o&&this.#v(o,l),this.#p(l)?r?(o&&(o.get="stale-fetching"),i&&h.__staleWhileFetching!==void 0?(o&&(o.returnedStale=!0),h.__staleWhileFetching):void 0):(n||this.#E(e,"expire"),o&&(o.get="stale"),i?(o&&(o.returnedStale=!0),h):void 0):(o&&(o.get=r?"fetching":"hit"),this.#L(l),s&&this.#R(l),r?h.__staleWhileFetching:h)}#$(e,t){this.#u[t]=e,this.#l[e]=t}#L(e){e!==this.#h&&(e===this.#a?this.#a=this.#l[e]:this.#$(this.#u[e],this.#l[e]),this.#$(this.#h,e),this.#h=e)}delete(e){return this.#E(e,"delete")}#E(e,t){S.hasSubscribers&&S.publish({op:"delete",delete:t,key:e,cache:this});let i=!1;if(this.#n!==0){let s=this.#s.get(e);if(s!==void 0)if(this.#g?.[s]&&(clearTimeout(this.#g[s]),this.#g[s]=void 0),i=!0,this.#n===1)this.#q(t);else{this.#x(s);let n=this.#t[s];if(this.#e(n)?n.__abortController.abort(new Error("deleted")):(this.#T||this.#f)&&(this.#T&&this.#S?.(n,e,t),this.#f&&this.#r?.push([n,e,t])),this.#s.delete(e),this.#i[s]=void 0,this.#t[s]=void 0,s===this.#h)this.#h=this.#u[s];else if(s===this.#a)this.#a=this.#l[s];else{let o=this.#u[s];this.#l[o]=this.#l[s];let l=this.#l[s];this.#u[l]=this.#u[s]}this.#n--,this.#y.push(s)}}if(this.#f&&this.#r?.length){let s=this.#r,n;for(;n=s?.shift();)this.#w?.(...n)}return i}clear(){return this.#q("delete")}#q(e){for(let t of this.#z({allowStale:!0})){let i=this.#t[t];if(this.#e(i))i.__abortController.abort(new Error("deleted"));else{let s=this.#i[t];this.#T&&this.#S?.(i,s,e),this.#f&&this.#r?.push([i,s,e])}}if(this.#s.clear(),this.#t.fill(void 0),this.#i.fill(void 0),this.#d&&this.#F){this.#d.fill(0),this.#F.fill(0);for(let t of this.#g??[])t!==void 0&&clearTimeout(t);this.#g?.fill(void 0)}if(this.#_&&this.#_.fill(0),this.#a=0,this.#h=0,this.#y.length=0,this.#b=0,this.#n=0,this.#f&&this.#r){let t=this.#r,i;for(;i=t?.shift();)this.#w?.(...i)}}};export{I as LRUCache};
//# sourceMappingURL=index.min.js.map
diff --git a/deps/npm/node_modules/lru-cache/package.json b/deps/npm/node_modules/lru-cache/package.json
index 6ada2c211f2..01dad2afbb3 100644
--- a/deps/npm/node_modules/lru-cache/package.json
+++ b/deps/npm/node_modules/lru-cache/package.json
@@ -1,7 +1,7 @@
{
"name": "lru-cache",
"description": "A cache object that deletes the least-recently-used items.",
- "version": "11.5.1",
+ "version": "11.5.2",
"author": "Isaac Z. Schlueter <i@izs.me>",
"keywords": [
"mru",
diff --git a/deps/npm/node_modules/make-fetch-happen/package.json b/deps/npm/node_modules/make-fetch-happen/package.json
index 92c48b45871..2bca3e4af11 100644
--- a/deps/npm/node_modules/make-fetch-happen/package.json
+++ b/deps/npm/node_modules/make-fetch-happen/package.json
@@ -1,6 +1,6 @@
{
"name": "make-fetch-happen",
- "version": "15.0.6",
+ "version": "16.0.1",
"description": "Opinionated, caching, retrying fetch client",
"main": "lib/index.js",
"files": [
@@ -34,28 +34,28 @@
"license": "ISC",
"dependencies": {
"@gar/promise-retry": "^1.0.0",
- "@npmcli/agent": "^4.0.0",
- "@npmcli/redact": "^4.0.0",
- "cacache": "^20.0.1",
+ "@npmcli/agent": "^5.0.0",
+ "@npmcli/redact": "^5.0.0",
+ "cacache": "^21.0.0",
"http-cache-semantics": "^4.1.1",
"minipass": "^7.0.2",
- "minipass-fetch": "^5.0.0",
+ "minipass-fetch": "^6.0.0",
"minipass-flush": "^1.0.5",
"minipass-pipeline": "^1.2.4",
"negotiator": "^1.0.0",
- "proc-log": "^6.0.0",
- "ssri": "^13.0.0"
+ "proc-log": "^7.0.0",
+ "ssri": "^14.0.0"
},
"devDependencies": {
- "@npmcli/eslint-config": "^5.0.0",
- "@npmcli/template-oss": "4.25.0",
+ "@npmcli/eslint-config": "^7.0.0",
+ "@npmcli/template-oss": "5.1.0",
"nock": "^13.2.4",
"safe-buffer": "^5.2.1",
"standard-version": "^9.3.2",
"tap": "^16.0.0"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"tap": {
"color": 1,
@@ -69,7 +69,7 @@
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.25.0",
+ "version": "5.1.0",
"publish": "true"
}
}
diff --git a/deps/npm/node_modules/minipass-fetch/package.json b/deps/npm/node_modules/minipass-fetch/package.json
index a180d8d234e..9b64fa5be8b 100644
--- a/deps/npm/node_modules/minipass-fetch/package.json
+++ b/deps/npm/node_modules/minipass-fetch/package.json
@@ -1,6 +1,6 @@
{
"name": "minipass-fetch",
- "version": "5.0.2",
+ "version": "6.0.0",
"description": "An implementation of window.fetch in Node.js using Minipass streams",
"license": "MIT",
"main": "lib/index.js",
@@ -25,7 +25,7 @@
},
"devDependencies": {
"@npmcli/eslint-config": "^5.0.0",
- "@npmcli/template-oss": "4.27.1",
+ "@npmcli/template-oss": "5.0.0",
"@ungap/url-search-params": "^0.2.2",
"abort-controller": "^3.0.0",
"abortcontroller-polyfill": "~1.7.3",
@@ -59,12 +59,12 @@
"lib/"
],
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"author": "GitHub Inc.",
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.27.1",
+ "version": "5.0.0",
"publish": "true"
}
}
diff --git a/deps/npm/node_modules/mute-stream/package.json b/deps/npm/node_modules/mute-stream/package.json
index 25e0af473d2..c3bf320c9c6 100644
--- a/deps/npm/node_modules/mute-stream/package.json
+++ b/deps/npm/node_modules/mute-stream/package.json
@@ -1,21 +1,22 @@
{
"name": "mute-stream",
- "version": "3.0.0",
+ "version": "4.0.0",
"main": "lib/index.js",
"devDependencies": {
- "@npmcli/eslint-config": "^5.0.0",
- "@npmcli/template-oss": "4.27.1",
- "tap": "^16.3.0"
+ "@npmcli/eslint-config": "^6.0.0",
+ "@npmcli/template-oss": "5.0.0"
},
"scripts": {
- "test": "tap",
+ "test": "node --test './test/**/*.js'",
"lint": "npm run eslint",
"postlint": "template-oss-check",
"template-oss-apply": "template-oss-apply --force",
"lintfix": "npm run eslint -- --fix",
- "snap": "tap",
+ "snap": "node --test --test-update-snapshots './test/**/*.js'",
"posttest": "npm run lint",
- "eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\""
+ "eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"",
+ "test:node20": "node --test test",
+ "test:cover": "node --test --experimental-test-coverage --test-timeout=3000 --test-coverage-lines=100 --test-coverage-functions=100 --test-coverage-branches=100 './test/**/*.js'"
},
"repository": {
"type": "git",
@@ -33,22 +34,14 @@
"bin/",
"lib/"
],
- "tap": {
- "statements": 70,
- "branches": 60,
- "functions": 81,
- "lines": 70,
- "nyc-arg": [
- "--exclude",
- "tap-snapshots/**"
- ]
- },
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.27.1",
- "publish": true
+ "version": "5.0.0",
+ "publish": true,
+ "testRunner": "node:test",
+ "latestCiVersion": 24
}
}
diff --git a/deps/npm/node_modules/node-gyp/.release-please-manifest.json b/deps/npm/node_modules/node-gyp/.release-please-manifest.json
index 7cf5faf7112..139a1591331 100644
--- a/deps/npm/node_modules/node-gyp/.release-please-manifest.json
+++ b/deps/npm/node_modules/node-gyp/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "12.4.0"
+ ".": "13.0.0"
}
diff --git a/deps/npm/node_modules/node-gyp/CHANGELOG.md b/deps/npm/node_modules/node-gyp/CHANGELOG.md
index 83881ed2a39..211b04ef357 100644
--- a/deps/npm/node_modules/node-gyp/CHANGELOG.md
+++ b/deps/npm/node_modules/node-gyp/CHANGELOG.md
@@ -1,5 +1,36 @@
# Changelog
+## [13.0.0](https://github.com/nodejs/node-gyp/compare/v12.4.0...v13.0.0) (2026-06-10)
+
+
+### ⚠ BREAKING CHANGES
+
+* `node-gyp` now supports node `^22.22.2 || ^24.15.0 || >=26.0.0`
+
+### Features
+
+* bump to new node engine range ([b792b8e](https://github.com/nodejs/node-gyp/commit/b792b8e321e6e56d46c32f4b9adb15e4085c3797))
+
+
+### Bug Fixes
+
+* **ci:** update ruff-action version to v4.0.0 ([#3324](https://github.com/nodejs/node-gyp/issues/3324)) ([f089669](https://github.com/nodejs/node-gyp/commit/f089669a4c95a3c8b7f435556b226fa66dcd94b7))
+* disable LTO for addon builds on Windows ([#3331](https://github.com/nodejs/node-gyp/issues/3331)) ([d30bb6e](https://github.com/nodejs/node-gyp/commit/d30bb6e6fdaf46374de9b9bfe1bf54f49337b052))
+
+
+### Core
+
+* **deps:** bump actions/github-script from 8 to 9 ([#3297](https://github.com/nodejs/node-gyp/issues/3297)) ([f6a5e45](https://github.com/nodejs/node-gyp/commit/f6a5e458e819f05ddfbba5cbd5589a7a1c80128e))
+* **deps:** bump googleapis/release-please-action from 4 to 5 ([#3307](https://github.com/nodejs/node-gyp/issues/3307)) ([b2cde80](https://github.com/nodejs/node-gyp/commit/b2cde802487f3b9efd726a1a1cb43650731f9958))
+* nopt@10.0.0 ([327424a](https://github.com/nodejs/node-gyp/commit/327424ad630dd7007771b19f7b77691b2156a556))
+* proc-log@7.0.0 ([f6c296b](https://github.com/nodejs/node-gyp/commit/f6c296b2952e23b7e690b7148c9dc32b25a26ee2))
+* which@7.0.0 ([11a8b10](https://github.com/nodejs/node-gyp/commit/11a8b109f805f13129302508c219607167a8e9ea))
+
+
+### Miscellaneous
+
+* add commit-lint ([#3325](https://github.com/nodejs/node-gyp/issues/3325)) ([6fb6c11](https://github.com/nodejs/node-gyp/commit/6fb6c11eae1258eddd478956a20f0cb154dd4553))
+
## [12.4.0](https://github.com/nodejs/node-gyp/compare/v12.3.0...v12.4.0) (2026-05-15)
diff --git a/deps/npm/node_modules/node-gyp/commitlint.config.mjs b/deps/npm/node_modules/node-gyp/commitlint.config.mjs
new file mode 100644
index 00000000000..2291173ef3b
--- /dev/null
+++ b/deps/npm/node_modules/node-gyp/commitlint.config.mjs
@@ -0,0 +1,3 @@
+export default {
+ extends: ['@commitlint/config-conventional']
+};
diff --git a/deps/npm/node_modules/node-gyp/lib/create-config-gypi.js b/deps/npm/node_modules/node-gyp/lib/create-config-gypi.js
index 01a820e9f2f..d471da51690 100644
--- a/deps/npm/node_modules/node-gyp/lib/create-config-gypi.js
+++ b/deps/npm/node_modules/node-gyp/lib/create-config-gypi.js
@@ -99,6 +99,11 @@ async function getCurrentConfigGypi ({ gyp, nodeDir, vsInfo, python }) {
if (config.variables.clang === 1) {
config.variables.clang = 0
}
+ // disable LTO for addon builds. node release builds may enable (thin) LTO,
+ // which leaks clang/lld-only flags like -flto=thin and /opt:lldltojobs into
+ // addons built with the default MSVC toolchain, which rejects those flags
+ variables.enable_lto = 'false'
+ variables.enable_thin_lto = 'false'
}
// loop through the rest of the opts and add the unknown ones as variables.
diff --git a/deps/npm/node_modules/node-gyp/package.json b/deps/npm/node_modules/node-gyp/package.json
index 7f579406da4..cc11fc65e8b 100644
--- a/deps/npm/node_modules/node-gyp/package.json
+++ b/deps/npm/node_modules/node-gyp/package.json
@@ -11,7 +11,7 @@
"bindings",
"gyp"
],
- "version": "12.4.0",
+ "version": "13.0.0",
"installVersion": 11,
"author": "Nathan Rajlich <nathan@tootallnate.net> (http://tootallnate.net)",
"repository": {
@@ -25,18 +25,20 @@
"env-paths": "^2.2.0",
"exponential-backoff": "^3.1.1",
"graceful-fs": "^4.2.6",
- "nopt": "^9.0.0",
- "proc-log": "^6.0.0",
+ "nopt": "^10.0.0",
+ "proc-log": "^7.0.0",
"semver": "^7.3.5",
"tar": "^7.5.4",
"tinyglobby": "^0.2.12",
"undici": "^6.25.0",
- "which": "^6.0.0"
+ "which": "^7.0.0"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"devDependencies": {
+ "@commitlint/cli": "^21.0.2",
+ "@commitlint/config-conventional": "^21.0.2",
"bindings": "^1.5.0",
"cross-env": "^10.1.0",
"eslint": "^9.39.1",
diff --git a/deps/npm/node_modules/nopt/README.md b/deps/npm/node_modules/nopt/README.md
index 19ef097bb2c..cbaf7df965c 100644
--- a/deps/npm/node_modules/nopt/README.md
+++ b/deps/npm/node_modules/nopt/README.md
@@ -141,15 +141,13 @@ config object and remove its invalid properties.
## Error Handling
-By default nopt logs debug messages if `DEBUG_NOPT` or `NOPT_DEBUG` are set in the environment.
-
-You can assign the following methods to `nopt` for a more granular notification of invalid, unknown, and expanding options:
+You can assign the following methods to `nopt` for notification of invalid, unknown, and expanding options:
`nopt.invalidHandler(key, value, type, data)` - Called when a value is invalid for its option.
`nopt.unknownHandler(key, next)` - Called when an option is found that has no configuration. In certain situations the next option on the command line will be parsed on its own instead of as part of the unknown option. In this case `next` will contain that option.
`nopt.abbrevHandler(short, long)` - Called when an option is automatically translated via abbreviations.
-You can also set any of these to `false` to disable the debugging messages that they generate.
+You can set any of these to `false` or leave them unset to skip that notification.
## Abbreviations
diff --git a/deps/npm/node_modules/nopt/lib/debug.js b/deps/npm/node_modules/nopt/lib/debug.js
deleted file mode 100644
index 544ab382ca8..00000000000
--- a/deps/npm/node_modules/nopt/lib/debug.js
+++ /dev/null
@@ -1,5 +0,0 @@
-/* istanbul ignore next */
-module.exports = process.env.DEBUG_NOPT || process.env.NOPT_DEBUG
- // eslint-disable-next-line no-console
- ? (...a) => console.error(...a)
- : () => {}
diff --git a/deps/npm/node_modules/nopt/lib/nopt-lib.js b/deps/npm/node_modules/nopt/lib/nopt-lib.js
index 441c9cc3037..2030f651ca8 100644
--- a/deps/npm/node_modules/nopt/lib/nopt-lib.js
+++ b/deps/npm/node_modules/nopt/lib/nopt-lib.js
@@ -1,5 +1,4 @@
const abbrev = require('abbrev')
-const debug = require('./debug')
const defaultTypeDefs = require('./type-defs')
const hasOwn = (o, k) => Object.prototype.hasOwnProperty.call(o, k)
@@ -31,8 +30,6 @@ function nopt (args, {
typeDefault,
dynamicTypes,
} = {}) {
- debug(types, shorthands, args, typeDefs)
-
const data = {}
const argv = {
remain: [],
@@ -89,7 +86,6 @@ function clean (data, {
return
}
let val = data[k]
- debug('val=%j', val)
const isArray = Array.isArray(val)
let [hasType, rawType] = getType(k, { types, dynamicTypes })
let type = rawType
@@ -106,12 +102,9 @@ function clean (data, {
type = [type]
}
- debug('val=%j', val)
- debug('types=', type)
val = val.map((v) => {
// if it's an unknown value, then parse false/true/null/numbers/dates
if (typeof v === 'string') {
- debug('string %j', v)
v = v.trim()
if ((v === 'null' && ~type.indexOf(null))
|| (v === 'true' &&
@@ -119,12 +112,9 @@ function clean (data, {
|| (v === 'false' &&
(~type.indexOf(false) || hasTypeDef(type, BooleanType)))) {
v = JSON.parse(v)
- debug('jsonable %j', v)
} else if (hasTypeDef(type, NumberType) && !isNaN(v)) {
- debug('convert to number', v)
v = +v
} else if (hasTypeDef(type, DateType) && !isNaN(Date.parse(v))) {
- debug('convert to date', v)
v = new Date(v)
}
}
@@ -148,32 +138,24 @@ function clean (data, {
const d = {}
d[k] = v
- debug('prevalidated val', d, v, rawType)
if (!validate(d, k, v, rawType, { typeDefs })) {
if (invalidHandler) {
invalidHandler(k, v, rawType, data)
- } else if (invalidHandler !== false) {
- debug('invalid: ' + k + '=' + v, rawType)
}
return remove
}
- debug('validated v', d, v, rawType)
return d[k]
}).filter((v) => v !== remove)
// if we allow Array specifically, then an empty array is how we
// express 'no value here', not null. Allow it.
if (!val.length && doesNotHaveTypeDef(type, ArrayType)) {
- debug('VAL HAS NO LENGTH, DELETE IT', val, k, type.indexOf(ArrayType))
delete data[k]
} else if (isArray) {
- debug(isArray, data[k], val)
data[k] = val
} else {
data[k] = val[0]
}
-
- debug('k=%s val=%j', k, val, data[k])
})
}
@@ -199,21 +181,21 @@ function validate (data, k, val, type, { typeDefs } = {}) {
}
// Original comment:
- // NaN is poisonous. Means that something is not allowed.
- // New comment: Changing this to an isNaN check breaks a lot of tests.
- // Something is being assumed here that is not actually what happens in
- // practice. Fixing it is outside the scope of getting linting to pass in
- // this repo. Leaving as-is for now.
+ // NaN is poisonous, it means that something is not allowed.
+
+ // New comment:
+ // Changing this to an isNaN check breaks a lot of tests.
+ // Something is being assumed here that is not actually what happens in practice.
+ // Fixing it is outside the scope of getting linting to pass in this repo.
+ // Leaving as-is for now.
/* eslint-disable-next-line no-self-compare */
if (type !== type) {
- debug('Poison NaN', k, val, type)
delete data[k]
return false
}
// explicit list of values
if (val === type) {
- debug('Explicitly allowed %j', val)
data[k] = val
return true
}
@@ -222,7 +204,6 @@ function validate (data, k, val, type, { typeDefs } = {}) {
let ok = false
const types = Object.keys(typeDefs)
for (let i = 0, l = types.length; i < l; i++) {
- debug('test type %j %j %j', k, val, types[i])
const t = typeDefs[types[i]]
if (t && (
(type && type.name && t.type && t.type.name) ?
@@ -238,7 +219,6 @@ function validate (data, k, val, type, { typeDefs } = {}) {
}
}
}
- debug('OK? %j (%j %j %j)', ok, k, val, types[types.length - 1])
if (!ok) {
delete data[k]
@@ -258,16 +238,11 @@ function parse (args, data, remain, {
const NumberType = typeDefs.Number?.type
const ArrayType = typeDefs.Array?.type
const BooleanType = typeDefs.Boolean?.type
-
- debug('parse', args, data, remain)
-
const abbrevs = abbrev(Object.keys(types))
- debug('abbrevs=%j', abbrevs)
const shortAbbr = abbrev(Object.keys(shorthands))
for (let i = 0; i < args.length; i++) {
let arg = args[i]
- debug('arg', arg)
if (arg.match(/^-{2,}$/)) {
// done with keys.
@@ -289,7 +264,6 @@ function parse (args, data, remain, {
// see if it's a shorthand
// if so, splice and back up to re-parse it.
const shRes = resolveShort(arg, shortAbbr, abbrevs, { shorthands, abbrevHandler })
- debug('arg=%j shRes=%j', arg, shRes)
if (shRes) {
args.splice.apply(args, [i, 1].concat(shRes))
if (arg !== shRes[0]) {
@@ -308,8 +282,6 @@ function parse (args, data, remain, {
if (abbrevs[arg] && abbrevs[arg] !== arg) {
if (abbrevHandler) {
abbrevHandler(arg, abbrevs[arg])
- } else if (abbrevHandler !== false) {
- debug(`abbrev: ${arg} -> ${abbrevs[arg]}`)
}
arg = abbrevs[arg]
}
@@ -352,11 +324,6 @@ function parse (args, data, remain, {
} else {
unknownHandler(arg)
}
- } else if (unknownHandler !== false) {
- debug(`unknown: ${arg}`)
- if (hangingLa) {
- debug(`unknown: ${la} parsed as normal opt`)
- }
}
}
@@ -442,7 +409,6 @@ const singleCharacters = (arg, shorthands) => {
return l
}, {})
shorthands[SINGLES] = singles
- debug('shorthand singles', singles)
}
const chrs = arg.split('').filter((c) => singles[c])
return chrs.join('') === arg ? chrs : null
@@ -490,8 +456,6 @@ function resolveShort (arg, ...rest) {
if (shortAbbr[arg]) {
if (abbrevHandler) {
abbrevHandler(arg, shortAbbr[arg])
- } else if (abbrevHandler !== false) {
- debug(`abbrev: ${arg} -> ${shortAbbr[arg]}`)
}
arg = shortAbbr[arg]
}
diff --git a/deps/npm/node_modules/nopt/lib/nopt.js b/deps/npm/node_modules/nopt/lib/nopt.js
index 9a24342b374..c9d9e820274 100644
--- a/deps/npm/node_modules/nopt/lib/nopt.js
+++ b/deps/npm/node_modules/nopt/lib/nopt.js
@@ -1,10 +1,8 @@
const lib = require('./nopt-lib')
const defaultTypeDefs = require('./type-defs')
-// This is the version of nopt's API that requires setting typeDefs and invalidHandler
-// on the required `nopt` object since it is a singleton. To not do a breaking change
-// an API that requires all options be passed in is located in `nopt-lib.js` and
-// exported here as lib.
+// This is the version of nopt's API that requires setting typeDefs and invalidHandler on the required `nopt` object since it is a singleton.
+// To not do a breaking change an API that requires all options be passed in is located in `nopt-lib.js` and exported here as lib.
// TODO(breaking): make API only work in non-singleton mode
module.exports = exports = nopt
diff --git a/deps/npm/node_modules/nopt/lib/type-defs.js b/deps/npm/node_modules/nopt/lib/type-defs.js
index 608352ee248..4e5e5a37ae1 100644
--- a/deps/npm/node_modules/nopt/lib/type-defs.js
+++ b/deps/npm/node_modules/nopt/lib/type-defs.js
@@ -1,8 +1,7 @@
-const url = require('url')
-const path = require('path')
-const Stream = require('stream').Stream
-const os = require('os')
-const debug = require('./debug')
+const os = require('node:os')
+const path = require('node:path')
+const { Stream } = require('node:stream')
+const { URL } = require('node:url')
function validateString (data, k, val) {
data[k] = String(val)
@@ -31,7 +30,6 @@ function validatePath (data, k, val) {
}
function validateNumber (data, k, val) {
- debug('validate Number %j %j %j', k, val, isNaN(val))
if (isNaN(val)) {
return false
}
@@ -40,7 +38,6 @@ function validateNumber (data, k, val) {
function validateDate (data, k, val) {
const s = Date.parse(val)
- debug('validate Date %j %j %j', k, val, s)
if (isNaN(s)) {
return false
}
@@ -63,13 +60,11 @@ function validateBoolean (data, k, val) {
}
function validateUrl (data, k, val) {
- // Changing this would be a breaking change in the npm cli
- /* eslint-disable-next-line node/no-deprecated-api */
- val = url.parse(String(val))
- if (!val.host) {
+ const parsed = URL.parse(String(val))
+ if (!parsed) {
return false
}
- data[k] = val.href
+ data[k] = parsed.href
}
function validateStream (data, k, val) {
@@ -82,7 +77,7 @@ function validateStream (data, k, val) {
module.exports = {
String: { type: String, validate: validateString },
Boolean: { type: Boolean, validate: validateBoolean },
- url: { type: url, validate: validateUrl },
+ url: { type: URL, validate: validateUrl },
Number: { type: Number, validate: validateNumber },
path: { type: path, validate: validatePath },
Stream: { type: Stream, validate: validateStream },
diff --git a/deps/npm/node_modules/nopt/package.json b/deps/npm/node_modules/nopt/package.json
index bb916429310..db57f7ef292 100644
--- a/deps/npm/node_modules/nopt/package.json
+++ b/deps/npm/node_modules/nopt/package.json
@@ -1,18 +1,20 @@
{
"name": "nopt",
- "version": "9.0.0",
+ "version": "10.0.1",
"description": "Option parsing for Node, supporting types, shorthands, etc. Used by npm.",
"author": "GitHub Inc.",
"main": "lib/nopt.js",
"scripts": {
- "test": "tap",
+ "test": "node --test './test/**/*.js'",
"lint": "npm run eslint",
"postlint": "template-oss-check",
"template-oss-apply": "template-oss-apply --force",
"lintfix": "npm run eslint -- --fix",
- "snap": "tap",
+ "snap": "node --test --test-update-snapshots './test/**/*.js'",
"posttest": "npm run lint",
- "eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\""
+ "eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"",
+ "test:node20": "node --test test",
+ "test:cover": "node --test --experimental-test-coverage --test-timeout=3000 --test-coverage-lines=100 --test-coverage-functions=100 --test-coverage-branches=100 './test/**/*.js'"
},
"repository": {
"type": "git",
@@ -23,30 +25,26 @@
},
"license": "ISC",
"dependencies": {
- "abbrev": "^4.0.0"
+ "abbrev": "^5.0.0"
},
"devDependencies": {
- "@npmcli/eslint-config": "^5.0.0",
- "@npmcli/template-oss": "4.27.1",
- "tap": "^16.3.0"
- },
- "tap": {
- "nyc-arg": [
- "--exclude",
- "tap-snapshots/**"
- ]
+ "@npmcli/eslint-config": "^7.0.0",
+ "@npmcli/template-oss": "5.1.0"
},
"files": [
"bin/",
"lib/"
],
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
"windowsCI": false,
- "version": "4.27.1",
- "publish": true
+ "version": "5.1.0",
+ "publish": true,
+ "testRunner": "node:test",
+ "latestCiVersion": 24,
+ "updateNpm": false
}
}
diff --git a/deps/npm/node_modules/npm-audit-report/package.json b/deps/npm/node_modules/npm-audit-report/package.json
index ff79f724997..0789ac1bde3 100644
--- a/deps/npm/node_modules/npm-audit-report/package.json
+++ b/deps/npm/node_modules/npm-audit-report/package.json
@@ -1,6 +1,6 @@
{
"name": "npm-audit-report",
- "version": "7.0.0",
+ "version": "8.0.0",
"description": "Given a response from the npm security api, render it into a variety of security reports",
"main": "lib/index.js",
"scripts": {
@@ -30,8 +30,8 @@
"author": "GitHub Inc.",
"license": "ISC",
"devDependencies": {
- "@npmcli/eslint-config": "^5.0.0",
- "@npmcli/template-oss": "4.27.1",
+ "@npmcli/eslint-config": "^6.0.0",
+ "@npmcli/template-oss": "5.0.0",
"chalk": "^5.2.0",
"tap": "^16.0.0"
},
@@ -52,11 +52,11 @@
"lib/"
],
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.27.1",
+ "version": "5.0.0",
"publish": true
}
}
diff --git a/deps/npm/node_modules/npm-install-checks/package.json b/deps/npm/node_modules/npm-install-checks/package.json
index aae100c2d4f..c97e2e63c76 100644
--- a/deps/npm/node_modules/npm-install-checks/package.json
+++ b/deps/npm/node_modules/npm-install-checks/package.json
@@ -1,14 +1,14 @@
{
"name": "npm-install-checks",
- "version": "8.0.0",
+ "version": "9.0.0",
"description": "Check the engines and platform fields in package.json",
"main": "lib/index.js",
"dependencies": {
"semver": "^7.1.1"
},
"devDependencies": {
- "@npmcli/eslint-config": "^5.0.0",
- "@npmcli/template-oss": "4.27.1",
+ "@npmcli/eslint-config": "^6.0.0",
+ "@npmcli/template-oss": "5.1.0",
"tap": "^16.0.1"
},
"scripts": {
@@ -35,12 +35,12 @@
"lib/"
],
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"author": "GitHub Inc.",
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.27.1",
+ "version": "5.1.0",
"publish": "true"
},
"tap": {
diff --git a/deps/npm/node_modules/npm-package-arg/package.json b/deps/npm/node_modules/npm-package-arg/package.json
index 2e2d027f055..692d59c7552 100644
--- a/deps/npm/node_modules/npm-package-arg/package.json
+++ b/deps/npm/node_modules/npm-package-arg/package.json
@@ -1,6 +1,6 @@
{
"name": "npm-package-arg",
- "version": "13.0.2",
+ "version": "14.0.0",
"description": "Parse the things that can be arguments to `npm install`",
"main": "./lib/npa.js",
"directories": {
@@ -11,14 +11,14 @@
"lib/"
],
"dependencies": {
- "hosted-git-info": "^9.0.0",
- "proc-log": "^6.0.0",
+ "hosted-git-info": "^10.1.0",
+ "proc-log": "^7.0.0",
"semver": "^7.3.5",
- "validate-npm-package-name": "^7.0.0"
+ "validate-npm-package-name": "^8.0.0"
},
"devDependencies": {
"@npmcli/eslint-config": "^6.0.0",
- "@npmcli/template-oss": "4.28.0",
+ "@npmcli/template-oss": "5.1.0",
"tap": "^16.0.1"
},
"scripts": {
@@ -44,7 +44,7 @@
},
"homepage": "https://github.com/npm/npm-package-arg",
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"tap": {
"nyc-arg": [
@@ -54,7 +54,7 @@
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.28.0",
+ "version": "5.1.0",
"publish": true
}
}
diff --git a/deps/npm/node_modules/npm-packlist/lib/index.js b/deps/npm/node_modules/npm-packlist/lib/index.js
index 422adcfcd13..4ff84b796b7 100644
--- a/deps/npm/node_modules/npm-packlist/lib/index.js
+++ b/deps/npm/node_modules/npm-packlist/lib/index.js
@@ -1,12 +1,14 @@
'use strict'
const { Walker: IgnoreWalker } = require('ignore-walk')
-const { lstatSync: lstat, readFileSync: readFile } = require('fs')
-const { basename, dirname, extname, join, relative, resolve, sep } = require('path')
+const { globSync } = require('glob')
+const { readFileSync: readFile } = require('node:fs')
+const { basename, dirname, extname, join, relative, resolve, sep } = require('node:path')
const { log } = require('proc-log')
// symbols used to represent synthetic rule sets
const defaultRules = Symbol('npm-packlist.rules.default')
+const globalRules = Symbol('npm-packlist.rules.global')
const strictRules = Symbol('npm-packlist.rules.strict')
// There may be others, but :?|<> are handled by node-tar
@@ -83,13 +85,23 @@ class PackWalker extends IgnoreWalker {
follow: false,
// we path.resolve() here because ignore-walk doesn't do it and we want full paths
path: resolve(opts?.path || tree.path).replace(/\\/g, '/'),
- ignoreFiles: opts?.ignoreFiles || [
+ // globalRules belongs on the root walker only. Child walkers reach it through
+ // parent.filterEntry, where package.json rules can still override it; reapplying
+ // globalRules at the child level would defeat that override.
+ ignoreFiles: opts?.ignoreFiles || (opts?.parent ? [
defaultRules,
'package.json',
'.npmignore',
'.gitignore',
strictRules,
- ],
+ ] : [
+ defaultRules,
+ globalRules,
+ 'package.json',
+ '.npmignore',
+ '.gitignore',
+ strictRules,
+ ]),
}
super(options)
@@ -97,7 +109,8 @@ class PackWalker extends IgnoreWalker {
this.isPackage = options.isPackage
this.seen = options.seen || new Set()
this.tree = tree
- this.requiredFiles = options.requiredFiles || []
+ this.globalIgnoreFile = options.globalIgnoreFile || null
+ this.globalIgnoreRules = options.globalIgnoreRules || null
const additionalDefaults = []
if (options.prefix && options.workspaces) {
@@ -124,13 +137,34 @@ class PackWalker extends IgnoreWalker {
// go ahead and inject the default rules now
this.injectRules(defaultRules, [...defaults, ...additionalDefaults])
+ // inject the global rules from the user's ignore file. positioned between
+ // defaultRules and package.json so an explicit entry in the package "files"
+ // field can still override. only the root walker carries globalRules in its
+ // ignoreFiles list; child walkers see global exclusions via parent.filterEntry,
+ // which is what lets the package.json `!/path/**` override win.
+ if (this.globalIgnoreRules === null && this.globalIgnoreFile) {
+ try {
+ this.globalIgnoreRules = readFile(this.globalIgnoreFile, { encoding: 'utf8' })
+ } catch (err) {
+ // istanbul ignore next -- only ENOENT is expected here
+ if (err.code !== 'ENOENT') {
+ throw err
+ }
+ this.globalIgnoreRules = ''
+ }
+ }
+ if (this.globalIgnoreRules) {
+ this.injectRules(globalRules, [this.globalIgnoreRules])
+ // istanbul ignore else -- globalIgnoreRules without a filename only happens when
+ // a caller pre-populates rules directly instead of going through globalIgnoreFile
+ if (this.globalIgnoreFile) {
+ log.silly('global-ignore-file', `applied rules from ${this.globalIgnoreFile}`)
+ }
+ }
+
if (!this.isPackage) {
- // if this instance is not a package, then place some strict default rules, and append
- // known required files for this directory
- this.injectRules(strictRules, [
- ...strictDefaults,
- ...this.requiredFiles.map((file) => `!${file}`),
- ])
+ // if this instance is not a package, then place some strict default rules
+ this.injectRules(strictRules, [...strictDefaults])
}
}
@@ -234,15 +268,6 @@ class PackWalker extends IgnoreWalker {
return {
...super.walkerOpt(entry, opts),
ignoreFiles,
- // we map over our own requiredFiles and pass ones that are within this entry
- requiredFiles: this.requiredFiles
- .map((file) => {
- if (relative(file, entry) === '..') {
- return relative(entry, file).replace(/\\/g, '/')
- }
- return false
- })
- .filter(Boolean),
}
}
@@ -280,6 +305,7 @@ class PackWalker extends IgnoreWalker {
browser,
files,
main,
+ patchedDependencies,
} = this.tree.package
// rules in these arrays are inverted since they are patterns we want to _not_ ignore
@@ -295,46 +321,62 @@ class PackWalker extends IgnoreWalker {
'/node_modules',
'.npmrc',
'/package-lock.json',
+ '/npm-shrinkwrap.json',
'/yarn.lock',
'/pnpm-lock.yaml',
'/bun.lockb',
+ '/bun.lock',
+ '/.npm-extension.mjs',
+ '/.npm-extension.cjs',
]
// if we have a files array in our package, we need to pull rules from it
if (files) {
- for (let file of files) {
- // invert the rule because these are things we want to include
- if (file.startsWith('./')) {
- file = file.slice(1)
+ for (const entry of files) {
+ const isNegation = entry.startsWith('!')
+ // normalize: strip leading `!`s, `./`, a single leading `/`, and trailing slashes.
+ // trailing slashes confuse glob; the leading forms are equivalent to their stripped versions for glob expansion.
+ const pattern = (isNegation ? entry.replace(/^!+/, '') : entry)
+ .replace(/^\.?\//, '')
+ .replace(/\/+$/, '')
+ if (!pattern) {
+ continue
}
- if (file.endsWith('/*')) {
- file += '*'
- }
- const inverse = `!${file}`
+
+ // expand the entry as a glob against the package root.
+ // literal paths (e.g. `lib`, `lib/foo.js`) are valid globs and resolve to themselves;
+ // patterns (e.g. `dist-*`, `**/*.js`) resolve to all matching entries;
+ // typos and non-existent entries resolve to nothing.
+ let matches = []
try {
- // if an entry in the files array is a specific file, then we need to include it as a
- // strict requirement for this package. if it's a directory or a pattern, it's a default
- // pattern instead. this is ugly, but we have to stat to find out if it's a file
- const stat = lstat(join(this.path, file.replace(/^!+/, '')).replace(/\\/g, '/'))
- // if we have a file and we know that, it's strictly required
- if (stat.isFile()) {
- strict.unshift(inverse)
- this.requiredFiles.push(file.startsWith('/') ? file.slice(1) : file)
- } else if (stat.isDirectory()) {
- // otherwise, it's a default ignore, and since we got here we know it's not a pattern
- // so we include the directory contents
- ignores.push(inverse)
- ignores.push(`${inverse}/**`)
+ matches = globSync(pattern, { cwd: this.path, withFileTypes: true, dot: true })
+ } catch {
+ // unparseable globs produce no matches and drop silently.
+ // (Pre-v11 instead fell through to push the raw entry as an ignore-walk pattern rule; we deliberately don't preserve that.)
+ }
+
+ // a positive entry produces `!path` rules (un-ignore from the surrounding `*` deny-all); a negation produces `path` rules (re-ignore them).
+ // directory matches expand to also include their contents; this is documented `files[]` behavior, not a glob hack.
+ const prefix = isNegation ? '' : '!'
+ for (const match of matches) {
+ const rel = match.relativePosix()
+ // istanbul ignore next -- defensive: glob with withFileTypes returns the cwd as an entry with an empty relative path; skip it.
+ if (!rel) {
+ continue
+ }
+ if (match.isDirectory()) {
+ ignores.push(`${prefix}/${rel}`)
+ ignores.push(`${prefix}/${rel}/**`)
+ continue
+ }
+ // istanbul ignore else -- non-file-non-dir matches (sockets, fifos, broken symlinks) drop silently.
+ if (match.isFile()) {
+ ignores.push(`${prefix}/${rel}`)
}
- // if the thing exists, but is neither a file or a directory, we don't want it at all
- } catch (err) {
- // if lstat throws, then we assume we're looking at a pattern and treat it as a default
- ignores.push(inverse)
}
}
- // we prepend a '*' to exclude everything, followed by our inverted file rules
- // which now mean to include those
+ // we prepend a '*' to exclude everything, followed by our inverted file rules which now mean to include those
this.injectRules('package.json', ['*', ...ignores])
}
@@ -355,6 +397,32 @@ class PackWalker extends IgnoreWalker {
}
}
+ // patch files declared in patchedDependencies are project-local fixes and must never ship.
+ // patchedDependencies is root-only state, so this applies only to the package being packed.
+ // each declared patch file is force-excluded even when it was added via "files".
+ // only the exact files are excluded, never their directory, so a shared dir keeps its other contents.
+ if (this.tree.isProjectRoot && patchedDependencies && typeof patchedDependencies === 'object') {
+ for (const patchPath of Object.values(patchedDependencies)) {
+ if (typeof patchPath !== 'string') {
+ continue
+ }
+ const rel = normalizePath(patchPath).replace(/^\.?\//, '').replace(/\/+$/, '')
+ // skip absolute paths or paths that escape the package root, which are never packed anyway
+ if (!rel || rel.startsWith('/') || rel === '..' || rel.startsWith('../') || rel.includes('/../')) {
+ continue
+ }
+ // warn when a "files" entry pulled the patch file in, either directly or via its directory
+ const parentGlob = `!/${normalizePath(dirname(rel))}/**`
+ if (files && (ignores.includes(`!/${rel}`) || ignores.includes(parentGlob))) {
+ log.warn(
+ 'patched-dependencies',
+ `excluding "${rel}" from the package tarball: patch files in patchedDependencies must not be published`
+ )
+ }
+ strict.push(`/${rel}`)
+ }
+ }
+
// and now we add all of the strict rules to our synthetic file
this.injectRules(strictRules, strict, callback)
}
diff --git a/deps/npm/node_modules/ignore-walk/LICENSE b/deps/npm/node_modules/npm-packlist/node_modules/ignore-walk/LICENSE
similarity index 100%
rename from deps/npm/node_modules/ignore-walk/LICENSE
rename to deps/npm/node_modules/npm-packlist/node_modules/ignore-walk/LICENSE
diff --git a/deps/npm/node_modules/ignore-walk/lib/index.js b/deps/npm/node_modules/npm-packlist/node_modules/ignore-walk/lib/index.js
similarity index 100%
rename from deps/npm/node_modules/ignore-walk/lib/index.js
rename to deps/npm/node_modules/npm-packlist/node_modules/ignore-walk/lib/index.js
diff --git a/deps/npm/node_modules/ignore-walk/package.json b/deps/npm/node_modules/npm-packlist/node_modules/ignore-walk/package.json
similarity index 92%
rename from deps/npm/node_modules/ignore-walk/package.json
rename to deps/npm/node_modules/npm-packlist/node_modules/ignore-walk/package.json
index ea640d5dbc1..0b11aa50e82 100644
--- a/deps/npm/node_modules/ignore-walk/package.json
+++ b/deps/npm/node_modules/npm-packlist/node_modules/ignore-walk/package.json
@@ -1,11 +1,11 @@
{
"name": "ignore-walk",
- "version": "8.0.0",
+ "version": "9.0.0",
"description": "Nested/recursive `.gitignore`/`.npmignore` parsing and filtering.",
"main": "lib/index.js",
"devDependencies": {
"@npmcli/eslint-config": "^5.0.0",
- "@npmcli/template-oss": "4.24.3",
+ "@npmcli/template-oss": "5.0.0",
"mutate-fs": "^2.1.1",
"tap": "^16.0.1"
},
@@ -53,11 +53,11 @@
]
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.24.3",
+ "version": "5.0.0",
"content": "scripts/template-oss",
"publish": "true"
}
diff --git a/deps/npm/node_modules/npm-packlist/package.json b/deps/npm/node_modules/npm-packlist/package.json
index 88e55b79c64..ae5c4fc596a 100644
--- a/deps/npm/node_modules/npm-packlist/package.json
+++ b/deps/npm/node_modules/npm-packlist/package.json
@@ -1,14 +1,15 @@
{
"name": "npm-packlist",
- "version": "10.0.4",
+ "version": "11.3.0",
"description": "Get a list of the files to add from a folder into an npm package",
"directories": {
"test": "test"
},
"main": "lib/index.js",
"dependencies": {
- "ignore-walk": "^8.0.0",
- "proc-log": "^6.0.0"
+ "glob": "^13.0.6",
+ "ignore-walk": "^9.0.0",
+ "proc-log": "^7.0.0"
},
"author": "GitHub Inc.",
"license": "ISC",
@@ -18,8 +19,8 @@
],
"devDependencies": {
"@npmcli/arborist": "^9.0.0",
- "@npmcli/eslint-config": "^6.0.0",
- "@npmcli/template-oss": "4.29.0",
+ "@npmcli/eslint-config": "^7.0.0",
+ "@npmcli/template-oss": "5.1.1",
"mutate-fs": "^2.1.1",
"tap": "^16.0.1"
},
@@ -52,11 +53,12 @@
]
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.29.0",
- "publish": true
+ "version": "5.1.1",
+ "publish": true,
+ "updateNpm": false
}
}
diff --git a/deps/npm/node_modules/npm-pick-manifest/node_modules/npm-normalize-package-bin/LICENSE b/deps/npm/node_modules/npm-pick-manifest/node_modules/npm-normalize-package-bin/LICENSE
new file mode 100644
index 00000000000..19cec97b184
--- /dev/null
+++ b/deps/npm/node_modules/npm-pick-manifest/node_modules/npm-normalize-package-bin/LICENSE
@@ -0,0 +1,15 @@
+The ISC License
+
+Copyright (c) npm, 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.
diff --git a/deps/npm/node_modules/npm-pick-manifest/node_modules/npm-normalize-package-bin/lib/index.js b/deps/npm/node_modules/npm-pick-manifest/node_modules/npm-normalize-package-bin/lib/index.js
new file mode 100644
index 00000000000..3cb8478cf6e
--- /dev/null
+++ b/deps/npm/node_modules/npm-pick-manifest/node_modules/npm-normalize-package-bin/lib/index.js
@@ -0,0 +1,64 @@
+// pass in a manifest with a 'bin' field here, and it'll turn it
+// into a properly santized bin object
+const { join, basename } = require('path')
+
+const normalize = pkg =>
+ !pkg.bin ? removeBin(pkg)
+ : typeof pkg.bin === 'string' ? normalizeString(pkg)
+ : Array.isArray(pkg.bin) ? normalizeArray(pkg)
+ : typeof pkg.bin === 'object' ? normalizeObject(pkg)
+ : removeBin(pkg)
+
+const normalizeString = pkg => {
+ if (!pkg.name) {
+ return removeBin(pkg)
+ }
+ pkg.bin = { [pkg.name]: pkg.bin }
+ return normalizeObject(pkg)
+}
+
+const normalizeArray = pkg => {
+ pkg.bin = pkg.bin.reduce((acc, k) => {
+ acc[basename(k)] = k
+ return acc
+ }, {})
+ return normalizeObject(pkg)
+}
+
+const removeBin = pkg => {
+ delete pkg.bin
+ return pkg
+}
+
+const normalizeObject = pkg => {
+ const orig = pkg.bin
+ const clean = {}
+ let hasBins = false
+ Object.keys(orig).forEach(binKey => {
+ const base = join('/', basename(binKey.replace(/\\|:/g, '/'))).slice(1)
+
+ if (typeof orig[binKey] !== 'string' || !base) {
+ return
+ }
+
+ const binTarget = join('/', orig[binKey].replace(/\\/g, '/'))
+ .replace(/\\/g, '/').slice(1)
+
+ if (!binTarget) {
+ return
+ }
+
+ clean[base] = binTarget
+ hasBins = true
+ })
+
+ if (hasBins) {
+ pkg.bin = clean
+ } else {
+ delete pkg.bin
+ }
+
+ return pkg
+}
+
+module.exports = normalize
diff --git a/deps/npm/node_modules/npm-pick-manifest/node_modules/npm-normalize-package-bin/package.json b/deps/npm/node_modules/npm-pick-manifest/node_modules/npm-normalize-package-bin/package.json
new file mode 100644
index 00000000000..1d0d821b7a2
--- /dev/null
+++ b/deps/npm/node_modules/npm-pick-manifest/node_modules/npm-normalize-package-bin/package.json
@@ -0,0 +1,42 @@
+{
+ "name": "npm-normalize-package-bin",
+ "version": "6.0.0",
+ "description": "Turn any flavor of allowable package.json bin into a normalized object",
+ "main": "lib/index.js",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/npm/npm-normalize-package-bin.git"
+ },
+ "author": "GitHub Inc.",
+ "license": "ISC",
+ "scripts": {
+ "test": "node --test './test/**/*.js'",
+ "snap": "node --test --test-update-snapshots './test/**/*.js'",
+ "lint": "npm run eslint",
+ "postlint": "template-oss-check",
+ "template-oss-apply": "template-oss-apply --force",
+ "lintfix": "npm run eslint -- --fix",
+ "posttest": "npm run lint",
+ "eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"",
+ "test:node20": "node --test test",
+ "test:cover": "node --test --experimental-test-coverage --test-timeout=3000 --test-coverage-lines=100 --test-coverage-functions=100 --test-coverage-branches=100 './test/**/*.js'"
+ },
+ "devDependencies": {
+ "@npmcli/eslint-config": "^6.0.0",
+ "@npmcli/template-oss": "5.0.0"
+ },
+ "files": [
+ "bin/",
+ "lib/"
+ ],
+ "engines": {
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
+ },
+ "templateOSS": {
+ "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
+ "version": "5.0.0",
+ "publish": "true",
+ "testRunner": "node:test",
+ "latestCiVersion": 24
+ }
+}
diff --git a/deps/npm/node_modules/npm-pick-manifest/package.json b/deps/npm/node_modules/npm-pick-manifest/package.json
index 5cfafcfb708..766b0b8d43a 100644
--- a/deps/npm/node_modules/npm-pick-manifest/package.json
+++ b/deps/npm/node_modules/npm-pick-manifest/package.json
@@ -1,6 +1,6 @@
{
"name": "npm-pick-manifest",
- "version": "11.0.3",
+ "version": "12.0.0",
"description": "Resolves a matching manifest from a package metadata document according to standard npm semver resolution rules.",
"main": "./lib",
"files": [
@@ -10,13 +10,15 @@
"scripts": {
"coverage": "tap",
"lint": "npm run eslint",
- "test": "tap",
+ "test": "node --test './test/**/*.js'",
"posttest": "npm run lint",
"postlint": "template-oss-check",
"lintfix": "npm run eslint -- --fix",
- "snap": "tap",
+ "snap": "node --test --test-update-snapshots './test/**/*.js'",
"template-oss-apply": "template-oss-apply --force",
- "eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\""
+ "eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"",
+ "test:node20": "node --test test",
+ "test:cover": "node --test --experimental-test-coverage --test-timeout=3000 --test-coverage-lines=100 --test-coverage-functions=100 --test-coverage-branches=100 './test/**/*.js'"
},
"repository": {
"type": "git",
@@ -30,29 +32,23 @@
"author": "GitHub Inc.",
"license": "ISC",
"dependencies": {
- "npm-install-checks": "^8.0.0",
- "npm-normalize-package-bin": "^5.0.0",
- "npm-package-arg": "^13.0.0",
+ "npm-install-checks": "^9.0.0",
+ "npm-normalize-package-bin": "^6.0.0",
+ "npm-package-arg": "^14.0.0",
"semver": "^7.3.5"
},
"devDependencies": {
"@npmcli/eslint-config": "^6.0.0",
- "@npmcli/template-oss": "4.27.1",
- "tap": "^16.0.1"
- },
- "tap": {
- "check-coverage": true,
- "nyc-arg": [
- "--exclude",
- "tap-snapshots/**"
- ]
+ "@npmcli/template-oss": "5.1.0"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.27.1",
- "publish": true
+ "version": "5.1.0",
+ "publish": true,
+ "testRunner": "node:test",
+ "latestCiVersion": 24
}
}
diff --git a/deps/npm/node_modules/npm-profile/lib/index.js b/deps/npm/node_modules/npm-profile/lib/index.js
index 734e08abb65..0a8a706f44a 100644
--- a/deps/npm/node_modules/npm-profile/lib/index.js
+++ b/deps/npm/node_modules/npm-profile/lib/index.js
@@ -18,24 +18,6 @@ const login = async (opener, prompter, opts = {}) => {
}
}
-const adduser = async (opener, prompter, opts = {}) => {
- try {
- return await adduserWeb(opener, opts)
- } catch (er) {
- if (er instanceof WebLoginNotSupported) {
- log.verbose('web adduser', 'not supported, trying couch')
- const { username, email, password } = await prompter(opts.creds)
- return adduserCouch(username, email, password, opts)
- }
- throw er
- }
-}
-
-const adduserWeb = (opener, opts = {}) => {
- log.verbose('web adduser', 'before first POST')
- return webAuth(opener, opts, { create: true })
-}
-
const loginWeb = (opener, opts = {}) => {
log.verbose('web login', 'before first POST')
return webAuth(opener, opts, {})
@@ -166,25 +148,6 @@ const putCouch = async (path, username, body, opts) => {
return result
}
-const adduserCouch = async (username, email, password, opts = {}) => {
- const body = {
- _id: `org.couchdb.user:${username}`,
- name: username,
- password: password,
- email: email,
- type: 'user',
- roles: [],
- date: new Date().toISOString(),
- }
-
- log.verbose('adduser', 'before first PUT', {
- ...body,
- password: 'XXXXX',
- })
-
- return putCouch('', username, body, opts)
-}
-
const loginCouch = async (username, password, opts = {}) => {
const body = {
_id: `org.couchdb.user:${username}`,
@@ -289,12 +252,9 @@ class WebLoginNotSupported extends HttpErrorBase {
}
module.exports = {
- adduserCouch,
loginCouch,
- adduserWeb,
loginWeb,
login,
- adduser,
get,
set,
listTokens,
diff --git a/deps/npm/node_modules/npm-profile/package.json b/deps/npm/node_modules/npm-profile/package.json
index bb7f23ec831..9b4e5a24b57 100644
--- a/deps/npm/node_modules/npm-profile/package.json
+++ b/deps/npm/node_modules/npm-profile/package.json
@@ -1,13 +1,13 @@
{
"name": "npm-profile",
- "version": "12.0.2",
+ "version": "13.0.1",
"description": "Library for updating an npmjs.com profile",
"keywords": [],
"author": "GitHub Inc.",
"license": "ISC",
"dependencies": {
- "npm-registry-fetch": "^19.0.0",
- "proc-log": "^6.1.0"
+ "npm-registry-fetch": "^20.0.0",
+ "proc-log": "^7.0.0"
},
"main": "./lib/index.js",
"repository": {
@@ -42,7 +42,7 @@
]
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
diff --git a/deps/npm/node_modules/npm-registry-fetch/lib/errors.js b/deps/npm/node_modules/npm-registry-fetch/lib/errors.js
index 5bf6b012a24..1b828825efa 100644
--- a/deps/npm/node_modules/npm-registry-fetch/lib/errors.js
+++ b/deps/npm/node_modules/npm-registry-fetch/lib/errors.js
@@ -38,13 +38,18 @@ class HttpErrorBase extends Error {
class HttpErrorGeneral extends HttpErrorBase {
constructor (method, res, body, spec) {
super(method, res, body, spec)
+ let detail = ''
+ if (body && typeof body === 'object' && !Buffer.isBuffer(body)) {
+ const text = body.error || body.message || JSON.stringify(body)
+ if (text && text !== '{}') {
+ detail = ' - ' + text
+ }
+ }
this.message = `${res.status} ${res.statusText} - ${
this.method.toUpperCase()
} ${
this.spec || this.uri
- }${
- (body && body.error) ? ' - ' + body.error : ''
- }`
+ }${detail}`
}
}
diff --git a/deps/npm/node_modules/npm-registry-fetch/package.json b/deps/npm/node_modules/npm-registry-fetch/package.json
index 6f43ed70367..12fc0fcae48 100644
--- a/deps/npm/node_modules/npm-registry-fetch/package.json
+++ b/deps/npm/node_modules/npm-registry-fetch/package.json
@@ -1,6 +1,6 @@
{
"name": "npm-registry-fetch",
- "version": "19.1.1",
+ "version": "20.0.1",
"description": "Fetch-based http client for use with npm registry APIs",
"main": "lib",
"files": [
@@ -31,22 +31,22 @@
"author": "GitHub Inc.",
"license": "ISC",
"dependencies": {
- "@npmcli/redact": "^4.0.0",
+ "@npmcli/redact": "^5.0.0",
"jsonparse": "^1.3.1",
- "make-fetch-happen": "^15.0.0",
+ "make-fetch-happen": "^16.0.0",
"minipass": "^7.0.2",
- "minipass-fetch": "^5.0.0",
+ "minipass-fetch": "^6.0.0",
"minizlib": "^3.0.1",
- "npm-package-arg": "^13.0.0",
- "proc-log": "^6.0.0"
+ "npm-package-arg": "^14.0.0",
+ "proc-log": "^7.0.0"
},
"devDependencies": {
- "@npmcli/eslint-config": "^6.0.0",
- "@npmcli/template-oss": "4.28.0",
- "cacache": "^20.0.0",
+ "@npmcli/eslint-config": "^7.0.0",
+ "@npmcli/template-oss": "5.1.0",
+ "cacache": "^21.0.0",
"nock": "^13.2.4",
"require-inject": "^1.4.4",
- "ssri": "^13.0.0",
+ "ssri": "^14.0.0",
"tap": "^16.0.1"
},
"tap": {
@@ -58,11 +58,11 @@
]
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.28.0",
+ "version": "5.1.0",
"publish": "true"
}
}
diff --git a/deps/npm/node_modules/npm-user-validate/package.json b/deps/npm/node_modules/npm-user-validate/package.json
index b7a30835afb..d18f7ffb149 100644
--- a/deps/npm/node_modules/npm-user-validate/package.json
+++ b/deps/npm/node_modules/npm-user-validate/package.json
@@ -1,22 +1,23 @@
{
"name": "npm-user-validate",
- "version": "4.0.0",
+ "version": "5.0.0",
"description": "User validations for npm",
"main": "lib/index.js",
"devDependencies": {
- "@npmcli/eslint-config": "^5.0.0",
- "@npmcli/template-oss": "4.27.1",
- "tap": "^16.3.2"
+ "@npmcli/eslint-config": "^6.0.0",
+ "@npmcli/template-oss": "5.0.0"
},
"scripts": {
- "test": "tap",
+ "test": "node --test './test/**/*.js'",
"lint": "npm run eslint",
"postlint": "template-oss-check",
"template-oss-apply": "template-oss-apply --force",
"lintfix": "npm run eslint -- --fix",
- "snap": "tap",
+ "snap": "node --test --test-update-snapshots './test/**/*.js'",
"posttest": "npm run lint",
- "eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\""
+ "eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"",
+ "test:cover": "node --test --experimental-test-coverage --test-timeout=3000 --test-coverage-lines=100 --test-coverage-functions=100 --test-coverage-branches=100 './test/**/*.js'",
+ "test:node20": "node --test test"
},
"repository": {
"type": "git",
@@ -34,17 +35,13 @@
"lib/"
],
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.27.1",
- "publish": true
- },
- "tap": {
- "nyc-arg": [
- "--exclude",
- "tap-snapshots/**"
- ]
+ "version": "5.0.0",
+ "publish": true,
+ "testRunner": "node:test",
+ "latestCiVersion": 24
}
}
diff --git a/deps/npm/node_modules/p-map/index.js b/deps/npm/node_modules/p-map/index.js
index f713b9bf363..5aabf95ad8a 100644
--- a/deps/npm/node_modules/p-map/index.js
+++ b/deps/npm/node_modules/p-map/index.js
@@ -226,7 +226,8 @@ export function pMapIterable(
trySpawn();
try {
- const returnValue = await mapper(await value, index++);
+ const currentIndex = index++;
+ const returnValue = await mapper(await value, currentIndex);
pendingPromisesCount--;
diff --git a/deps/npm/node_modules/p-map/package.json b/deps/npm/node_modules/p-map/package.json
index 6401a2a6a51..dec77dd6f3f 100644
--- a/deps/npm/node_modules/p-map/package.json
+++ b/deps/npm/node_modules/p-map/package.json
@@ -1,6 +1,6 @@
{
"name": "p-map",
- "version": "7.0.4",
+ "version": "7.0.5",
"description": "Map over promises concurrently",
"license": "MIT",
"repository": "sindresorhus/p-map",
diff --git a/deps/npm/node_modules/pacote/lib/dir.js b/deps/npm/node_modules/pacote/lib/dir.js
index 04846eb8a6e..f1d416fcfab 100644
--- a/deps/npm/node_modules/pacote/lib/dir.js
+++ b/deps/npm/node_modules/pacote/lib/dir.js
@@ -1,8 +1,11 @@
-const { resolve } = require('node:path')
+const { resolve, join } = require('node:path')
+const { mkdtemp, writeFile, rm } = require('node:fs/promises')
+const { tmpdir } = require('node:os')
const packlist = require('npm-packlist')
const runScript = require('@npmcli/run-script')
const tar = require('tar')
const { Minipass } = require('minipass')
+const PackageJson = require('@npmcli/package-json')
const Fetcher = require('./fetcher.js')
const FileFetcher = require('./file.js')
const _ = require('./util/protected.js')
@@ -66,7 +69,7 @@ class DirFetcher extends Fetcher {
stream.resolved = this.resolved
stream.integrity = this.integrity
- const { prefix, workspaces } = this.opts
+ const { prefix, workspaces, globalIgnoreFile } = this.opts
// run the prepare script, get the list of files, and tar it up
// pipe to the stream, and proxy errors the chain.
@@ -76,14 +79,66 @@ class DirFetcher extends Fetcher {
const arb = new this.Arborist({ path: this.resolved })
this.tree = await arb.loadActual()
}
- return packlist(this.tree, { path: this.resolved, prefix, workspaces })
+ return packlist(this.tree, { path: this.resolved, prefix, workspaces, globalIgnoreFile })
+ })
+ .then(async files => {
+ const { options, cleanup } = await this.#tarOptions()
+ const source = tar.c(options, files)
+ // the strip temp file must outlive content consumption, so clean up once the stream is done
+ source.once('end', cleanup)
+ source.once('error', cleanup)
+ return source.on('error', er => stream.emit('error', er)).pipe(stream)
})
- .then(files => tar.c(tarCreateOptions(this.package), files)
- .on('error', er => stream.emit('error', er)).pipe(stream))
.catch(er => stream.emit('error', er))
return stream
}
+ // Build the tar create options.
+ // When the packed package.json declares patchedDependencies, redirect it to a stripped copy so project-local patches never ship.
+ // Non-patched packs are unchanged.
+ async #tarOptions () {
+ const options = tarCreateOptions(this.package)
+
+ // read package.json from disk after prepare so the strip reflects the actually-packed manifest.
+ const pkgJson = await PackageJson.load(this.resolved)
+ if (!('patchedDependencies' in pkgJson.content)) {
+ return { options, cleanup: () => {} }
+ }
+
+ // serialize the package.json minus patchedDependencies, preserving its indent and newline.
+ // JSON.stringify ignores the indent and newline symbols @npmcli/package-json attaches to content.
+ delete pkgJson.content.patchedDependencies
+ const { content } = pkgJson
+ const indent = content[Symbol.for('indent')]
+ const newline = content[Symbol.for('newline')]
+ const stripped = `${JSON.stringify(content, null, indent)}\n`.replace(/\n/g, newline)
+
+ // write the stripped copy to a temp dir, removing it if the write itself fails.
+ const dir = await mkdtemp(join(tmpdir(), 'pacote-pack-'))
+ const strippedPath = join(dir, 'package.json')
+ try {
+ await writeFile(strippedPath, stripped)
+ } catch (er) {
+ /* istanbul ignore next - writing to a freshly created temp dir is not deterministically failable */
+ await rm(dir, { recursive: true, force: true })
+ /* istanbul ignore next */
+ throw er
+ }
+ const size = Buffer.byteLength(stripped)
+
+ // point only the top-level package.json entry at the stripped copy; every other file is untouched.
+ // onWriteEntry runs before the tar header and the file's hardlink check, so size and nlink here are honored.
+ options.onWriteEntry = (entry) => {
+ if (entry.path === 'package.json') {
+ entry.absolute = strippedPath
+ entry.stat.size = size
+ entry.stat.nlink = 1
+ }
+ }
+
+ return { options, cleanup: () => rm(dir, { recursive: true, force: true }) }
+ }
+
manifest () {
if (this.package) {
return Promise.resolve(this.package)
diff --git a/deps/npm/node_modules/pacote/lib/fetcher.js b/deps/npm/node_modules/pacote/lib/fetcher.js
index 8324f46f1f3..20c0d67548a 100644
--- a/deps/npm/node_modules/pacote/lib/fetcher.js
+++ b/deps/npm/node_modules/pacote/lib/fetcher.js
@@ -118,6 +118,10 @@ class FetcherBase {
// we need the actual things, not just the lockfile
'--no-package-lock-only',
'--no-dry-run',
+ // override npm_config_global from the parent process: this inner
+ // `npm install` is preparing deps inside a tmp git clone, and it
+ // must reify into that clone's cwd, never the outer global prefix.
+ '--global=false',
]
}
diff --git a/deps/npm/node_modules/pacote/lib/git.js b/deps/npm/node_modules/pacote/lib/git.js
index 8faf125c6e5..198540ab8d3 100644
--- a/deps/npm/node_modules/pacote/lib/git.js
+++ b/deps/npm/node_modules/pacote/lib/git.js
@@ -19,7 +19,7 @@ const hashre = /^[a-f0-9]{40,64}$/
// otherwise, prefer ssh if available (more secure).
// We have to add the git+ back because npa suppresses it.
const repoUrl = (h, opts) =>
- h.sshurl && !(h.https && h.auth) && addGitPlus(h.sshurl(opts)) ||
+ h.sshurl && !(h.https && (h.auth || h.default === 'https')) && addGitPlus(h.sshurl(opts)) ||
h.https && addGitPlus(h.https(opts))
// add git+ to the url, but only one time.
@@ -171,6 +171,11 @@ class GitFetcher extends Fetcher {
return
}
+ // honor ignoreScripts: spawning `npm install` here would run lifecycle scripts (install, preinstall, postinstall, prepare) from the cloned repo, defeating the caller's explicit opt-out.
+ if (this.opts.ignoreScripts) {
+ return
+ }
+
// to avoid cases where we have an cycle of git deps that depend
// on one another, we only ever do preparation for one instance
// of a given git dep along the chain of installations.
@@ -254,8 +259,11 @@ class GitFetcher extends Fetcher {
resolved: this.resolved,
integrity: null, // it'll always be different, if we have one
}).extract(tmp).then(() => handler(`${tmp}${this.spec.gitSubdir || ''}`), er => {
- // fall back to ssh download if tarball fails
- if (er.constructor.name.match(/^Http/)) {
+ // fall back to clone if the tarball download fails due to an
+ // HTTP error or if the response is not a valid tarball (e.g.
+ // a hosted provider returning an HTML sign-in page with 200)
+ if ((typeof er.statusCode === 'number' && er.statusCode >= 400) ||
+ /^TAR_/.test(er.code)) {
return this.#clone(handler, false)
} else {
throw er
diff --git a/deps/npm/node_modules/pacote/lib/util/add-git-sha.js b/deps/npm/node_modules/pacote/lib/util/add-git-sha.js
index 8518bff9e20..39893b47598 100644
--- a/deps/npm/node_modules/pacote/lib/util/add-git-sha.js
+++ b/deps/npm/node_modules/pacote/lib/util/add-git-sha.js
@@ -3,7 +3,7 @@ const addGitSha = (spec, sha) => {
if (spec.hosted) {
const h = spec.hosted
const opt = { noCommittish: true }
- const base = h.https && h.auth ? h.https(opt) : h.shortcut(opt)
+ const base = h.https && (h.auth || h.default === 'https') ? h.https(opt) : h.shortcut(opt)
return `${base}#${sha}`
} else {
diff --git a/deps/npm/node_modules/pacote/package.json b/deps/npm/node_modules/pacote/package.json
index ee9bea58fc0..2e544354ef8 100644
--- a/deps/npm/node_modules/pacote/package.json
+++ b/deps/npm/node_modules/pacote/package.json
@@ -1,6 +1,6 @@
{
"name": "pacote",
- "version": "21.5.1",
+ "version": "22.0.0",
"description": "JavaScript package downloader",
"author": "GitHub Inc.",
"bin": {
@@ -27,9 +27,9 @@
},
"devDependencies": {
"@npmcli/arborist": "^9.0.2",
- "@npmcli/eslint-config": "^6.0.0",
+ "@npmcli/eslint-config": "^7.0.0",
"@npmcli/template-oss": "5.1.0",
- "hosted-git-info": "^9.0.0",
+ "hosted-git-info": "^10.1.1",
"mutate-fs": "^2.1.1",
"nock": "^13.2.4",
"npm-registry-mock": "^1.3.2",
@@ -47,25 +47,25 @@
],
"dependencies": {
"@gar/promise-retry": "^1.0.0",
- "@npmcli/git": "^7.0.0",
- "@npmcli/installed-package-contents": "^4.0.0",
- "@npmcli/package-json": "^7.0.0",
- "@npmcli/promise-spawn": "^9.0.0",
- "@npmcli/run-script": "^10.0.0",
- "cacache": "^20.0.0",
+ "@npmcli/git": "^8.0.0",
+ "@npmcli/installed-package-contents": "^5.0.0",
+ "@npmcli/package-json": "^8.0.0",
+ "@npmcli/promise-spawn": "^10.0.0",
+ "@npmcli/run-script": "^11.0.0",
+ "cacache": "^21.0.1",
"fs-minipass": "^3.0.0",
"minipass": "^7.0.2",
- "npm-package-arg": "^13.0.0",
- "npm-packlist": "^10.0.1",
- "npm-pick-manifest": "^11.0.1",
- "npm-registry-fetch": "^19.0.0",
- "proc-log": "^6.0.0",
- "sigstore": "^4.0.0",
- "ssri": "^13.0.0",
+ "npm-package-arg": "^14.0.0",
+ "npm-packlist": "^11.2.0",
+ "npm-pick-manifest": "^12.0.0",
+ "npm-registry-fetch": "^20.0.1",
+ "proc-log": "^7.0.0",
+ "sigstore": "^5.0.0",
+ "ssri": "^14.0.0",
"tar": "^7.4.3"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"repository": {
"type": "git",
@@ -75,6 +75,7 @@
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
"version": "5.1.0",
"windowsCI": false,
- "publish": "true"
+ "publish": "true",
+ "updateNpm": false
}
}
diff --git a/deps/npm/node_modules/parse-conflict-json/package.json b/deps/npm/node_modules/parse-conflict-json/package.json
index 1d4bc102169..9da656e103c 100644
--- a/deps/npm/node_modules/parse-conflict-json/package.json
+++ b/deps/npm/node_modules/parse-conflict-json/package.json
@@ -1,6 +1,6 @@
{
"name": "parse-conflict-json",
- "version": "5.0.1",
+ "version": "6.0.0",
"description": "Parse a JSON string that has git merge conflicts, resolving if possible",
"author": "GitHub Inc.",
"license": "ISC",
@@ -23,12 +23,12 @@
]
},
"devDependencies": {
- "@npmcli/eslint-config": "^5.0.0",
- "@npmcli/template-oss": "4.27.1",
+ "@npmcli/eslint-config": "^6.0.0",
+ "@npmcli/template-oss": "5.1.0",
"tap": "^16.0.1"
},
"dependencies": {
- "json-parse-even-better-errors": "^5.0.0",
+ "json-parse-even-better-errors": "^6.0.0",
"just-diff": "^6.0.0",
"just-diff-apply": "^5.2.0"
},
@@ -41,11 +41,11 @@
"lib/"
],
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.27.1",
+ "version": "5.1.0",
"publish": true
}
}
diff --git a/deps/npm/node_modules/proc-log/package.json b/deps/npm/node_modules/proc-log/package.json
index 556697d71ed..1d298804641 100644
--- a/deps/npm/node_modules/proc-log/package.json
+++ b/deps/npm/node_modules/proc-log/package.json
@@ -1,6 +1,6 @@
{
"name": "proc-log",
- "version": "6.1.0",
+ "version": "7.0.0",
"files": [
"bin/",
"lib/"
@@ -26,15 +26,15 @@
},
"devDependencies": {
"@npmcli/eslint-config": "^6.0.0",
- "@npmcli/template-oss": "4.28.1",
+ "@npmcli/template-oss": "5.0.0",
"tap": "^16.0.1"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.28.1",
+ "version": "5.0.0",
"publish": true
},
"tap": {
diff --git a/deps/npm/node_modules/promzard/package.json b/deps/npm/node_modules/promzard/package.json
index 38fec6423f7..85081356fa9 100644
--- a/deps/npm/node_modules/promzard/package.json
+++ b/deps/npm/node_modules/promzard/package.json
@@ -2,17 +2,17 @@
"author": "GitHub Inc.",
"name": "promzard",
"description": "prompting wizardly",
- "version": "3.0.1",
+ "version": "4.0.0",
"repository": {
"url": "git+https://github.com/npm/promzard.git",
"type": "git"
},
"dependencies": {
- "read": "^5.0.0"
+ "read": "^6.0.0"
},
"devDependencies": {
- "@npmcli/eslint-config": "^5.0.0",
- "@npmcli/template-oss": "4.27.1",
+ "@npmcli/eslint-config": "^6.0.0",
+ "@npmcli/template-oss": "5.1.0",
"tap": "^16.3.0"
},
"main": "lib/index.js",
@@ -32,11 +32,11 @@
"lib/"
],
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.27.1",
+ "version": "5.1.0",
"publish": true
},
"tap": {
diff --git a/deps/npm/node_modules/proxy-agent-negotiate/dist/index.js b/deps/npm/node_modules/proxy-agent-negotiate/dist/index.js
new file mode 100644
index 00000000000..a6f7219533f
--- /dev/null
+++ b/deps/npm/node_modules/proxy-agent-negotiate/dist/index.js
@@ -0,0 +1,35 @@
+export function createNegotiateAuth() {
+ return async ({ response, scheme }) => {
+ if (scheme.toLowerCase() !== 'negotiate') {
+ throw new Error(`Expected Negotiate scheme but got "${scheme}"`);
+ }
+ let kerberos;
+ try {
+ kerberos = await import('kerberos');
+ }
+ catch {
+ throw new Error('The "kerberos" package is required for Negotiate proxy authentication. ' +
+ 'Install it with: npm install kerberos');
+ }
+ const proxyAuthenticate = response.headers['proxy-authenticate'] || '';
+ const challengeHeader = Array.isArray(proxyAuthenticate)
+ ? proxyAuthenticate[0]
+ : proxyAuthenticate;
+ const serverToken = typeof challengeHeader === 'string' && challengeHeader.includes(' ')
+ ? challengeHeader.split(' ').slice(1).join(' ')
+ : undefined;
+ const client = await kerberos.initializeClient('HTTP@proxy', {
+ mechOID: kerberos.GSS_MECH_OID_SPNEGO,
+ });
+ const token = await client.step(serverToken || '');
+ if (!token) {
+ throw new Error('Kerberos client.step() returned no token');
+ }
+ return {
+ headers: {
+ 'Proxy-Authorization': `Negotiate ${token}`,
+ },
+ };
+ };
+}
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/deps/npm/node_modules/proxy-agent-negotiate/package.json b/deps/npm/node_modules/proxy-agent-negotiate/package.json
new file mode 100644
index 00000000000..2e5697a36a8
--- /dev/null
+++ b/deps/npm/node_modules/proxy-agent-negotiate/package.json
@@ -0,0 +1,47 @@
+{
+ "name": "proxy-agent-negotiate",
+ "version": "1.1.0",
+ "type": "module",
+ "description": "Negotiate/SPNEGO proxy authentication for proxy-agents",
+ "exports": {
+ "types": "./dist/index.d.ts",
+ "default": "./dist/index.js"
+ },
+ "files": [
+ "dist"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/TooTallNate/proxy-agents.git",
+ "directory": "packages/negotiate"
+ },
+ "keywords": [
+ "proxy",
+ "negotiate",
+ "kerberos",
+ "spnego",
+ "authentication"
+ ],
+ "author": "Nathan Rajlich <nathan@tootallnate.net> (http://n8.io/)",
+ "license": "MIT",
+ "devDependencies": {
+ "@types/node": "^22.13.0",
+ "typescript": "^5.1.6",
+ "tsconfig": "0.0.0"
+ },
+ "engines": {
+ "node": ">= 20"
+ },
+ "peerDependencies": {
+ "kerberos": "^2.0.0"
+ },
+ "peerDependenciesMeta": {
+ "kerberos": {
+ "optional": true
+ }
+ },
+ "scripts": {
+ "build": "tsc",
+ "pack": "node ../../scripts/pack.mjs"
+ }
+}
\ No newline at end of file
diff --git a/deps/npm/node_modules/read/package.json b/deps/npm/node_modules/read/package.json
index 723bcfb9656..80049fa3ab9 100644
--- a/deps/npm/node_modules/read/package.json
+++ b/deps/npm/node_modules/read/package.json
@@ -1,6 +1,6 @@
{
"name": "read",
- "version": "5.0.1",
+ "version": "6.0.0",
"exports": {
"./package.json": "./package.json",
".": {
@@ -22,23 +22,19 @@
}
},
"dependencies": {
- "mute-stream": "^3.0.0"
+ "mute-stream": "^4.0.0"
},
"devDependencies": {
- "@npmcli/eslint-config": "^5.0.0",
- "@npmcli/template-oss": "4.27.1",
+ "@npmcli/eslint-config": "^6.0.0",
+ "@npmcli/template-oss": "5.1.0",
"@types/mute-stream": "^0.0.4",
- "@types/tap": "^15.0.11",
"@typescript-eslint/parser": "^8.0.1",
- "c8": "^10.1.2",
"eslint-import-resolver-typescript": "^4.3.2",
- "tap": "^16.3.9",
- "ts-node": "^10.9.1",
- "tshy": "^3.0.2",
- "typescript": "^5.2.2"
+ "tshy": "^4.1.1",
+ "typescript": "^6.0.3"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"author": "GitHub Inc.",
"description": "read(1) for node programs",
@@ -49,38 +45,27 @@
"license": "ISC",
"scripts": {
"prepare": "tshy",
- "pretest": "npm run prepare",
- "presnap": "npm run prepare",
- "test": "c8 tap",
+ "test": "node --experimental-strip-types --no-warnings --test './test/*.ts'",
+ "snap": "node --experimental-strip-types --no-warnings --test --test-update-snapshots './test/*.ts'",
+ "test:cover": "node --experimental-strip-types --no-warnings --test --experimental-test-coverage './test/*.ts'",
"lint": "npm run eslint",
"postlint": "template-oss-check",
"template-oss-apply": "template-oss-apply --force",
"lintfix": "npm run eslint -- --fix",
- "snap": "c8 tap",
"posttest": "npm run lint",
"eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\""
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.27.1",
+ "version": "5.1.0",
"publish": true,
- "typescript": true
+ "typescript": true,
+ "updateNpm": false,
+ "testRunner": "node:test",
+ "content": "./scripts/template-oss"
},
"main": "./dist/commonjs/read.js",
"types": "./dist/commonjs/read.d.ts",
- "tap": {
- "coverage": false,
- "node-arg": [
- "--no-warnings",
- "--loader",
- "ts-node/esm"
- ],
- "ts": false,
- "nyc-arg": [
- "--exclude",
- "tap-snapshots/**"
- ]
- },
"files": [
"dist/"
],
diff --git a/deps/npm/node_modules/sigstore/package.json b/deps/npm/node_modules/sigstore/package.json
index e0acea6d962..c32bfefa3e2 100644
--- a/deps/npm/node_modules/sigstore/package.json
+++ b/deps/npm/node_modules/sigstore/package.json
@@ -1,6 +1,6 @@
{
"name": "sigstore",
- "version": "4.1.1",
+ "version": "5.0.0",
"description": "code-signing for npm packages",
"main": "dist/index.js",
"types": "dist/index.d.ts",
@@ -27,21 +27,21 @@
"provenance": true
},
"devDependencies": {
- "@sigstore/rekor-types": "^4.0.0",
"@sigstore/jest": "^0.0.0",
- "@sigstore/mock": "^0.12.1",
- "@tufjs/repo-mock": "^4.0.1",
+ "@sigstore/mock": "^0.13.0",
+ "@sigstore/rekor-types": "^5.0.0",
+ "@tufjs/repo-mock": "^5.0.0",
"@types/make-fetch-happen": "^10.0.4"
},
"dependencies": {
- "@sigstore/bundle": "^4.0.0",
- "@sigstore/core": "^3.2.1",
+ "@sigstore/bundle": "^5.0.0",
+ "@sigstore/core": "^4.0.0",
"@sigstore/protobuf-specs": "^0.5.0",
- "@sigstore/sign": "^4.1.1",
- "@sigstore/tuf": "^4.0.2",
- "@sigstore/verify": "^3.1.1"
+ "@sigstore/sign": "^5.0.0",
+ "@sigstore/tuf": "^5.0.0",
+ "@sigstore/verify": "^4.0.0"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
}
}
diff --git a/deps/npm/node_modules/socks-proxy-agent/dist/index.js b/deps/npm/node_modules/socks-proxy-agent/dist/index.js
index 15e06e8f431..4c74bea208b 100644
--- a/deps/npm/node_modules/socks-proxy-agent/dist/index.js
+++ b/deps/npm/node_modules/socks-proxy-agent/dist/index.js
@@ -1,40 +1,11 @@
-"use strict";
-var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
- if (k2 === undefined) k2 = k;
- var desc = Object.getOwnPropertyDescriptor(m, k);
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
- desc = { enumerable: true, get: function() { return m[k]; } };
- }
- Object.defineProperty(o, k2, desc);
-}) : (function(o, m, k, k2) {
- if (k2 === undefined) k2 = k;
- o[k2] = m[k];
-}));
-var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
- Object.defineProperty(o, "default", { enumerable: true, value: v });
-}) : function(o, v) {
- o["default"] = v;
-});
-var __importStar = (this && this.__importStar) || function (mod) {
- if (mod && mod.__esModule) return mod;
- var result = {};
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
- __setModuleDefault(result, mod);
- return result;
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.SocksProxyAgent = void 0;
-const socks_1 = require("socks");
-const agent_base_1 = require("agent-base");
-const debug_1 = __importDefault(require("debug"));
-const dns = __importStar(require("dns"));
-const net = __importStar(require("net"));
-const tls = __importStar(require("tls"));
-const url_1 = require("url");
-const debug = (0, debug_1.default)('socks-proxy-agent');
+import { SocksClient } from 'socks';
+import { Agent } from 'agent-base';
+import createDebug from 'debug';
+import * as dns from 'dns';
+import * as net from 'net';
+import * as tls from 'tls';
+import { URL } from 'url';
+const debug = createDebug('socks-proxy-agent');
const setServernameFromNonIpHost = (options) => {
if (options.servername === undefined &&
options.host &&
@@ -97,13 +68,14 @@ function parseSocksURL(url) {
}
return { lookup, proxy };
}
-class SocksProxyAgent extends agent_base_1.Agent {
+export class SocksProxyAgent extends Agent {
constructor(uri, opts) {
super(opts);
- const url = typeof uri === 'string' ? new url_1.URL(uri) : uri;
+ const url = typeof uri === 'string' ? new URL(uri) : uri;
const { proxy, lookup } = parseSocksURL(url);
this.shouldLookup = lookup;
this.proxy = proxy;
+ this.proxyUrl = url.href;
this.timeout = opts?.timeout ?? null;
this.socketOptions = opts?.socketOptions ?? null;
}
@@ -122,12 +94,14 @@ class SocksProxyAgent extends agent_base_1.Agent {
// Client-side DNS resolution for "4" and "5" socks proxy versions.
host = await new Promise((resolve, reject) => {
// Use the request's custom lookup, if one was configured:
- lookupFn(host, {}, (err, res) => {
+ lookupFn(host, {}, (err, address) => {
if (err) {
reject(err);
}
else {
- resolve(res);
+ resolve(typeof address === 'string'
+ ? address
+ : address[0].address);
}
});
});
@@ -151,8 +125,9 @@ class SocksProxyAgent extends agent_base_1.Agent {
tlsSocket.destroy();
};
debug('Creating socks proxy connection: %o', socksOpts);
- const { socket } = await socks_1.SocksClient.createConnection(socksOpts);
+ const { socket } = await SocksClient.createConnection(socksOpts);
debug('Successfully created socks proxy connection');
+ req.emit('proxy', { proxy: this.proxyUrl, socket });
if (timeout !== null) {
socket.setTimeout(timeout);
socket.on('timeout', () => cleanup());
@@ -181,7 +156,6 @@ SocksProxyAgent.protocols = [
'socks5',
'socks5h',
];
-exports.SocksProxyAgent = SocksProxyAgent;
function omit(obj, ...keys) {
const ret = {};
let key;
diff --git a/deps/npm/node_modules/socks-proxy-agent/node_modules/agent-base/LICENSE b/deps/npm/node_modules/socks-proxy-agent/node_modules/agent-base/LICENSE
new file mode 100644
index 00000000000..008728cb518
--- /dev/null
+++ b/deps/npm/node_modules/socks-proxy-agent/node_modules/agent-base/LICENSE
@@ -0,0 +1,22 @@
+(The MIT License)
+
+Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/deps/npm/node_modules/socks-proxy-agent/node_modules/agent-base/dist/helpers.js b/deps/npm/node_modules/socks-proxy-agent/node_modules/agent-base/dist/helpers.js
new file mode 100644
index 00000000000..42c6ed2a0fe
--- /dev/null
+++ b/deps/npm/node_modules/socks-proxy-agent/node_modules/agent-base/dist/helpers.js
@@ -0,0 +1,37 @@
+import * as http from 'http';
+import * as https from 'https';
+export async function toBuffer(stream) {
+ let length = 0;
+ const chunks = [];
+ for await (const chunk of stream) {
+ length += chunk.length;
+ chunks.push(chunk);
+ }
+ return Buffer.concat(chunks, length);
+}
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export async function json(stream) {
+ const buf = await toBuffer(stream);
+ const str = buf.toString('utf8');
+ try {
+ return JSON.parse(str);
+ }
+ catch (_err) {
+ const err = _err;
+ err.message += ` (input: ${str})`;
+ throw err;
+ }
+}
+export function req(url, opts = {}) {
+ const href = typeof url === 'string' ? url : url.href;
+ const req = (href.startsWith('https:') ? https : http).request(url, opts);
+ const promise = new Promise((resolve, reject) => {
+ req
+ .once('response', resolve)
+ .once('error', reject)
+ .end();
+ });
+ req.then = promise.then.bind(promise);
+ return req;
+}
+//# sourceMappingURL=helpers.js.map
\ No newline at end of file
diff --git a/deps/npm/node_modules/socks-proxy-agent/node_modules/agent-base/dist/index.js b/deps/npm/node_modules/socks-proxy-agent/node_modules/agent-base/dist/index.js
new file mode 100644
index 00000000000..15aa6e9d745
--- /dev/null
+++ b/deps/npm/node_modules/socks-proxy-agent/node_modules/agent-base/dist/index.js
@@ -0,0 +1,146 @@
+import * as net from 'net';
+import * as http from 'http';
+import { Agent as HttpsAgent } from 'https';
+export * from './helpers.js';
+const INTERNAL = Symbol('AgentBaseInternalState');
+export class Agent extends http.Agent {
+ constructor(opts) {
+ super(opts);
+ this[INTERNAL] = {};
+ }
+ /**
+ * Determine whether this is an `http` or `https` request.
+ */
+ isSecureEndpoint(options) {
+ if (options) {
+ // First check the `secureEndpoint` property explicitly, since this
+ // means that a parent `Agent` is "passing through" to this instance.
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ if (typeof options.secureEndpoint === 'boolean') {
+ return options.secureEndpoint;
+ }
+ // If no explicit `secure` endpoint, check if `protocol` property is
+ // set. This will usually be the case since using a full string URL
+ // or `URL` instance should be the most common usage.
+ if (typeof options.protocol === 'string') {
+ return options.protocol === 'https:';
+ }
+ }
+ // Finally, if no `protocol` property was set, then fall back to
+ // checking the stack trace of the current call stack, and try to
+ // detect the "https" module.
+ const { stack } = new Error();
+ if (typeof stack !== 'string')
+ return false;
+ return stack
+ .split('\n')
+ .some((l) => l.indexOf('(https.js:') !== -1 ||
+ l.indexOf('node:https:') !== -1);
+ }
+ // In order to support async signatures in `connect()` and Node's native
+ // connection pooling in `http.Agent`, the array of sockets for each origin
+ // has to be updated synchronously. This is so the length of the array is
+ // accurate when `addRequest()` is next called. We achieve this by creating a
+ // fake socket and adding it to `sockets[origin]` and incrementing
+ // `totalSocketCount`.
+ incrementSockets(name) {
+ // If `maxSockets` and `maxTotalSockets` are both Infinity then there is no
+ // need to create a fake socket because Node.js native connection pooling
+ // will never be invoked.
+ if (this.maxSockets === Infinity && this.maxTotalSockets === Infinity) {
+ return null;
+ }
+ // All instances of `sockets` are expected TypeScript errors. The
+ // alternative is to add it as a private property of this class but that
+ // will break TypeScript subclassing.
+ if (!this.sockets[name]) {
+ // @ts-expect-error `sockets` is readonly in `@types/node`
+ this.sockets[name] = [];
+ }
+ const fakeSocket = new net.Socket({ writable: false });
+ this.sockets[name].push(fakeSocket);
+ // @ts-expect-error `totalSocketCount` isn't defined in `@types/node`
+ this.totalSocketCount++;
+ return fakeSocket;
+ }
+ decrementSockets(name, socket) {
+ if (!this.sockets[name] || socket === null) {
+ return;
+ }
+ const sockets = this.sockets[name];
+ const index = sockets.indexOf(socket);
+ if (index !== -1) {
+ sockets.splice(index, 1);
+ // @ts-expect-error `totalSocketCount` isn't defined in `@types/node`
+ this.totalSocketCount--;
+ if (sockets.length === 0) {
+ // @ts-expect-error `sockets` is readonly in `@types/node`
+ delete this.sockets[name];
+ }
+ }
+ }
+ // In order to properly update the socket pool, we need to call `getName()` on
+ // the core `https.Agent` if it is a secureEndpoint.
+ getName(options) {
+ const secureEndpoint = this.isSecureEndpoint(options);
+ if (secureEndpoint) {
+ return HttpsAgent.prototype.getName.call(this, options);
+ }
+ return super.getName(options);
+ }
+ createSocket(req, options, cb) {
+ const connectOpts = {
+ ...options,
+ secureEndpoint: this.isSecureEndpoint(options),
+ };
+ const name = this.getName(connectOpts);
+ const fakeSocket = this.incrementSockets(name);
+ Promise.resolve()
+ .then(() => this.connect(req, connectOpts))
+ .then((socket) => {
+ this.decrementSockets(name, fakeSocket);
+ if (typeof socket
+ .addRequest === 'function') {
+ try {
+ return socket.addRequest(req, connectOpts);
+ }
+ catch (err) {
+ return cb(err);
+ }
+ }
+ this[INTERNAL].currentSocket = socket;
+ // @ts-expect-error `createSocket()` isn't defined in `@types/node`
+ super.createSocket(req, options, cb);
+ }, (err) => {
+ this.decrementSockets(name, fakeSocket);
+ cb(err);
+ });
+ }
+ createConnection() {
+ const socket = this[INTERNAL].currentSocket;
+ this[INTERNAL].currentSocket = undefined;
+ if (!socket) {
+ throw new Error('No socket was returned in the `connect()` function');
+ }
+ return socket;
+ }
+ get defaultPort() {
+ return (this[INTERNAL].defaultPort ??
+ (this.protocol === 'https:' ? 443 : 80));
+ }
+ set defaultPort(v) {
+ if (this[INTERNAL]) {
+ this[INTERNAL].defaultPort = v;
+ }
+ }
+ get protocol() {
+ return (this[INTERNAL].protocol ??
+ (this.isSecureEndpoint() ? 'https:' : 'http:'));
+ }
+ set protocol(v) {
+ if (this[INTERNAL]) {
+ this[INTERNAL].protocol = v;
+ }
+ }
+}
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/deps/npm/node_modules/socks-proxy-agent/node_modules/agent-base/package.json b/deps/npm/node_modules/socks-proxy-agent/node_modules/agent-base/package.json
new file mode 100644
index 00000000000..8ef80c2bb09
--- /dev/null
+++ b/deps/npm/node_modules/socks-proxy-agent/node_modules/agent-base/package.json
@@ -0,0 +1,46 @@
+{
+ "name": "agent-base",
+ "version": "9.0.0",
+ "type": "module",
+ "description": "Turn a function into an `http.Agent` instance",
+ "exports": {
+ "types": "./dist/index.d.ts",
+ "default": "./dist/index.js"
+ },
+ "files": [
+ "dist"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/TooTallNate/proxy-agents.git",
+ "directory": "packages/agent-base"
+ },
+ "keywords": [
+ "http",
+ "agent",
+ "base",
+ "barebones",
+ "https"
+ ],
+ "author": "Nathan Rajlich <nathan@tootallnate.net> (http://n8.io/)",
+ "license": "MIT",
+ "devDependencies": {
+ "@types/debug": "^4.1.7",
+ "@types/node": "^22.13.0",
+ "@types/semver": "^7.3.13",
+ "@types/ws": "^8.5.4",
+ "async-listen": "^3.0.0",
+ "typescript": "^5.1.6",
+ "ws": "^8.13.0",
+ "tsconfig": "0.0.0"
+ },
+ "engines": {
+ "node": ">= 20"
+ },
+ "scripts": {
+ "build": "tsc",
+ "test": "vitest",
+ "lint": "eslint . --ext .ts",
+ "pack": "node ../../scripts/pack.mjs"
+ }
+}
\ No newline at end of file
diff --git a/deps/npm/node_modules/socks-proxy-agent/package.json b/deps/npm/node_modules/socks-proxy-agent/package.json
index 0f330a73106..3f24cb9a538 100644
--- a/deps/npm/node_modules/socks-proxy-agent/package.json
+++ b/deps/npm/node_modules/socks-proxy-agent/package.json
@@ -1,9 +1,12 @@
{
"name": "socks-proxy-agent",
- "version": "8.0.5",
+ "version": "10.1.0",
+ "type": "module",
"description": "A SOCKS proxy `http.Agent` implementation for HTTP and HTTPS",
- "main": "./dist/index.js",
- "types": "./dist/index.d.ts",
+ "exports": {
+ "types": "./dist/index.d.ts",
+ "default": "./dist/index.js"
+ },
"files": [
"dist"
],
@@ -107,35 +110,32 @@
"socks5h"
],
"dependencies": {
- "agent-base": "^7.1.2",
"debug": "^4.3.4",
- "socks": "^2.8.3"
+ "socks": "^2.8.3",
+ "agent-base": "9.0.0"
},
"devDependencies": {
"@types/async-retry": "^1.4.5",
"@types/debug": "^4.1.7",
"@types/dns2": "^2.0.3",
- "@types/jest": "^29.5.1",
- "@types/node": "^14.18.45",
+ "@types/node": "^22.13.0",
"async-listen": "^3.0.0",
"async-retry": "^1.3.3",
"cacheable-lookup": "^6.1.0",
"dns2": "^2.1.0",
- "jest": "^29.5.0",
- "socksv5": "github:TooTallNate/socksv5#fix/dstSock-close-event",
- "ts-jest": "^29.1.0",
- "typescript": "^5.0.4",
- "proxy": "2.2.0",
+ "socksv5": "github:TooTallNate/socksv5#d937368b28e929396166d77a06d387a4a902bd51",
+ "typescript": "^5.1.6",
+ "proxy": "4.1.0",
"tsconfig": "0.0.0"
},
"engines": {
- "node": ">= 14"
+ "node": ">= 20"
},
"license": "MIT",
"scripts": {
"build": "tsc",
- "test": "jest --env node --verbose --bail test/test.ts",
- "test-e2e": "jest --env node --verbose --bail test/e2e.test.ts",
+ "test": "vitest --exclude test/e2e.test.ts",
+ "test-e2e": "vitest run test/e2e.test.ts",
"lint": "eslint . --ext .ts",
"pack": "node ../../scripts/pack.mjs"
}
diff --git a/deps/npm/node_modules/ssri/package.json b/deps/npm/node_modules/ssri/package.json
index d4769fc2907..c5126ce55ba 100644
--- a/deps/npm/node_modules/ssri/package.json
+++ b/deps/npm/node_modules/ssri/package.json
@@ -1,6 +1,6 @@
{
"name": "ssri",
- "version": "13.0.1",
+ "version": "14.0.0",
"description": "Standard Subresource Integrity library -- parses, serializes, generates, and verifies integrity metadata according to the SRI spec.",
"main": "lib/index.js",
"files": [
@@ -47,15 +47,15 @@
},
"devDependencies": {
"@npmcli/eslint-config": "^6.0.0",
- "@npmcli/template-oss": "4.28.1",
+ "@npmcli/template-oss": "5.0.0",
"benchmark": "^2.1.4"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.28.1",
+ "version": "5.0.0",
"publish": "true",
"allowPaths": [
"benchmarks/"
diff --git a/deps/npm/node_modules/tinyglobby/node_modules/picomatch/lib/parse.js b/deps/npm/node_modules/tinyglobby/node_modules/picomatch/lib/parse.js
index 57d994a8789..a85bb2d441e 100644
--- a/deps/npm/node_modules/tinyglobby/node_modules/picomatch/lib/parse.js
+++ b/deps/npm/node_modules/tinyglobby/node_modules/picomatch/lib/parse.js
@@ -230,7 +230,15 @@ const parseRepeatedExtglob = (pattern, requireEnd = true) => {
}
};
-const getStarExtglobSequenceOutput = pattern => {
+const buildCharClassStar = chars => {
+ const source = chars.length === 1
+ ? utils.escapeRegex(chars[0])
+ : `[${chars.map(ch => utils.escapeRegex(ch)).join('')}]`;
+
+ return `${source}*`;
+};
+
+const getStarExtglobSequenceChars = pattern => {
let index = 0;
const chars = [];
@@ -259,11 +267,7 @@ const getStarExtglobSequenceOutput = pattern => {
return;
}
- const source = chars.length === 1
- ? utils.escapeRegex(chars[0])
- : `[${chars.map(ch => utils.escapeRegex(ch)).join('')}]`;
-
- return `${source}*`;
+ return chars;
};
const repeatedExtglobRecursion = pattern => {
@@ -302,17 +306,43 @@ const analyzeRepeatedExtglob = (body, options) => {
}
}
+ // A repeated extglob is "risky" (prone to catastrophic backtracking) when a
+ // branch is itself a `*(...)` sequence, since that nests an unbounded quantifier
+ // inside the outer `+(...)`/`*(...)`. When *every* branch reduces to single
+ // characters we can emit one flat, ReDoS-safe character class that preserves the
+ // meaning of ALL branches (e.g. `+(*(a)|*(b))` -> `[ab]*`), rather than dropping
+ // every branch but the first.
+ const safeChars = [];
+ let sawStarSequence = false;
+ let combinable = true;
+
for (const branch of branches) {
- const safeOutput = getStarExtglobSequenceOutput(branch);
- if (safeOutput) {
- return { risky: true, safeOutput };
+ const chars = getStarExtglobSequenceChars(branch);
+ if (chars) {
+ sawStarSequence = true;
+ safeChars.push(...chars);
+ continue;
+ }
+
+ const literal = normalizeSimpleBranch(branch);
+ if (literal && literal.length === 1) {
+ safeChars.push(literal);
+ continue;
}
+ combinable = false;
+
if (repeatedExtglobRecursion(branch) > max) {
return { risky: true };
}
}
+ if (sawStarSequence) {
+ return combinable
+ ? { risky: true, safeOutput: buildCharClassStar([...new Set(safeChars)]) }
+ : { risky: true };
+ }
+
return { risky: false };
};
diff --git a/deps/npm/node_modules/tinyglobby/node_modules/picomatch/lib/picomatch.js b/deps/npm/node_modules/tinyglobby/node_modules/picomatch/lib/picomatch.js
index fbb8b1ca9f1..9c2bfd5ca67 100644
--- a/deps/npm/node_modules/tinyglobby/node_modules/picomatch/lib/picomatch.js
+++ b/deps/npm/node_modules/tinyglobby/node_modules/picomatch/lib/picomatch.js
@@ -20,6 +20,18 @@ const isObject = val => val && typeof val === 'object' && !Array.isArray(val);
* const isMatch = picomatch('*.!(*a)');
* console.log(isMatch('a.a')); //=> false
* console.log(isMatch('a.b')); //=> true
+ *
+ * // For environments without `node.js`, `picomatch/posix` provides you a dependency-free matcher, without automatic OS detection.
+ * const picomatch = require('picomatch/posix');
+ * // the same API, defaulting to posix paths
+ * const isMatch = picomatch('a/*');
+ * console.log(isMatch('a\\b')); //=> false
+ * console.log(isMatch('a/b')); //=> true
+ *
+ * // you can still configure the matcher function to accept windows paths
+ * const isMatch = picomatch('a/*', { options: windows });
+ * console.log(isMatch('a\\b')); //=> true
+ * console.log(isMatch('a/b')); //=> true
* ```
* @name picomatch
* @param {String|Array} `globs` One or more glob patterns.
@@ -157,9 +169,9 @@ picomatch.test = (input, regex, options, { glob, posix } = {}) => {
* @api public
*/
-picomatch.matchBase = (input, glob, options) => {
+picomatch.matchBase = (input, glob, options, posix = options && options.windows) => {
const regex = glob instanceof RegExp ? glob : picomatch.makeRe(glob, options);
- return regex.test(utils.basename(input));
+ return regex.test(utils.basename(input, { windows: posix }));
};
/**
diff --git a/deps/npm/node_modules/tinyglobby/node_modules/picomatch/package.json b/deps/npm/node_modules/tinyglobby/node_modules/picomatch/package.json
index 9151f1d8358..c8ebbaeb004 100644
--- a/deps/npm/node_modules/tinyglobby/node_modules/picomatch/package.json
+++ b/deps/npm/node_modules/tinyglobby/node_modules/picomatch/package.json
@@ -1,7 +1,7 @@
{
"name": "picomatch",
"description": "Blazing fast and accurate glob matcher written in JavaScript, with no dependencies and full support for standard and extended Bash glob features, including braces, extglobs, POSIX brackets, and regular expressions.",
- "version": "4.0.4",
+ "version": "4.0.5",
"homepage": "https://github.com/micromatch/picomatch",
"author": "Jon Schlinkert (https://github.com/jonschlinkert)",
"funding": "https://github.com/sponsors/jonschlinkert",
@@ -43,7 +43,8 @@
"reporter": [
"html",
"lcov",
- "text-summary"
+ "text-summary",
+ "cobertura"
]
},
"verb": {
diff --git a/deps/npm/node_modules/tuf-js/dist/fetcher.js b/deps/npm/node_modules/tuf-js/dist/fetcher.js
index 03c7260c8d1..dc6373d8288 100644
--- a/deps/npm/node_modules/tuf-js/dist/fetcher.js
+++ b/deps/npm/node_modules/tuf-js/dist/fetcher.js
@@ -6,10 +6,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.DefaultFetcher = exports.BaseFetcher = void 0;
const debug_1 = __importDefault(require("debug"));
const fs_1 = __importDefault(require("fs"));
-const make_fetch_happen_1 = __importDefault(require("make-fetch-happen"));
const util_1 = __importDefault(require("util"));
const error_1 = require("./error");
const tmpfile_1 = require("./utils/tmpfile");
+const promise_retry_1 = require("@gar/promise-retry");
const log = (0, debug_1.default)('tuf:fetch');
const USER_AGENT_HEADER = 'User-Agent';
class BaseFetcher {
@@ -24,16 +24,22 @@ class BaseFetcher {
const fileStream = fs_1.default.createWriteStream(tmpFile);
// Read the stream a chunk at a time so that we can check
// the length of the file as we go
+ const streamReader = reader.getReader();
try {
- for await (const chunk of reader) {
+ while (true) {
+ const { done, value: chunk } = await streamReader.read();
+ if (done) {
+ break;
+ }
numberOfBytesReceived += chunk.length;
if (numberOfBytesReceived > maxLength) {
throw new error_1.DownloadLengthMismatchError('Max length reached');
}
- await writeBufferToStream(fileStream, chunk);
+ await writeBufferToStream(fileStream, Buffer.from(chunk));
}
}
finally {
+ streamReader.releaseLock();
// Make sure we always close the stream
// eslint-disable-next-line @typescript-eslint/unbound-method
await util_1.default.promisify(fileStream.close).bind(fileStream)();
@@ -62,21 +68,54 @@ class DefaultFetcher extends BaseFetcher {
super();
this.userAgent = options.userAgent;
this.timeout = options.timeout;
- this.retry = options.retry;
+ // Map retry to OperationOptions
+ if (options.retry === true) {
+ this.retry = { forever: true };
+ }
+ else if (options.retry === false || options.retry === undefined) {
+ this.retry = undefined;
+ }
+ else if (typeof options.retry === 'number') {
+ if (options.retry < 0) {
+ throw new Error('Retry count must be non-negative number');
+ }
+ this.retry = { retries: options.retry };
+ }
+ else {
+ this.retry = options.retry;
+ }
}
async fetch(url) {
- log('GET %s', url);
- const response = await (0, make_fetch_happen_1.default)(url, {
- headers: {
- [USER_AGENT_HEADER]: this.userAgent || '',
- },
- timeout: this.timeout,
- retry: this.retry,
- });
- if (!response.ok || !response?.body) {
- throw new error_1.DownloadHTTPError('Failed to download', response.status);
- }
- return response.body;
+ const shouldRetry = this.retry !== undefined;
+ return (0, promise_retry_1.promiseRetry)(async (retry, number) => {
+ log('GET %s (attempt %d)', url, number);
+ let response;
+ try {
+ response = await fetch(url, {
+ headers: {
+ [USER_AGENT_HEADER]: this.userAgent || '',
+ },
+ signal: this.timeout
+ ? AbortSignal.timeout(this.timeout)
+ : undefined,
+ });
+ }
+ catch (error) {
+ const err = error instanceof Error ? error : new Error(String(error));
+ if (shouldRetry) {
+ return retry(err);
+ }
+ throw err;
+ }
+ if (!response.ok || !response.body) {
+ const err = new error_1.DownloadHTTPError('Failed to download', response.status);
+ if (shouldRetry && response.status >= 500 && response.status < 600) {
+ return retry(err);
+ }
+ throw err;
+ }
+ return response.body;
+ }, this.retry);
}
}
exports.DefaultFetcher = DefaultFetcher;
diff --git a/deps/npm/node_modules/tuf-js/dist/updater.js b/deps/npm/node_modules/tuf-js/dist/updater.js
index 3f8614d7d49..94a76581557 100644
--- a/deps/npm/node_modules/tuf-js/dist/updater.js
+++ b/deps/npm/node_modules/tuf-js/dist/updater.js
@@ -234,7 +234,7 @@ class Updater {
}
catch (error) {
if (!this.trustedSet.timestamp) {
- throw new ReferenceError('No timestamp metadata');
+ throw new ReferenceError('No timestamp metadata', { cause: error });
}
const snapshotMeta = this.trustedSet.timestamp.signed.snapshotMeta;
const maxLength = snapshotMeta.length || this.config.snapshotMaxLength;
@@ -268,7 +268,7 @@ class Updater {
catch (error) {
// Local 'role' does not exist or is invalid: update from remote
if (!this.trustedSet.snapshot) {
- throw new ReferenceError('No snapshot metadata');
+ throw new ReferenceError('No snapshot metadata', { cause: error });
}
const metaInfo = this.trustedSet.snapshot.signed.meta[`${role}.json`];
// TODO: use length for fetching
diff --git a/deps/npm/node_modules/tuf-js/package.json b/deps/npm/node_modules/tuf-js/package.json
index 30d7a95fa5f..d311a6a9f00 100644
--- a/deps/npm/node_modules/tuf-js/package.json
+++ b/deps/npm/node_modules/tuf-js/package.json
@@ -1,6 +1,6 @@
{
"name": "tuf-js",
- "version": "4.1.0",
+ "version": "6.0.0",
"description": "JavaScript implementation of The Update Framework (TUF)",
"main": "dist/index.js",
"types": "dist/index.d.ts",
@@ -28,16 +28,16 @@
},
"homepage": "https://github.com/theupdateframework/tuf-js/tree/main/packages/client#readme",
"devDependencies": {
- "@tufjs/repo-mock": "4.0.1",
- "@types/debug": "^4.1.12",
- "@types/make-fetch-happen": "^10.0.4"
+ "@tufjs/repo-mock": "5.0.0",
+ "@types/debug": "^4.1.13",
+ "@types/retry": "^0.12.5"
},
"dependencies": {
- "@tufjs/models": "4.1.0",
- "debug": "^4.4.3",
- "make-fetch-happen": "^15.0.1"
+ "@gar/promise-retry": "^1.0.3",
+ "@tufjs/models": "5.0.0",
+ "debug": "^4.4.3"
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
}
}
diff --git a/deps/npm/node_modules/validate-npm-package-name/package.json b/deps/npm/node_modules/validate-npm-package-name/package.json
index 754742cbf6f..25195871887 100644
--- a/deps/npm/node_modules/validate-npm-package-name/package.json
+++ b/deps/npm/node_modules/validate-npm-package-name/package.json
@@ -1,6 +1,6 @@
{
"name": "validate-npm-package-name",
- "version": "7.0.2",
+ "version": "8.0.0",
"description": "Give me a string and I'll tell you if it's a valid npm package name",
"main": "lib/",
"directories": {
@@ -8,7 +8,7 @@
},
"devDependencies": {
"@npmcli/eslint-config": "^6.0.0",
- "@npmcli/template-oss": "4.28.1"
+ "@npmcli/template-oss": "5.0.0"
},
"scripts": {
"builtin-fixture": "node -e \"console.log(JSON.stringify(require('node:module').builtinModules))\" > ./lib/builtin-modules.json",
@@ -47,11 +47,11 @@
"lib/"
],
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.28.1",
+ "version": "5.0.0",
"publish": true,
"testRunner": "node:test",
"latestCiVersion": 24
diff --git a/deps/npm/node_modules/which/package.json b/deps/npm/node_modules/which/package.json
index c6a4bf229fd..f65f91b7f8d 100644
--- a/deps/npm/node_modules/which/package.json
+++ b/deps/npm/node_modules/which/package.json
@@ -2,7 +2,7 @@
"author": "GitHub Inc.",
"name": "which",
"description": "Like which(1) unix command. Find the first instance of an executable in the PATH.",
- "version": "6.0.1",
+ "version": "7.0.0",
"repository": {
"type": "git",
"url": "git+https://github.com/npm/node-which.git"
@@ -17,7 +17,7 @@
},
"devDependencies": {
"@npmcli/eslint-config": "^6.0.0",
- "@npmcli/template-oss": "4.28.1",
+ "@npmcli/template-oss": "5.0.0",
"tap": "^16.3.0"
},
"scripts": {
@@ -42,11 +42,11 @@
]
},
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.28.1",
+ "version": "5.0.0",
"publish": "true"
}
}
diff --git a/deps/npm/node_modules/write-file-atomic/package.json b/deps/npm/node_modules/write-file-atomic/package.json
index da35aeec254..200ca040e3d 100644
--- a/deps/npm/node_modules/write-file-atomic/package.json
+++ b/deps/npm/node_modules/write-file-atomic/package.json
@@ -1,6 +1,6 @@
{
"name": "write-file-atomic",
- "version": "7.0.1",
+ "version": "8.0.0",
"description": "Write files in an atomic fashion w/configurable ownership",
"main": "./lib/index.js",
"scripts": {
@@ -32,7 +32,7 @@
},
"devDependencies": {
"@npmcli/eslint-config": "^6.0.0",
- "@npmcli/template-oss": "4.28.1",
+ "@npmcli/template-oss": "5.0.0",
"tap": "^16.0.1"
},
"files": [
@@ -40,12 +40,12 @@
"lib/"
],
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
"windowsCI": false,
- "version": "4.28.1",
+ "version": "5.0.0",
"publish": "true"
},
"tap": {
diff --git a/deps/npm/package.json b/deps/npm/package.json
index a67f3456955..c6631a7bf45 100644
--- a/deps/npm/package.json
+++ b/deps/npm/package.json
@@ -1,5 +1,5 @@
{
- "version": "11.19.1",
+ "version": "12.1.0",
"name": "npm",
"description": "a package manager for JavaScript",
"workspaces": [
@@ -32,10 +32,6 @@
"bugs": {
"url": "https://github.com/npm/cli/issues"
},
- "directories": {
- "doc": "./doc",
- "man": "./man"
- },
"main": "./index.js",
"bin": {
"npm": "bin/npm-cli.js",
@@ -52,76 +48,80 @@
},
"dependencies": {
"@isaacs/string-locale-compare": "^1.1.0",
- "@npmcli/arborist": "^9.9.1",
- "@npmcli/config": "^10.12.0",
- "@npmcli/fs": "^5.0.0",
- "@npmcli/map-workspaces": "^5.0.3",
- "@npmcli/metavuln-calculator": "^9.0.3",
- "@npmcli/package-json": "^7.0.5",
- "@npmcli/promise-spawn": "^9.0.1",
- "@npmcli/redact": "^4.0.0",
- "@npmcli/run-script": "^10.0.4",
- "@sigstore/tuf": "^4.0.2",
- "abbrev": "^4.0.0",
+ "@npmcli/arborist": "^10.0.3",
+ "@npmcli/config": "^11.1.0",
+ "@npmcli/fs": "^6.0.0",
+ "@npmcli/git": "^8.0.0",
+ "@npmcli/map-workspaces": "^6.0.0",
+ "@npmcli/metavuln-calculator": "^10.0.0",
+ "@npmcli/package-json": "^8.0.0",
+ "@npmcli/promise-spawn": "^10.0.0",
+ "@npmcli/redact": "^5.0.0",
+ "@npmcli/run-script": "^11.0.0",
+ "@sigstore/tuf": "^5.0.0",
+ "abbrev": "^5.0.0",
"archy": "~1.0.0",
- "cacache": "^20.0.4",
+ "bin-links": "^7.0.0",
+ "cacache": "^21.0.1",
"chalk": "^5.6.2",
"ci-info": "^4.4.0",
+ "diff": "^8.0.2",
"fastest-levenshtein": "^1.0.16",
"fs-minipass": "^3.0.3",
"glob": "^13.0.6",
"graceful-fs": "^4.2.11",
- "hosted-git-info": "^9.0.3",
- "ini": "^6.0.0",
- "init-package-json": "^8.2.5",
- "is-cidr": "^6.0.4",
- "json-parse-even-better-errors": "^5.0.0",
- "libnpmaccess": "^10.0.3",
- "libnpmdiff": "^8.1.12",
- "libnpmexec": "^10.3.2",
- "libnpmfund": "^7.0.26",
- "libnpmorg": "^8.0.1",
- "libnpmpack": "^9.1.13",
- "libnpmpublish": "^11.2.0",
- "libnpmsearch": "^9.0.1",
- "libnpmteam": "^8.0.2",
- "libnpmversion": "^8.0.4",
- "make-fetch-happen": "^15.0.6",
+ "hosted-git-info": "^10.1.1",
+ "ini": "^7.0.0",
+ "init-package-json": "^9.0.0",
+ "is-cidr": "^7.0.0",
+ "json-parse-even-better-errors": "^6.0.0",
+ "libnpmaccess": "^11.0.0",
+ "libnpmdiff": "^9.0.3",
+ "libnpmexec": "^11.0.3",
+ "libnpmfund": "^8.0.3",
+ "libnpmorg": "^9.0.0",
+ "libnpmpack": "^10.0.3",
+ "libnpmpublish": "^12.0.1",
+ "libnpmsearch": "^10.0.0",
+ "libnpmteam": "^9.0.0",
+ "libnpmversion": "^9.0.0",
+ "make-fetch-happen": "^16.0.1",
"minimatch": "^10.2.5",
"minipass": "^7.1.3",
"minipass-pipeline": "^1.2.4",
"ms": "^2.1.2",
- "node-gyp": "^12.4.0",
- "nopt": "^9.0.0",
- "npm-audit-report": "^7.0.0",
- "npm-install-checks": "^8.0.0",
- "npm-package-arg": "^13.0.2",
- "npm-pick-manifest": "^11.0.3",
- "npm-profile": "^12.0.2",
- "npm-registry-fetch": "^19.1.1",
- "npm-user-validate": "^4.0.0",
+ "node-gyp": "^13.0.0",
+ "nopt": "^10.0.1",
+ "npm-audit-report": "^8.0.0",
+ "npm-install-checks": "^9.0.0",
+ "npm-package-arg": "^14.0.0",
+ "npm-pick-manifest": "^12.0.0",
+ "npm-profile": "^13.0.1",
+ "npm-registry-fetch": "^20.0.1",
+ "npm-user-validate": "^5.0.0",
"p-map": "^7.0.4",
- "pacote": "^21.5.1",
- "parse-conflict-json": "^5.0.1",
- "proc-log": "^6.1.0",
+ "pacote": "^22.0.0",
+ "parse-conflict-json": "^6.0.0",
+ "proc-log": "^7.0.0",
"qrcode-terminal": "^0.12.0",
- "read": "^5.0.1",
+ "read": "^6.0.0",
"semver": "^7.8.5",
"spdx-expression-parse": "^4.0.0",
- "ssri": "^13.0.1",
+ "ssri": "^14.0.0",
"supports-color": "^10.2.2",
"tar": "^7.5.22",
"text-table": "~0.2.0",
"tiny-relative-date": "^2.0.2",
"treeverse": "^3.0.0",
- "validate-npm-package-name": "^7.0.2",
- "which": "^6.0.1"
+ "validate-npm-package-name": "^8.0.0",
+ "which": "^7.0.0"
},
"bundleDependencies": [
"@isaacs/string-locale-compare",
"@npmcli/arborist",
"@npmcli/config",
"@npmcli/fs",
+ "@npmcli/git",
"@npmcli/map-workspaces",
"@npmcli/metavuln-calculator",
"@npmcli/package-json",
@@ -131,9 +131,11 @@
"@sigstore/tuf",
"abbrev",
"archy",
+ "bin-links",
"cacache",
"chalk",
"ci-info",
+ "diff",
"fastest-levenshtein",
"fs-minipass",
"glob",
@@ -187,18 +189,20 @@
"devDependencies": {
"@npmcli/docs": "^1.0.0",
"@npmcli/eslint-config": "^5.1.0",
- "@npmcli/git": "^7.0.2",
+ "@npmcli/installed-package-contents": "^5.0.0",
"@npmcli/mock-globals": "^1.0.0",
"@npmcli/mock-registry": "^1.0.0",
- "@npmcli/template-oss": "4.29.0",
- "@tufjs/repo-mock": "^4.0.0",
+ "@npmcli/name-from-folder": "^5.0.0",
+ "@npmcli/node-gyp": "^6.0.0",
+ "@npmcli/template-oss": "5.1.1",
+ "@tufjs/repo-mock": "^5.0.0",
"ajv": "^8.12.0",
"ajv-formats": "^3.0.1",
"ajv-formats-draft2019": "^1.6.1",
"cli-table3": "^0.6.4",
"diff": "^8.0.4",
- "nock": "^13.4.0",
- "npm-packlist": "^10.0.4",
+ "nock": "^14.0.0",
+ "npm-packlist": "^11.3.0",
"remark": "^15.0.1",
"remark-gfm": "^4.0.1",
"remark-github": "^12.0.0",
@@ -229,6 +233,10 @@
"test-env": [
"LC_ALL=sk"
],
+ "node-arg": [
+ "--require",
+ "./scripts/disable-agent-for-tests.js"
+ ],
"timeout": 600,
"nyc-arg": [
"--exclude",
@@ -248,12 +256,12 @@
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
- "version": "4.29.0",
+ "version": "5.1.1",
"content": "./scripts/template-oss/root.js",
"updateNpm": false
},
"license": "Artistic-2.0",
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
}
}
diff --git a/deps/npm/tap-snapshots/test/lib/cli/exit-handler.js.test.cjs b/deps/npm/tap-snapshots/test/lib/cli/exit-handler.js.test.cjs
index fd68eea5779..29865aadf56 100644
--- a/deps/npm/tap-snapshots/test/lib/cli/exit-handler.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/cli/exit-handler.js.test.cjs
@@ -6,7 +6,6 @@
*/
'use strict'
exports[`test/lib/cli/exit-handler.js TAP handles unknown error with logs and debug file > debug file contents 1`] = `
-XX timing npm:load:whichnode Completed in {TIME}ms
XX silly config load:file:{CWD}/npmrc
XX silly config load:file:{CWD}/prefix/.npmrc
XX silly config load:file:{CWD}/home/.npmrc
@@ -36,7 +35,6 @@ XX error A complete log of this run can be found in: {CWD}/cache/_logs/{DATE}-de
`
exports[`test/lib/cli/exit-handler.js TAP handles unknown error with logs and debug file > logs 1`] = `
-timing npm:load:whichnode Completed in {TIME}ms
silly config load:file:{CWD}/npmrc
silly config load:file:{CWD}/prefix/.npmrc
silly config load:file:{CWD}/home/.npmrc
diff --git a/deps/npm/tap-snapshots/test/lib/commands/completion.js.test.cjs b/deps/npm/tap-snapshots/test/lib/commands/completion.js.test.cjs
index 12f1c803cd7..c2d4abc9d4c 100644
--- a/deps/npm/tap-snapshots/test/lib/commands/completion.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/commands/completion.js.test.cjs
@@ -61,12 +61,10 @@ exports[`test/lib/commands/completion.js TAP completion multiple command names >
Array [
String(
access
- adduser
approve-scripts
audit
author
add
- add-user
),
]
`
diff --git a/deps/npm/tap-snapshots/test/lib/commands/config.js.test.cjs b/deps/npm/tap-snapshots/test/lib/commands/config.js.test.cjs
index 84a67b23091..c92e2d942e3 100644
--- a/deps/npm/tap-snapshots/test/lib/commands/config.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/commands/config.js.test.cjs
@@ -10,16 +10,16 @@ exports[`test/lib/commands/config.js TAP config list --json > output matches sna
"cache": "{CACHE}",
"color": {COLOR},
"json": true,
- "projectloaded": "yes",
- "userloaded": "yes",
- "globalloaded": "yes",
+ "tag": "from-project",
+ "init-author-name": "from-user",
+ "init-license": "from-global",
"access": null,
"all": false,
"allow-same-version": false,
"allow-directory": "all",
"allow-file": "all",
- "allow-git": "all",
- "allow-remote": "all",
+ "allow-git": "none",
+ "allow-remote": "none",
"allow-scripts": [
""
],
@@ -58,6 +58,7 @@ exports[`test/lib/commands/config.js TAP config list --json > output matches sna
"expect-result-count": null,
"expect-results": null,
"expires": null,
+ "extension-file": null,
"fetch-retries": 2,
"fetch-retry-factor": 10,
"fetch-retry-maxtimeout": 60000,
@@ -71,19 +72,19 @@ exports[`test/lib/commands/config.js TAP config list --json > output matches sna
"git-tag-version": true,
"global": false,
"globalconfig": "{CWD}/global/etc/npmrc",
+ "global-ignore-file": "{CWD}/global/etc/npmignore",
"global-style": false,
"heading": "npm",
"https-proxy": null,
"if-present": false,
+ "ignore-extension": false,
"ignore-scripts": false,
"include": [],
"include-staged": false,
"include-workspace-root": false,
"include-attestations": false,
"init-author-email": "",
- "init-author-name": "",
"init-author-url": "",
- "init-license": "ISC",
"init-module": "{CWD}/home/.npm-init.js",
"init-type": "commonjs",
"init-version": "1.0.0",
@@ -91,7 +92,7 @@ exports[`test/lib/commands/config.js TAP config list --json > output matches sna
"init.author.email": "",
"init.author.name": "",
"init.author.url": "",
- "init.license": "ISC",
+ "init.license": "",
"init.module": "{CWD}/home/.npm-init.js",
"init.version": "1.0.0",
"install-links": false,
@@ -131,6 +132,12 @@ exports[`test/lib/commands/config.js TAP config list --json > output matches sna
"package-lock-only": false,
"pack-destination": ".",
"packages": [],
+ "patches-dir": "patches",
+ "allow-unused-patches": false,
+ "ignore-patch-failures": false,
+ "edit-dir": null,
+ "ignore-existing": false,
+ "keep-edit-dir": false,
"parseable": false,
"allow-scripts-pending": false,
"allow-scripts-pin": true,
@@ -170,15 +177,15 @@ exports[`test/lib/commands/config.js TAP config list --json > output matches sna
"searchopts": "",
"searchstaleness": 900,
"shell": "{SHELL}",
- "shrinkwrap": true,
"sign-git-commit": false,
"sign-git-tag": false,
"strict-peer-deps": false,
"strict-allow-scripts": false,
+ "strict-npmrc": false,
"strict-ssl": true,
- "tag": "latest",
"tag-version-prefix": "v",
"timing": false,
+ "to": null,
"umask": 0,
"unicode": false,
"update-notifier": true,
@@ -205,12 +212,13 @@ access = null
all = false
allow-directory = "all"
allow-file = "all"
-allow-git = "all"
-allow-remote = "all"
+allow-git = "none"
+allow-remote = "none"
allow-same-version = false
allow-scripts = [""]
allow-scripts-pending = false
allow-scripts-pin = true
+allow-unused-patches = false
also = null
audit = true
audit-level = null
@@ -243,11 +251,13 @@ diff-src-prefix = "a/"
diff-text = false
diff-unified = 3
dry-run = false
+edit-dir = null
editor = "{EDITOR}"
engine-strict = false
expect-result-count = null
expect-results = null
expires = null
+extension-file = null
fetch-retries = 2
fetch-retry-factor = 10
fetch-retry-maxtimeout = 60000
@@ -260,20 +270,24 @@ fund = true
git = "git"
git-tag-version = true
global = false
+global-ignore-file = "{CWD}/global/etc/npmignore"
global-style = false
globalconfig = "{CWD}/global/etc/npmrc"
heading = "npm"
https-proxy = null
if-present = false
+ignore-existing = false
+ignore-extension = false
+ignore-patch-failures = false
ignore-scripts = false
include = []
include-attestations = false
include-staged = false
include-workspace-root = false
init-author-email = ""
-init-author-name = ""
+; init-author-name = "" ; overridden by user
init-author-url = ""
-init-license = "ISC"
+; init-license = "" ; overridden by global
init-module = "{CWD}/home/.npm-init.js"
init-private = false
init-type = "commonjs"
@@ -281,12 +295,13 @@ init-version = "1.0.0"
init.author.email = ""
init.author.name = ""
init.author.url = ""
-init.license = "ISC"
+init.license = ""
init.module = "{CWD}/home/.npm-init.js"
init.version = "1.0.0"
install-links = false
install-strategy = "hoisted"
json = false
+keep-edit-dir = false
key = null
legacy-bundling = false
legacy-peer-deps = false
@@ -326,6 +341,7 @@ packages-all = false
packages-and-scopes-permission = null
parseable = false
password = (protected)
+patches-dir = "patches"
prefer-dedupe = false
prefer-offline = false
prefer-online = false
@@ -358,15 +374,16 @@ searchlimit = 20
searchopts = ""
searchstaleness = 900
shell = "{SHELL}"
-shrinkwrap = true
sign-git-commit = false
sign-git-tag = false
strict-allow-scripts = false
+strict-npmrc = false
strict-peer-deps = false
strict-ssl = true
-tag = "latest"
+; tag = "latest" ; overridden by project
tag-version-prefix = "v"
timing = false
+to = null
token-description = null
umask = 0
unicode = false
@@ -385,15 +402,15 @@ yes = null
; "global" config from {CWD}/global/etc/npmrc
-globalloaded = "yes"
+init-license = "from-global"
; "user" config from {CWD}/home/.npmrc
-userloaded = "yes"
+init-author-name = "from-user"
; "project" config from {CWD}/prefix/.npmrc
-projectloaded = "yes"
+tag = "from-project"
; "cli" config from command line options
@@ -405,19 +422,17 @@ long = true
exports[`test/lib/commands/config.js TAP config list > output matches snapshot 1`] = `
; "global" config from {CWD}/global/etc/npmrc
-globalloaded = "yes"
+init-license = "from-global"
; "user" config from {CWD}/home/.npmrc
_auth = (protected)
//nerfdart:_auth = (protected)
-//nerfdart:auth = (protected)
-auth = (protected)
-userloaded = "yes"
+init-author-name = "from-user"
; "project" config from {CWD}/prefix/.npmrc
-projectloaded = "yes"
+tag = "from-project"
; "cli" config from command line options
diff --git a/deps/npm/tap-snapshots/test/lib/commands/diff.js.test.cjs b/deps/npm/tap-snapshots/test/lib/commands/diff.js.test.cjs
index e87086d7d9b..0eb91154b24 100644
--- a/deps/npm/tap-snapshots/test/lib/commands/diff.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/commands/diff.js.test.cjs
@@ -62,11 +62,13 @@ package.json
`
exports[`test/lib/commands/diff.js TAP various options using diff option > must match snapshot 1`] = `
-diff --git a/index.js b/index.js
+diff --git bar/index.js foo/index.js
index v2.0.0..v3.0.0 100644
---- a/index.js
-+++ b/index.js
-@@ -18,7 +18,7 @@
+--- bar/index.js
++++ foo/index.js
+@@ -16,11 +16,11 @@
+ 15
+ 16
17
18
19
@@ -75,10 +77,12 @@ index v2.0.0..v3.0.0 100644
21
22
23
-diff --git a/package.json b/package.json
+ 24
+ 25
+diff --git bar/package.json foo/package.json
index v2.0.0..v3.0.0 100644
---- a/package.json
-+++ b/package.json
+--- bar/package.json
++++ foo/package.json
@@ -1,4 +1,4 @@
{
"name": "bar",
diff --git a/deps/npm/tap-snapshots/test/lib/commands/install.js.test.cjs b/deps/npm/tap-snapshots/test/lib/commands/install.js.test.cjs
index 5d78992b51b..9070c6299f0 100644
--- a/deps/npm/tap-snapshots/test/lib/commands/install.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/commands/install.js.test.cjs
@@ -135,8 +135,8 @@ verbose stack Error: The developer of this package has specified the following t
verbose stack Invalid devEngines.runtime
verbose stack Invalid name "nondescript" does not match "node" for "runtime"
verbose stack at Install.checkDevEngines ({CWD}/lib/base-cmd.js:249:27)
-verbose stack at MockNpm.execCommandClass ({CWD}/lib/npm.js:293:7)
-verbose stack at MockNpm.exec ({CWD}/lib/npm.js:193:9)
+verbose stack at MockNpm.execCommandClass ({CWD}/lib/npm.js:294:7)
+verbose stack at MockNpm.exec ({CWD}/lib/npm.js:194:9)
error code EBADDEVENGINES
error EBADDEVENGINES The developer of this package has specified the following through devEngines
error EBADDEVENGINES Invalid devEngines.runtime
@@ -200,8 +200,8 @@ verbose stack Error: The developer of this package has specified the following t
verbose stack Invalid devEngines.runtime
verbose stack Invalid name "nondescript" does not match "node" for "runtime"
verbose stack at Install.checkDevEngines ({CWD}/lib/base-cmd.js:249:27)
-verbose stack at MockNpm.execCommandClass ({CWD}/lib/npm.js:293:7)
-verbose stack at MockNpm.exec ({CWD}/lib/npm.js:193:9)
+verbose stack at MockNpm.execCommandClass ({CWD}/lib/npm.js:294:7)
+verbose stack at MockNpm.exec ({CWD}/lib/npm.js:194:9)
error code EBADDEVENGINES
error EBADDEVENGINES The developer of this package has specified the following through devEngines
error EBADDEVENGINES Invalid devEngines.runtime
@@ -226,8 +226,8 @@ verbose stack Error: The developer of this package has specified the following t
verbose stack Invalid devEngines.runtime
verbose stack Invalid name "nondescript" does not match "node" for "runtime"
verbose stack at Install.checkDevEngines ({CWD}/lib/base-cmd.js:249:27)
-verbose stack at MockNpm.execCommandClass ({CWD}/lib/npm.js:293:7)
-verbose stack at MockNpm.exec ({CWD}/lib/npm.js:193:9)
+verbose stack at MockNpm.execCommandClass ({CWD}/lib/npm.js:294:7)
+verbose stack at MockNpm.exec ({CWD}/lib/npm.js:194:9)
error code EBADDEVENGINES
error EBADDEVENGINES The developer of this package has specified the following through devEngines
error EBADDEVENGINES Invalid devEngines.runtime
diff --git a/deps/npm/tap-snapshots/test/lib/commands/ls.js.test.cjs b/deps/npm/tap-snapshots/test/lib/commands/ls.js.test.cjs
index 7381a4d2f2f..b5ed56aa863 100644
--- a/deps/npm/tap-snapshots/test/lib/commands/ls.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/commands/ls.js.test.cjs
@@ -315,6 +315,12 @@ test-npm-ls@1.0.0 {CWD}/prefix
\`-- dog@2.0.0
`
+exports[`test/lib/commands/ls.js TAP ls .npm-extension dep > human output annotates the transformed node 1`] = `
+test-npm-extension@1.0.0 {CWD}/prefix
+\`-- foo@1.0.0 .npm-extension: dependencies.bar
+ \`-- bar@1.0.0
+`
+
exports[`test/lib/commands/ls.js TAP ls broken resolved field > should NOT print git refs in output tree 1`] = `
npm-broken-resolved-field-test@1.0.0 {CWD}/prefix
\`-- a@1.0.1
@@ -556,6 +562,12 @@ exports[`test/lib/commands/ls.js TAP ls overridden dep w/ color > should contain
[0m[0m
`
+exports[`test/lib/commands/ls.js TAP ls packageExtensions dep > human output annotates the extended node 1`] = `
+test-package-extensions@1.0.0 {CWD}/prefix
+\`-- foo@1.0.0 packageExtensions: dependencies.bar
+ \`-- bar@1.0.0
+`
+
exports[`test/lib/commands/ls.js TAP ls print deduped symlinks > should output tree containing linked deps 1`] = `
print-deduped-symlinks@1.0.0 {CWD}/prefix
+-- a@1.0.0
@@ -565,7 +577,7 @@ print-deduped-symlinks@1.0.0 {CWD}/prefix
exports[`test/lib/commands/ls.js TAP ls resolved points to git ref > should output tree containing git refs 1`] = `
test-npm-ls@1.0.0 {CWD}/prefix
-\`-- abbrev@1.1.1 (git+ssh://git@github.com/isaacs/abbrev-js.git#b8f3a2fc0c3bb8ffd8b0d0072cc6b5a3667e963c)
+\`-- abbrev@1.1.1 (git+https://github.com/isaacs/abbrev-js.git#b8f3a2fc0c3bb8ffd8b0d0072cc6b5a3667e963c)
`
exports[`test/lib/commands/ls.js TAP ls unmet optional dep > should output tree with empty entry for missing optional deps 1`] = `
diff --git a/deps/npm/tap-snapshots/test/lib/commands/pack.js.test.cjs b/deps/npm/tap-snapshots/test/lib/commands/pack.js.test.cjs
index f8c35e1c2c1..3afb19a16b9 100644
--- a/deps/npm/tap-snapshots/test/lib/commands/pack.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/commands/pack.js.test.cjs
@@ -41,6 +41,10 @@ Array [
exports[`test/lib/commands/pack.js TAP foreground-scripts defaults to true > logs pack contents 1`] = `
Array [
+ "run test-fg-scripts@0.0.0 prepack",
+ "run echo prepack!",
+ "run test-fg-scripts@0.0.0 postpack",
+ "run echo postpack!",
"package: test-fg-scripts@0.0.0",
"Tarball Contents",
"110B package.json",
@@ -62,8 +66,8 @@ Array []
exports[`test/lib/commands/pack.js TAP should log output as valid json > outputs as json 1`] = `
Array [
- Array [
- Object {
+ Object {
+ "test-package": Object {
"bundled": Array [],
"entryCount": 1,
"filename": "test-package-1.0.0.tgz",
@@ -82,18 +86,21 @@ Array [
"unpackedSize": 41,
"version": "1.0.0",
},
- ],
+ },
]
`
exports[`test/lib/commands/pack.js TAP should log scoped package output as valid json > logs pack contents 1`] = `
-Array []
+Array [
+ "run @myscope/test-package@1.0.0 prepack",
+ "run echo prepack!",
+]
`
exports[`test/lib/commands/pack.js TAP should log scoped package output as valid json > outputs as json 1`] = `
Array [
- Array [
- Object {
+ Object {
+ "@myscope/test-package": Object {
"bundled": Array [],
"entryCount": 1,
"filename": "myscope-test-package-1.0.0.tgz",
@@ -112,18 +119,7 @@ Array [
"unpackedSize": 88,
"version": "1.0.0",
},
- ],
-]
-`
-
-exports[`test/lib/commands/pack.js TAP should log scoped package output as valid json > stderr has banners 1`] = `
-Array [
- String(
-
- > @myscope/test-package@1.0.0 prepack
- > echo prepack!
-
- ),
+ },
]
`
diff --git a/deps/npm/tap-snapshots/test/lib/commands/pkg.js.test.cjs b/deps/npm/tap-snapshots/test/lib/commands/pkg.js.test.cjs
new file mode 100644
index 00000000000..9e31b675ec2
--- /dev/null
+++ b/deps/npm/tap-snapshots/test/lib/commands/pkg.js.test.cjs
@@ -0,0 +1,220 @@
+/* IMPORTANT
+ * This snapshot file is auto-generated, but designed for humans.
+ * It should be checked into source control and tracked carefully.
+ * Re-generate by setting TAP_SNAPSHOT=1 and running tests.
+ * Make sure to inspect the output below. Do not ignore changes!
+ */
+'use strict'
+exports[`test/lib/commands/pkg.js TAP delete delete multiple field > should delete multiple fields from package.json 1`] = `
+Object {
+ "name": "foo",
+}
+`
+
+exports[`test/lib/commands/pkg.js TAP delete delete nested field > should delete nested fields from package.json 1`] = `
+Object {
+ "info": Object {
+ "foo": Object {
+ "bar": Array [
+ Object {},
+ ],
+ },
+ },
+ "name": "foo",
+ "version": "1.0.0",
+}
+`
+
+exports[`test/lib/commands/pkg.js TAP delete delete single field > should delete single field from package.json 1`] = `
+Object {
+ "name": "foo",
+}
+`
+
+exports[`test/lib/commands/pkg.js TAP fix > fixes package.json issues 1`] = `
+Object {
+ "name": "foo",
+ "version": "1.1.1",
+}
+`
+
+exports[`test/lib/commands/pkg.js TAP get array field > should print retrieved array field 1`] = `
+[ 'index.js', 'cli.js' ]
+`
+
+exports[`test/lib/commands/pkg.js TAP get array item > should print retrieved array field 1`] = `
+index.js
+`
+
+exports[`test/lib/commands/pkg.js TAP get get array nested items notation > should print json result containing matching results 1`] = `
+contributors[0].name = 'Ruy'
+contributors[1].name = 'Gar'
+`
+
+exports[`test/lib/commands/pkg.js TAP get json no args > should print package.json content 1`] = `
+{
+ "name": "foo",
+ "version": "1.1.1"
+}
+`
+
+exports[`test/lib/commands/pkg.js TAP get json with args > should print package.json content 1`] = `
+{
+ "name": "foo"
+}
+`
+
+exports[`test/lib/commands/pkg.js TAP get multiple arg > should print retrieved package.json fields 1`] = `
+name = 'foo'
+version = '1.1.1'
+`
+
+exports[`test/lib/commands/pkg.js TAP get multiple arg with empty value > should print retrieved package.json field regardless of empty value 1`] = `
+name = 'foo'
+author = ''
+`
+
+exports[`test/lib/commands/pkg.js TAP get multiple arg with only one arg existing > should print retrieved package.json field 1`] = `
+name = 'foo'
+`
+
+exports[`test/lib/commands/pkg.js TAP get nested arg > node test.js 1`] = `
+node test.js
+`
+
+exports[`test/lib/commands/pkg.js TAP get no args > should print package.json content 1`] = `
+name = 'foo'
+version = '1.1.1'
+`
+
+exports[`test/lib/commands/pkg.js TAP get non string > should print retrieved package.json field 1`] = `
+{ '@npmcli/test': '*' }
+`
+
+exports[`test/lib/commands/pkg.js TAP get single arg > should print retrieved package.json field 1`] = `
+1.1.1
+`
+
+exports[`test/lib/commands/pkg.js TAP set push to array syntax > should append to arrays using empty bracket syntax 1`] = `
+Object {
+ "keywords": Array [
+ "foo",
+ "bar",
+ "baz",
+ ],
+ "name": "foo",
+ "version": "1.1.1",
+}
+`
+
+exports[`test/lib/commands/pkg.js TAP set set --json > should add fields to package.json 1`] = `
+Object {
+ "description": "awesome",
+ "foo": Object {
+ "bar": Object {
+ "baz": "BAZ",
+ },
+ },
+ "name": "foo",
+ "private": true,
+ "tap": Object {
+ "timeout": 60,
+ },
+ "version": "1.1.1",
+ "workspaces": Array [
+ "packages/*",
+ ],
+}
+`
+
+exports[`test/lib/commands/pkg.js TAP set set = separate value > should add single field to package.json 1`] = `
+Object {
+ "name": "foo",
+ "tap": Object {
+ "test-env": Array [
+ "LC_ALL=sk",
+ ],
+ },
+ "version": "1.1.1",
+}
+`
+
+exports[`test/lib/commands/pkg.js TAP set set multiple fields > should add single field to package.json 1`] = `
+Object {
+ "bin": Object {
+ "foo": "foo.js",
+ },
+ "name": "foo",
+ "scripts": Object {
+ "test": "node test.js",
+ },
+ "version": "1.1.1",
+}
+`
+
+exports[`test/lib/commands/pkg.js TAP set set single field > should add single field to package.json 1`] = `
+Object {
+ "description": "Awesome stuff",
+ "name": "foo",
+ "version": "1.1.1",
+}
+`
+
+exports[`test/lib/commands/pkg.js TAP single workspace multiple args > should only return info for one workspace 1`] = `
+a name = 'a'
+a version = '1.0.0'
+`
+
+exports[`test/lib/commands/pkg.js TAP single workspace single arg > should only return info for one workspace 1`] = `
+a 1.0.0
+`
+
+exports[`test/lib/commands/pkg.js TAP workspaces get > should return expected result for configured workspaces 1`] = `
+a name = 'a'
+a version = '1.0.0'
+b name = 'b'
+b version = '1.2.3'
+`
+
+exports[`test/lib/commands/pkg.js TAP workspaces get json > should return expected json result for configured workspaces 1`] = `
+{
+ "a": {
+ "name": "a",
+ "version": "1.0.0"
+ },
+ "b": {
+ "name": "b",
+ "version": "1.2.3"
+ }
+}
+`
+
+exports[`test/lib/commands/pkg.js TAP workspaces set > should add field to workspace a 1`] = `
+Object {
+ "funding": "http://example.com",
+ "name": "a",
+ "version": "1.0.0",
+}
+`
+
+exports[`test/lib/commands/pkg.js TAP workspaces set > should add field to workspace b 1`] = `
+Object {
+ "funding": "http://example.com",
+ "name": "b",
+ "version": "1.2.3",
+}
+`
+
+exports[`test/lib/commands/pkg.js TAP workspaces set > should delete version field from workspace a 1`] = `
+Object {
+ "funding": "http://example.com",
+ "name": "a",
+}
+`
+
+exports[`test/lib/commands/pkg.js TAP workspaces set > should delete version field from workspace b 1`] = `
+Object {
+ "funding": "http://example.com",
+ "name": "b",
+}
+`
diff --git a/deps/npm/tap-snapshots/test/lib/commands/profile.js.test.cjs b/deps/npm/tap-snapshots/test/lib/commands/profile.js.test.cjs
index 1fbb09de29f..255bd3abc4e 100644
--- a/deps/npm/tap-snapshots/test/lib/commands/profile.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/commands/profile.js.test.cjs
@@ -40,8 +40,6 @@ created 2015-02-26T01:26:37.384Z
updated 2020-08-12T16:19:35.326Z
fullname Foo Bar
homepage https://github.com
-freenode foobar
-twitter https://twitter.com/npmjs
github https://github.com/npm
`
@@ -51,8 +49,6 @@ email: foo@github.com (verified)
two-factor auth: auth-and-writes
fullname: Foo Bar
homepage: https://github.com
-freenode: foobar
-twitter: https://twitter.com/npmjs
github: https://github.com/npm
created: 2015-02-26T01:26:37.384Z
updated: 2020-08-12T16:19:35.326Z
@@ -64,8 +60,6 @@ email: foo@github.com (verified)
two-factor auth: disabled
fullname: Foo Bar
homepage: https://github.com
-freenode: foobar
-twitter: https://twitter.com/npmjs
github: https://github.com/npm
created: 2015-02-26T01:26:37.384Z
updated: 2020-08-12T16:19:35.326Z
@@ -77,8 +71,6 @@ email: foo@github.com (verified)
two-factor auth: auth-and-writes
fullname: Foo Bar
homepage: https://github.com
-freenode: foobar
-twitter: https://twitter.com/npmjs
github: https://github.com/npm
created: 2015-02-26T01:26:37.384Z
updated: 2020-08-12T16:19:35.326Z
@@ -91,8 +83,6 @@ email: foo@github.com(unverified)
two-factor auth: auth-and-writes
fullname: Foo Bar
homepage: https://github.com
-freenode: foobar
-twitter: https://twitter.com/npmjs
github: https://github.com/npm
created: 2015-02-26T01:26:37.384Z
updated: 2020-08-12T16:19:35.326Z
diff --git a/deps/npm/tap-snapshots/test/lib/commands/publish.js.test.cjs b/deps/npm/tap-snapshots/test/lib/commands/publish.js.test.cjs
index dbc6b9f13b0..d037582500b 100644
--- a/deps/npm/tap-snapshots/test/lib/commands/publish.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/commands/publish.js.test.cjs
@@ -51,6 +51,10 @@ Array [
exports[`test/lib/commands/publish.js TAP foreground-scripts defaults to true > must match snapshot 1`] = `
Array [
+ "run test-fg-scripts@0.0.0 prepack",
+ "run echo prepack!",
+ "run test-fg-scripts@0.0.0 postpack",
+ "run echo postpack!",
"package: test-fg-scripts@0.0.0",
"Tarball Contents",
"110B package.json",
@@ -123,10 +127,6 @@ Object {
"url": "https://github.com/npm/cli/issues",
},
"description": "a package manager for JavaScript",
- "directories": Object {
- "doc": "./doc",
- "man": "./man",
- },
"exports": Object {
".": Array [
Object {
@@ -153,101 +153,6 @@ Object {
],
"license": "Artistic-2.0",
"main": "./index.js",
- "man": Array [
- "man/man1/npm-access.1",
- "man/man1/npm-adduser.1",
- "man/man1/npm-approve-scripts.1",
- "man/man1/npm-audit.1",
- "man/man1/npm-bugs.1",
- "man/man1/npm-cache.1",
- "man/man1/npm-ci.1",
- "man/man1/npm-completion.1",
- "man/man1/npm-config.1",
- "man/man1/npm-dedupe.1",
- "man/man1/npm-deny-scripts.1",
- "man/man1/npm-deprecate.1",
- "man/man1/npm-diff.1",
- "man/man1/npm-dist-tag.1",
- "man/man1/npm-docs.1",
- "man/man1/npm-doctor.1",
- "man/man1/npm-edit.1",
- "man/man1/npm-exec.1",
- "man/man1/npm-explain.1",
- "man/man1/npm-explore.1",
- "man/man1/npm-find-dupes.1",
- "man/man1/npm-fund.1",
- "man/man1/npm-get.1",
- "man/man1/npm-help-search.1",
- "man/man1/npm-help.1",
- "man/man1/npm-init.1",
- "man/man1/npm-install-ci-test.1",
- "man/man1/npm-install-scripts.1",
- "man/man1/npm-install-test.1",
- "man/man1/npm-install.1",
- "man/man1/npm-link.1",
- "man/man1/npm-ll.1",
- "man/man1/npm-login.1",
- "man/man1/npm-logout.1",
- "man/man1/npm-ls.1",
- "man/man1/npm-org.1",
- "man/man1/npm-outdated.1",
- "man/man1/npm-owner.1",
- "man/man1/npm-pack.1",
- "man/man1/npm-ping.1",
- "man/man1/npm-pkg.1",
- "man/man1/npm-prefix.1",
- "man/man1/npm-profile.1",
- "man/man1/npm-prune.1",
- "man/man1/npm-publish.1",
- "man/man1/npm-query.1",
- "man/man1/npm-rebuild.1",
- "man/man1/npm-repo.1",
- "man/man1/npm-restart.1",
- "man/man1/npm-root.1",
- "man/man1/npm-run.1",
- "man/man1/npm-sbom.1",
- "man/man1/npm-search.1",
- "man/man1/npm-set.1",
- "man/man1/npm-shrinkwrap.1",
- "man/man1/npm-stage.1",
- "man/man1/npm-star.1",
- "man/man1/npm-stars.1",
- "man/man1/npm-start.1",
- "man/man1/npm-stop.1",
- "man/man1/npm-team.1",
- "man/man1/npm-test.1",
- "man/man1/npm-token.1",
- "man/man1/npm-trust.1",
- "man/man1/npm-undeprecate.1",
- "man/man1/npm-uninstall.1",
- "man/man1/npm-unpublish.1",
- "man/man1/npm-unstar.1",
- "man/man1/npm-update.1",
- "man/man1/npm-version.1",
- "man/man1/npm-view.1",
- "man/man1/npm-whoami.1",
- "man/man1/npm.1",
- "man/man1/npx.1",
- "man/man5/folders.5",
- "man/man5/install.5",
- "man/man5/npm-global.5",
- "man/man5/npm-json.5",
- "man/man5/npm-shrinkwrap-json.5",
- "man/man5/npmrc.5",
- "man/man5/package-json.5",
- "man/man5/package-lock-json.5",
- "man/man7/config.7",
- "man/man7/dependency-selectors.7",
- "man/man7/developers.7",
- "man/man7/logging.7",
- "man/man7/orgs.7",
- "man/man7/package-spec.7",
- "man/man7/registry.7",
- "man/man7/removal.7",
- "man/man7/scope.7",
- "man/man7/scripts.7",
- "man/man7/workspaces.7",
- ],
"name": "npm",
"readmeFilename": "README.md",
"repository": Object {
@@ -321,15 +226,6 @@ exports[`test/lib/commands/publish.js TAP re-loads publishConfig.registry if add
`
exports[`test/lib/commands/publish.js TAP respects publishConfig.registry, runs appropriate scripts > new package version 1`] = `
-
-> @npmcli/test-package@1.0.0 prepublishOnly
-> touch scripts-prepublishonly
-
-> @npmcli/test-package@1.0.0 publish
-> touch scripts-publish
-
-> @npmcli/test-package@1.0.0 postpublish
-> touch scripts-postpublish
+ @npmcli/test-package@1.0.0
`
diff --git a/deps/npm/tap-snapshots/test/lib/commands/sbom.js.test.cjs b/deps/npm/tap-snapshots/test/lib/commands/sbom.js.test.cjs
index 3f1600d9beb..2643ac44ce7 100644
--- a/deps/npm/tap-snapshots/test/lib/commands/sbom.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/commands/sbom.js.test.cjs
@@ -255,7 +255,7 @@ exports[`test/lib/commands/sbom.js TAP sbom basic sbom - cyclonedx > must match
"component": {
"bom-ref": "test-npm-sbom@1.0.0",
"type": "application",
- "name": "prefix",
+ "name": "test-npm-sbom",
"version": "1.0.0",
"scope": "required",
"purl": "pkg:npm/test-npm-sbom@1.0.0",
@@ -457,7 +457,7 @@ exports[`test/lib/commands/sbom.js TAP sbom duplicate deps - cyclonedx > must ma
"component": {
"bom-ref": "test-npm-sbom@1.0.0",
"type": "library",
- "name": "prefix",
+ "name": "test-npm-sbom",
"version": "1.0.0",
"scope": "required",
"purl": "pkg:npm/test-npm-sbom@1.0.0",
diff --git a/deps/npm/tap-snapshots/test/lib/commands/shrinkwrap.js.test.cjs b/deps/npm/tap-snapshots/test/lib/commands/shrinkwrap.js.test.cjs
deleted file mode 100644
index 96b41b117d1..00000000000
--- a/deps/npm/tap-snapshots/test/lib/commands/shrinkwrap.js.test.cjs
+++ /dev/null
@@ -1,435 +0,0 @@
-/* IMPORTANT
- * This snapshot file is auto-generated, but designed for humans.
- * It should be checked into source control and tracked carefully.
- * Re-generate by setting TAP_SNAPSHOT=1 and running tests.
- * Make sure to inspect the output below. Do not ignore changes!
- */
-'use strict'
-exports[`test/lib/commands/shrinkwrap.js TAP with hidden lockfile ancient > must match snapshot 1`] = `
-{
- "localPrefix": {
- "node_modules": {
- ".package-lock.json": {
- "lockfileVersion": 1
- }
- }
- },
- "config": {},
- "shrinkwrap": {
- "name": "prefix",
- "lockfileVersion": 1,
- "requires": true
- },
- "logs": [
- "created a lockfile as npm-shrinkwrap.json"
- ],
- "warn": []
-}
-`
-
-exports[`test/lib/commands/shrinkwrap.js TAP with hidden lockfile ancient upgrade > must match snapshot 1`] = `
-{
- "localPrefix": {
- "node_modules": {
- ".package-lock.json": {
- "lockfileVersion": 1
- }
- }
- },
- "config": {
- "lockfile-version": 3
- },
- "shrinkwrap": {
- "name": "prefix",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {}
- },
- "logs": [
- "created a lockfile as npm-shrinkwrap.json with version 3"
- ],
- "warn": [
- "shrinkwrap Converting lock file (npm-shrinkwrap.json) from v1 -> v3"
- ]
-}
-`
-
-exports[`test/lib/commands/shrinkwrap.js TAP with hidden lockfile existing > must match snapshot 1`] = `
-{
- "localPrefix": {
- "node_modules": {
- ".package-lock.json": {
- "lockfileVersion": 2
- }
- }
- },
- "config": {},
- "shrinkwrap": {
- "name": "prefix",
- "lockfileVersion": 2,
- "requires": true,
- "packages": {}
- },
- "logs": [
- "created a lockfile as npm-shrinkwrap.json"
- ],
- "warn": []
-}
-`
-
-exports[`test/lib/commands/shrinkwrap.js TAP with hidden lockfile existing downgrade > must match snapshot 1`] = `
-{
- "localPrefix": {
- "node_modules": {
- ".package-lock.json": {
- "lockfileVersion": 2
- }
- }
- },
- "config": {
- "lockfile-version": 1
- },
- "shrinkwrap": {
- "name": "prefix",
- "lockfileVersion": 1,
- "requires": true
- },
- "logs": [
- "created a lockfile as npm-shrinkwrap.json with version 1"
- ],
- "warn": [
- "shrinkwrap Converting lock file (npm-shrinkwrap.json) from v2 -> v1"
- ]
-}
-`
-
-exports[`test/lib/commands/shrinkwrap.js TAP with hidden lockfile existing upgrade > must match snapshot 1`] = `
-{
- "localPrefix": {
- "node_modules": {
- ".package-lock.json": {
- "lockfileVersion": 2
- }
- }
- },
- "config": {
- "lockfile-version": 3
- },
- "shrinkwrap": {
- "name": "prefix",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {}
- },
- "logs": [
- "created a lockfile as npm-shrinkwrap.json with version 3"
- ],
- "warn": [
- "shrinkwrap Converting lock file (npm-shrinkwrap.json) from v2 -> v3"
- ]
-}
-`
-
-exports[`test/lib/commands/shrinkwrap.js TAP with nothing ancient > must match snapshot 1`] = `
-{
- "localPrefix": {},
- "config": {},
- "shrinkwrap": {
- "name": "prefix",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {}
- },
- "logs": [
- "created a lockfile as npm-shrinkwrap.json with version 3"
- ],
- "warn": []
-}
-`
-
-exports[`test/lib/commands/shrinkwrap.js TAP with nothing ancient upgrade > must match snapshot 1`] = `
-{
- "localPrefix": {},
- "config": {
- "lockfile-version": 3
- },
- "shrinkwrap": {
- "name": "prefix",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {}
- },
- "logs": [
- "created a lockfile as npm-shrinkwrap.json with version 3"
- ],
- "warn": []
-}
-`
-
-exports[`test/lib/commands/shrinkwrap.js TAP with npm-shrinkwrap.json ancient > must match snapshot 1`] = `
-{
- "localPrefix": {
- "npm-shrinkwrap.json": {
- "lockfileVersion": 1
- }
- },
- "config": {},
- "shrinkwrap": {
- "name": "prefix",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "prefix"
- }
- }
- },
- "logs": [
- "npm-shrinkwrap.json updated to version 3"
- ],
- "warn": [
- "shrinkwrap Converting lock file (npm-shrinkwrap.json) from v1 -> v3"
- ]
-}
-`
-
-exports[`test/lib/commands/shrinkwrap.js TAP with npm-shrinkwrap.json ancient upgrade > must match snapshot 1`] = `
-{
- "localPrefix": {
- "npm-shrinkwrap.json": {
- "lockfileVersion": 1
- }
- },
- "config": {
- "lockfile-version": 3
- },
- "shrinkwrap": {
- "name": "prefix",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "prefix"
- }
- }
- },
- "logs": [
- "npm-shrinkwrap.json updated to version 3"
- ],
- "warn": [
- "shrinkwrap Converting lock file (npm-shrinkwrap.json) from v1 -> v3"
- ]
-}
-`
-
-exports[`test/lib/commands/shrinkwrap.js TAP with npm-shrinkwrap.json existing > must match snapshot 1`] = `
-{
- "localPrefix": {
- "npm-shrinkwrap.json": {
- "lockfileVersion": 2
- }
- },
- "config": {},
- "shrinkwrap": {
- "name": "prefix",
- "lockfileVersion": 2,
- "requires": true,
- "packages": {
- "": {
- "name": "prefix"
- }
- }
- },
- "logs": [
- "npm-shrinkwrap.json up to date"
- ],
- "warn": []
-}
-`
-
-exports[`test/lib/commands/shrinkwrap.js TAP with npm-shrinkwrap.json existing downgrade > must match snapshot 1`] = `
-{
- "localPrefix": {
- "npm-shrinkwrap.json": {
- "lockfileVersion": 2
- }
- },
- "config": {
- "lockfile-version": 1
- },
- "shrinkwrap": {
- "name": "prefix",
- "lockfileVersion": 1,
- "requires": true
- },
- "logs": [
- "npm-shrinkwrap.json updated to version 1"
- ],
- "warn": [
- "shrinkwrap Converting lock file (npm-shrinkwrap.json) from v2 -> v1"
- ]
-}
-`
-
-exports[`test/lib/commands/shrinkwrap.js TAP with npm-shrinkwrap.json existing upgrade > must match snapshot 1`] = `
-{
- "localPrefix": {
- "npm-shrinkwrap.json": {
- "lockfileVersion": 2
- }
- },
- "config": {
- "lockfile-version": 3
- },
- "shrinkwrap": {
- "name": "prefix",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "prefix"
- }
- }
- },
- "logs": [
- "npm-shrinkwrap.json updated to version 3"
- ],
- "warn": [
- "shrinkwrap Converting lock file (npm-shrinkwrap.json) from v2 -> v3"
- ]
-}
-`
-
-exports[`test/lib/commands/shrinkwrap.js TAP with package-lock.json ancient > must match snapshot 1`] = `
-{
- "localPrefix": {
- "package-lock.json": {
- "lockfileVersion": 1
- }
- },
- "config": {},
- "shrinkwrap": {
- "name": "prefix",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "prefix"
- }
- }
- },
- "logs": [
- "package-lock.json has been renamed to npm-shrinkwrap.json and updated to version 3"
- ],
- "warn": [
- "shrinkwrap Converting lock file (npm-shrinkwrap.json) from v1 -> v3"
- ]
-}
-`
-
-exports[`test/lib/commands/shrinkwrap.js TAP with package-lock.json ancient upgrade > must match snapshot 1`] = `
-{
- "localPrefix": {
- "package-lock.json": {
- "lockfileVersion": 1
- }
- },
- "config": {
- "lockfile-version": 3
- },
- "shrinkwrap": {
- "name": "prefix",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "prefix"
- }
- }
- },
- "logs": [
- "package-lock.json has been renamed to npm-shrinkwrap.json and updated to version 3"
- ],
- "warn": [
- "shrinkwrap Converting lock file (npm-shrinkwrap.json) from v1 -> v3"
- ]
-}
-`
-
-exports[`test/lib/commands/shrinkwrap.js TAP with package-lock.json existing > must match snapshot 1`] = `
-{
- "localPrefix": {
- "package-lock.json": {
- "lockfileVersion": 2
- }
- },
- "config": {},
- "shrinkwrap": {
- "name": "prefix",
- "lockfileVersion": 2,
- "requires": true,
- "packages": {
- "": {
- "name": "prefix"
- }
- }
- },
- "logs": [
- "package-lock.json has been renamed to npm-shrinkwrap.json"
- ],
- "warn": []
-}
-`
-
-exports[`test/lib/commands/shrinkwrap.js TAP with package-lock.json existing downgrade > must match snapshot 1`] = `
-{
- "localPrefix": {
- "package-lock.json": {
- "lockfileVersion": 2
- }
- },
- "config": {
- "lockfile-version": 1
- },
- "shrinkwrap": {
- "name": "prefix",
- "lockfileVersion": 1,
- "requires": true
- },
- "logs": [
- "package-lock.json has been renamed to npm-shrinkwrap.json and updated to version 1"
- ],
- "warn": [
- "shrinkwrap Converting lock file (npm-shrinkwrap.json) from v2 -> v1"
- ]
-}
-`
-
-exports[`test/lib/commands/shrinkwrap.js TAP with package-lock.json existing upgrade > must match snapshot 1`] = `
-{
- "localPrefix": {
- "package-lock.json": {
- "lockfileVersion": 2
- }
- },
- "config": {
- "lockfile-version": 3
- },
- "shrinkwrap": {
- "name": "prefix",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "prefix"
- }
- }
- },
- "logs": [
- "package-lock.json has been renamed to npm-shrinkwrap.json and updated to version 3"
- ],
- "warn": [
- "shrinkwrap Converting lock file (npm-shrinkwrap.json) from v2 -> v3"
- ]
-}
-`
diff --git a/deps/npm/tap-snapshots/test/lib/commands/view.js.test.cjs b/deps/npm/tap-snapshots/test/lib/commands/view.js.test.cjs
index 8d66ef78000..470d4138e90 100644
--- a/deps/npm/tap-snapshots/test/lib/commands/view.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/commands/view.js.test.cjs
@@ -321,22 +321,24 @@ published {TIME} ago[39m
`
exports[`test/lib/commands/view.js TAP package with single version full json > must match snapshot 1`] = `
-{
- "_id": "single-version",
- "name": "single-version",
- "dist-tags": {
- "latest": "1.0.0"
- },
- "versions": [
- "1.0.0"
- ],
- "version": "1.0.0",
- "dist": {
- "shasum": "123",
- "tarball": "http://hm.single-version.com/1.0.0.tgz",
- "fileCount": 1
+[
+ {
+ "_id": "single-version",
+ "name": "single-version",
+ "dist-tags": {
+ "latest": "1.0.0"
+ },
+ "versions": [
+ "1.0.0"
+ ],
+ "version": "1.0.0",
+ "dist": {
+ "shasum": "123",
+ "tarball": "http://hm.single-version.com/1.0.0.tgz",
+ "fileCount": 1
+ }
}
-}
+]
`
exports[`test/lib/commands/view.js TAP specific field names array field - 1 element > must match snapshot 1`] = `
@@ -415,60 +417,62 @@ error [94m404[39m 404
exports[`test/lib/commands/view.js TAP workspaces 404 workspaces json > must match snapshot 1`] = `
{
- "green": {
- "_id": "green",
- "name": "green",
- "dist-tags": {
- "latest": "1.0.0"
- },
- "maintainers": [
- {
- "name": "claudia",
- "email": "c@yellow.com",
- "twitter": "cyellow"
+ "green": [
+ {
+ "_id": "green",
+ "name": "green",
+ "dist-tags": {
+ "latest": "1.0.0"
+ },
+ "maintainers": [
+ {
+ "name": "claudia",
+ "email": "c@yellow.com",
+ "twitter": "cyellow"
+ },
+ {
+ "name": "isaacs",
+ "email": "i@yellow.com",
+ "twitter": "iyellow"
+ }
+ ],
+ "keywords": [
+ "colors",
+ "green",
+ "crayola"
+ ],
+ "versions": [
+ "1.0.0",
+ "1.0.1"
+ ],
+ "version": "1.0.0",
+ "description": "green is a very important color",
+ "bugs": {
+ "url": "http://bugs.green.com"
+ },
+ "deprecated": true,
+ "repository": {
+ "url": "http://repository.green.com"
},
- {
- "name": "isaacs",
- "email": "i@yellow.com",
- "twitter": "iyellow"
+ "license": {
+ "type": "ACME"
+ },
+ "bin": {
+ "green": "bin/green.js"
+ },
+ "dependencies": {
+ "red": "1.0.0",
+ "yellow": "1.0.0"
+ },
+ "dist": {
+ "shasum": "123",
+ "tarball": "http://hm.green.com/1.0.0.tgz",
+ "integrity": "---",
+ "fileCount": 1,
+ "unpackedSize": 1000000000
}
- ],
- "keywords": [
- "colors",
- "green",
- "crayola"
- ],
- "versions": [
- "1.0.0",
- "1.0.1"
- ],
- "version": "1.0.0",
- "description": "green is a very important color",
- "bugs": {
- "url": "http://bugs.green.com"
- },
- "deprecated": true,
- "repository": {
- "url": "http://repository.green.com"
- },
- "license": {
- "type": "ACME"
- },
- "bin": {
- "green": "bin/green.js"
- },
- "dependencies": {
- "red": "1.0.0",
- "yellow": "1.0.0"
- },
- "dist": {
- "shasum": "123",
- "tarball": "http://hm.green.com/1.0.0.tgz",
- "integrity": "---",
- "fileCount": 1,
- "unpackedSize": 1000000000
}
- },
+ ],
"error": {
"missing-package": {
"code": "E404",
@@ -530,80 +534,84 @@ error Unknown error
exports[`test/lib/commands/view.js TAP workspaces all workspaces --json > must match snapshot 1`] = `
{
- "green": {
- "_id": "green",
- "name": "green",
- "dist-tags": {
- "latest": "1.0.0"
- },
- "maintainers": [
- {
- "name": "claudia",
- "email": "c@yellow.com",
- "twitter": "cyellow"
+ "green": [
+ {
+ "_id": "green",
+ "name": "green",
+ "dist-tags": {
+ "latest": "1.0.0"
+ },
+ "maintainers": [
+ {
+ "name": "claudia",
+ "email": "c@yellow.com",
+ "twitter": "cyellow"
+ },
+ {
+ "name": "isaacs",
+ "email": "i@yellow.com",
+ "twitter": "iyellow"
+ }
+ ],
+ "keywords": [
+ "colors",
+ "green",
+ "crayola"
+ ],
+ "versions": [
+ "1.0.0",
+ "1.0.1"
+ ],
+ "version": "1.0.0",
+ "description": "green is a very important color",
+ "bugs": {
+ "url": "http://bugs.green.com"
+ },
+ "deprecated": true,
+ "repository": {
+ "url": "http://repository.green.com"
+ },
+ "license": {
+ "type": "ACME"
+ },
+ "bin": {
+ "green": "bin/green.js"
},
- {
- "name": "isaacs",
- "email": "i@yellow.com",
- "twitter": "iyellow"
+ "dependencies": {
+ "red": "1.0.0",
+ "yellow": "1.0.0"
+ },
+ "dist": {
+ "shasum": "123",
+ "tarball": "http://hm.green.com/1.0.0.tgz",
+ "integrity": "---",
+ "fileCount": 1,
+ "unpackedSize": 1000000000
}
- ],
- "keywords": [
- "colors",
- "green",
- "crayola"
- ],
- "versions": [
- "1.0.0",
- "1.0.1"
- ],
- "version": "1.0.0",
- "description": "green is a very important color",
- "bugs": {
- "url": "http://bugs.green.com"
- },
- "deprecated": true,
- "repository": {
- "url": "http://repository.green.com"
- },
- "license": {
- "type": "ACME"
- },
- "bin": {
- "green": "bin/green.js"
- },
- "dependencies": {
- "red": "1.0.0",
- "yellow": "1.0.0"
- },
- "dist": {
- "shasum": "123",
- "tarball": "http://hm.green.com/1.0.0.tgz",
- "integrity": "---",
- "fileCount": 1,
- "unpackedSize": 1000000000
}
- },
- "orange": {
- "name": "orange",
- "dist-tags": {
- "latest": "1.0.0"
- },
- "versions": [
- "1.0.0",
- "1.0.1"
- ],
- "version": "1.0.0",
- "homepage": "http://hm.orange.com",
- "license": {},
- "dist": {
- "shasum": "123",
- "tarball": "http://hm.orange.com/1.0.0.tgz",
- "integrity": "---",
- "fileCount": 1,
- "unpackedSize": 1
+ ],
+ "orange": [
+ {
+ "name": "orange",
+ "dist-tags": {
+ "latest": "1.0.0"
+ },
+ "versions": [
+ "1.0.0",
+ "1.0.1"
+ ],
+ "version": "1.0.0",
+ "homepage": "http://hm.orange.com",
+ "license": {},
+ "dist": {
+ "shasum": "123",
+ "tarball": "http://hm.orange.com/1.0.0.tgz",
+ "integrity": "---",
+ "fileCount": 1,
+ "unpackedSize": 1
+ }
}
- }
+ ]
}
`
@@ -658,8 +666,12 @@ orange:
exports[`test/lib/commands/view.js TAP workspaces all workspaces single field --json > must match snapshot 1`] = `
{
- "green": "green",
- "orange": "orange"
+ "green": [
+ "green"
+ ],
+ "orange": [
+ "orange"
+ ]
}
`
@@ -720,59 +732,61 @@ Array [
exports[`test/lib/commands/view.js TAP workspaces single workspace --json > must match snapshot 1`] = `
{
- "green": {
- "_id": "green",
- "name": "green",
- "dist-tags": {
- "latest": "1.0.0"
- },
- "maintainers": [
- {
- "name": "claudia",
- "email": "c@yellow.com",
- "twitter": "cyellow"
+ "green": [
+ {
+ "_id": "green",
+ "name": "green",
+ "dist-tags": {
+ "latest": "1.0.0"
+ },
+ "maintainers": [
+ {
+ "name": "claudia",
+ "email": "c@yellow.com",
+ "twitter": "cyellow"
+ },
+ {
+ "name": "isaacs",
+ "email": "i@yellow.com",
+ "twitter": "iyellow"
+ }
+ ],
+ "keywords": [
+ "colors",
+ "green",
+ "crayola"
+ ],
+ "versions": [
+ "1.0.0",
+ "1.0.1"
+ ],
+ "version": "1.0.0",
+ "description": "green is a very important color",
+ "bugs": {
+ "url": "http://bugs.green.com"
+ },
+ "deprecated": true,
+ "repository": {
+ "url": "http://repository.green.com"
},
- {
- "name": "isaacs",
- "email": "i@yellow.com",
- "twitter": "iyellow"
+ "license": {
+ "type": "ACME"
+ },
+ "bin": {
+ "green": "bin/green.js"
+ },
+ "dependencies": {
+ "red": "1.0.0",
+ "yellow": "1.0.0"
+ },
+ "dist": {
+ "shasum": "123",
+ "tarball": "http://hm.green.com/1.0.0.tgz",
+ "integrity": "---",
+ "fileCount": 1,
+ "unpackedSize": 1000000000
}
- ],
- "keywords": [
- "colors",
- "green",
- "crayola"
- ],
- "versions": [
- "1.0.0",
- "1.0.1"
- ],
- "version": "1.0.0",
- "description": "green is a very important color",
- "bugs": {
- "url": "http://bugs.green.com"
- },
- "deprecated": true,
- "repository": {
- "url": "http://repository.green.com"
- },
- "license": {
- "type": "ACME"
- },
- "bin": {
- "green": "bin/green.js"
- },
- "dependencies": {
- "red": "1.0.0",
- "yellow": "1.0.0"
- },
- "dist": {
- "shasum": "123",
- "tarball": "http://hm.green.com/1.0.0.tgz",
- "integrity": "---",
- "fileCount": 1,
- "unpackedSize": 1000000000
}
- }
+ ]
}
`
diff --git a/deps/npm/tap-snapshots/test/lib/docs.js.test.cjs b/deps/npm/tap-snapshots/test/lib/docs.js.test.cjs
index 1e2799652c9..6e34b0832ea 100644
--- a/deps/npm/tap-snapshots/test/lib/docs.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/docs.js.test.cjs
@@ -36,7 +36,6 @@ npm@{VERSION} {BASEDIR}
exports[`test/lib/docs.js TAP command list > aliases 1`] = `
Object {
"add": "install",
- "add-user": "adduser",
"author": "owner",
"c": "config",
"cit": "install-ci-test",
@@ -98,7 +97,6 @@ Object {
exports[`test/lib/docs.js TAP command list > commands 1`] = `
Array [
"access",
- "adduser",
"approve-scripts",
"audit",
"bugs",
@@ -136,6 +134,7 @@ Array [
"outdated",
"owner",
"pack",
+ "patch",
"ping",
"pkg",
"prefix",
@@ -151,10 +150,7 @@ Array [
"sbom",
"search",
"set",
- "shrinkwrap",
"stage",
- "star",
- "stars",
"start",
"stop",
"team",
@@ -164,7 +160,6 @@ Array [
"undeprecate",
"uninstall",
"unpublish",
- "unstar",
"update",
"version",
"view",
@@ -262,7 +257,7 @@ dependencies to be used for other commands like \`npm view\`
#### \`allow-git\`
-* Default: "all"
+* Default: "none"
* Type: "all", "none", or "root"
Limits the ability for npm to fetch dependencies from git references. That
@@ -271,6 +266,11 @@ range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.
+As of npm 12 the default is \`none\`. Git dependencies run \`git\` against a
+remote repo and may install configuration the project does not control. Opt
+in explicitly per project (in \`.npmrc\`) or per command (on the CLI) when you
+need git deps.
+
\`all\` allows any git dependencies to be fetched and installed. \`none\`
prevents any git dependencies from being fetched and installed. \`root\` only
allows git dependencies defined in your project's package.json to be fetched
@@ -281,7 +281,7 @@ like \`npm view\`
#### \`allow-remote\`
-* Default: "all"
+* Default: "none"
* Type: "all", "none", or "root"
Limits the ability for npm to fetch dependencies from urls. That is,
@@ -290,6 +290,13 @@ range. Please note that this could leave your tree incomplete and some
packages may not function as intended or designed. Changing this setting
will not remove dependencies that are already installed.
+As of npm 12 the default is \`none\`. Tarballs that share a hostname with the
+configured registry (the typical case for the npm registry, GitHub Packages,
+and most private registries) are still installed normally. If your registry
+serves tarballs from a different host, set \`replace-registry-host\` or
+override this setting. Opt in explicitly per project (in \`.npmrc\`) or per
+command (on the CLI) when you intentionally install from a URL.
+
\`all\` allows any url to be installed. \`none\` prevents any url from being
installed. \`root\` only allows urls defined in your project's package.json to
be installed. Also allows url dependencies to be used for other commands
@@ -327,7 +334,7 @@ Each name is matched against a dependency's resolved identity, not against
the package's self-reported name. \`--ignore-scripts\` and
\`--dangerously-allow-all-scripts\` both override this setting.
-
+This value is not exported to the environment for child processes.
#### \`allow-scripts-pending\`
@@ -352,6 +359,19 @@ setting.
+#### \`allow-unused-patches\`
+
+* Default: false
+* Type: Boolean
+
+Install even when a registered patch in \`patchedDependencies\` matches no
+installed package. Does not silence patch apply failures.
+
+This flag is only honored when passed on the command line; it is ignored in
+\`.npmrc\` and environment variables, and rejected by \`npm ci\`.
+
+
+
#### \`audit\`
* Default: true
@@ -677,6 +697,16 @@ Note: This is NOT honored by other network related commands, eg \`dist-tags\`,
+#### \`edit-dir\`
+
+* Default: null
+* Type: null or Path
+
+Override the temporary directory used by \`npm patch add\` to prepare a
+package for editing.
+
+
+
#### \`editor\`
* Default: The EDITOR or VISUAL environment variables, or
@@ -730,6 +760,19 @@ expiration.
+#### \`extension-file\`
+
+* Default: null
+* Type: null or Path
+
+Path to a project-local npm extension file to load instead of discovering
+\`.npm-extension.mjs\` / \`.npm-extension.cjs\` at the project root. Must
+resolve inside the project root and use a \`.mjs\` or \`.cjs\` extension. Only
+honored from project config or the command line, never from user, global, or
+builtin config.
+
+
+
#### \`fetch-retries\`
* Default: 2
@@ -829,8 +872,7 @@ but can be useful for debugging.
* Default: true
* Type: Boolean
-Format \`package-lock.json\` or \`npm-shrinkwrap.json\` as a human readable
-file.
+Format \`package-lock.json\` as a human readable file.
@@ -881,6 +923,25 @@ folder instead of the current working directory. See
+#### \`global-ignore-file\`
+
+* Default: The global --prefix setting plus 'etc/npmignore'. For example,
+ '/usr/local/etc/npmignore'
+* Type: Path
+
+An additional ignore file applied during \`npm pack\` and \`npm publish\`, owned
+by the current user rather than the package. Patterns follow the same syntax
+as a package's local \`.npmignore\` file. Useful for keeping editor metadata
+(such as \`.idea/\` or \`*.iml\`) and scratch directories out of every package
+you publish, without adding them to each package's own ignore rules.
+
+The global rules apply in addition to a package's local \`.npmignore\`. When a
+package uses a \`files\` field in its \`package.json\`, an entry in \`files\` that
+contradicts a global rule (i.e., explicitly includes a path the global rule
+would exclude) still wins.
+
+
+
#### \`globalconfig\`
* Default: The global --prefix setting plus 'etc/npmrc'. For example,
@@ -926,6 +987,41 @@ CI setup.
This value is not exported to the environment for child processes.
+#### \`ignore-existing\`
+
+* Default: false
+* Type: Boolean
+
+With \`npm patch add\`, discard a previous unfinished edit directory and start
+fresh.
+
+
+
+#### \`ignore-extension\`
+
+* Default: false
+* Type: Boolean
+
+If true, npm does not import or execute a root \`.npm-extension.mjs\` /
+\`.npm-extension.cjs\` file (or one selected via \`extension-file\`).
+\`ignore-scripts\` implies \`ignore-extension\`, since both disable root-owned
+install-time code.
+
+
+
+#### \`ignore-patch-failures\`
+
+* Default: false
+* Type: Boolean
+
+Install even when a registered patch fails to apply, with a warning per
+failure. Intended for incident response only.
+
+This flag is only honored when passed on the command line; it is ignored in
+\`.npmrc\` and environment variables, and rejected by \`npm ci\`.
+
+
+
#### \`ignore-scripts\`
* Default: false
@@ -938,6 +1034,9 @@ Note that commands explicitly intended to run a particular script, such as
run their intended script if \`ignore-scripts\` is set, but they will *not*
run any pre- or post-scripts.
+Setting \`ignore-scripts\` also disables \`.npm-extension\` execution, as if
+\`ignore-extension\` were set.
+
#### \`include\`
@@ -1021,10 +1120,11 @@ homepage.
#### \`init-license\`
-* Default: "ISC"
+* Default: ""
* Type: String
-The value \`npm init\` should use by default for the package license.
+The value \`npm init\` should use by default for the package license. If not
+set, the license field will be omitted from new packages.
@@ -1116,6 +1216,16 @@ Not supported by all npm commands.
+#### \`keep-edit-dir\`
+
+* Default: false
+* Type: Boolean
+
+With \`npm patch commit\`, do not remove the edit directory after committing
+the patch.
+
+
+
#### \`legacy-peer-deps\`
* Default: false
@@ -1190,8 +1300,8 @@ instead of the current working directory. See
otherwise, maintain current lockfile version.
* Type: null, 1, 2, 3, "1", "2", or "3"
-Set the lockfile format version to be used in package-lock.json and
-npm-shrinkwrap-json files. Possible options are:
+Set the lockfile format version to be used in package-lock.json files.
+Possible options are:
1: The lockfile version used by npm versions 5 and 6. Lacks some data that
is used during the install, resulting in slower and possibly less
@@ -1395,8 +1505,7 @@ allow the CLI to fill in missing cache data, see \`--prefer-offline\`.
Dependency types to omit from the installation tree on disk.
Note that these dependencies _are_ still resolved and added to the
-\`package-lock.json\` or \`npm-shrinkwrap.json\` file. They are just not
-physically installed on disk.
+\`package-lock.json\` file. They are just not physically installed on disk.
If a package type appears in both the \`--include\` and \`--omit\` lists, then
it will be included.
@@ -1529,11 +1638,14 @@ token access to all packages instead of limiting to specific packages.
#### \`packages-and-scopes-permission\`
* Default: null
-* Type: null, "read-only", "read-write", or "no-access"
+* Type: null, "read-only", "read-write", "read-write-stage-only", or
+ "no-access"
When creating a Granular Access Token with \`npm token create\`, sets the
permission level for packages and scopes. Options are "read-only",
-"read-write", or "no-access".
+"read-write", "read-write-stage-only", or "no-access".
+"read-write-stage-only" grants publish access that stages releases instead
+of publishing them directly.
@@ -1557,6 +1669,16 @@ tokens, though it's generally safer to be prompted for it.
+#### \`patches-dir\`
+
+* Default: "patches"
+* Type: String
+
+The directory, relative to the project root, where \`npm patch commit\` writes
+patch files for \`patchedDependencies\`.
+
+
+
#### \`prefer-dedupe\`
* Default: false
@@ -1631,6 +1753,9 @@ Set to \`false\` to suppress the progress bar.
When publishing from a supported cloud CI/CD system, the package will be
publicly linked to where it was built and published from.
+When the \`provenance-file\` config is set, it takes precedence and automatic
+provenance generation (including via trusted publishing/OIDC) is skipped.
+
This config cannot be used with: \`provenance-file\`
#### \`provenance-file\`
@@ -1640,6 +1765,9 @@ This config cannot be used with: \`provenance-file\`
When publishing, the provenance bundle at the given path will be used.
+This takes precedence over automatic provenance generation in trusted
+publishing flows.
+
This config cannot be used with: \`provenance\`
#### \`proxy\`
@@ -1950,11 +2078,12 @@ this to work properly.
* Type: Boolean
If \`true\`, turn the install-script policy from a warning into a hard error:
-any dependency with install scripts not covered by \`allowScripts\` will fail
-the install instead of running with a notice.
+any dependency with install scripts that is not covered by \`allowScripts\`
+will fail the install instead of being blocked with a warning.
Dependencies explicitly denied with \`false\` in \`allowScripts\` are always
-silently skipped; this setting only affects unreviewed entries.
+silently skipped; this setting only affects unreviewed entries (packages
+with install scripts that are neither approved nor denied).
\`--ignore-scripts\` and \`--dangerously-allow-all-scripts\` both override this
setting.
@@ -1964,6 +2093,19 @@ their install scripts never run.
+#### \`strict-npmrc\`
+
+* Default: false
+* Type: Boolean
+
+If set to \`true\`, unknown configuration keys found in \`.npmrc\` files are
+treated as a hard error instead of a warning.
+
+Unknown command line flags and abbreviated flags always error regardless of
+this setting.
+
+
+
#### \`strict-peer-deps\`
* Default: false
@@ -2047,6 +2189,17 @@ while still writing the timing file, use \`--silent\`.
+#### \`to\`
+
+* Default: null
+* Type: null or String
+
+Used by \`npm patch update\` to set the version to rebase a patch onto when it
+cannot be read from \`package-lock.json\` — for example an exact-version
+selector, or a version that has not been installed yet.
+
+
+
#### \`token-description\`
* Default: null
@@ -2352,7 +2505,7 @@ Alias for \`--init-author-url\`
#### \`init.license\`
-* Default: "ISC"
+* Default: ""
* Type: String
* DEPRECATED: Use \`--init-license\` instead.
@@ -2447,16 +2600,6 @@ Alias for --include=optional or --omit=optional
Alias for \`--omit=dev\`
-
-#### \`shrinkwrap\`
-
-* Default: true
-* Type: Boolean
-* DEPRECATED: Use the --package-lock setting instead.
-
-Alias for --package-lock
-
-
`
exports[`test/lib/docs.js TAP config > all keys 1`] = `
@@ -2507,6 +2650,7 @@ Array [
"expect-result-count",
"expect-results",
"expires",
+ "extension-file",
"fetch-retries",
"fetch-retry-factor",
"fetch-retry-maxtimeout",
@@ -2520,10 +2664,12 @@ Array [
"git-tag-version",
"global",
"globalconfig",
+ "global-ignore-file",
"global-style",
"heading",
"https-proxy",
"if-present",
+ "ignore-extension",
"ignore-scripts",
"include",
"include-staged",
@@ -2579,6 +2725,12 @@ Array [
"package-lock-only",
"pack-destination",
"packages",
+ "patches-dir",
+ "allow-unused-patches",
+ "ignore-patch-failures",
+ "edit-dir",
+ "ignore-existing",
+ "keep-edit-dir",
"parseable",
"allow-scripts-pending",
"allow-scripts-pin",
@@ -2619,15 +2771,16 @@ Array [
"searchopts",
"searchstaleness",
"shell",
- "shrinkwrap",
"sign-git-commit",
"sign-git-tag",
"strict-peer-deps",
"strict-allow-scripts",
+ "strict-npmrc",
"strict-ssl",
"tag",
"tag-version-prefix",
"timing",
+ "to",
"umask",
"unicode",
"update-notifier",
@@ -2691,6 +2844,7 @@ Array [
"editor",
"engine-strict",
"expires",
+ "extension-file",
"fetch-retries",
"fetch-retry-factor",
"fetch-retry-maxtimeout",
@@ -2704,10 +2858,12 @@ Array [
"git-tag-version",
"global",
"globalconfig",
+ "global-ignore-file",
"global-style",
"heading",
"https-proxy",
"if-present",
+ "ignore-extension",
"ignore-scripts",
"include",
"include-staged",
@@ -2745,6 +2901,7 @@ Array [
"package-lock-only",
"pack-destination",
"packages",
+ "patches-dir",
"parseable",
"allow-scripts-pending",
"allow-scripts-pin",
@@ -2784,11 +2941,11 @@ Array [
"searchopts",
"searchstaleness",
"shell",
- "shrinkwrap",
"sign-git-commit",
"sign-git-tag",
"strict-peer-deps",
"strict-allow-scripts",
+ "strict-npmrc",
"strict-ssl",
"tag",
"tag-version-prefix",
@@ -2823,8 +2980,14 @@ Array [
"logs-max",
"long",
"node-options",
+ "allow-unused-patches",
+ "ignore-patch-failures",
+ "edit-dir",
+ "ignore-existing",
+ "keep-edit-dir",
"prefix",
"timing",
+ "to",
"update-notifier",
"usage",
"userconfig",
@@ -2843,8 +3006,8 @@ Object {
"all": false,
"allowDirectory": "all",
"allowFile": "all",
- "allowGit": "all",
- "allowRemote": "all",
+ "allowGit": "none",
+ "allowRemote": "none",
"allowSameVersion": false,
"allowScripts": Array [],
"allowScriptsPending": false,
@@ -2879,6 +3042,7 @@ Object {
"editor": "{EDITOR}",
"engineStrict": false,
"expires": null,
+ "extensionFile": null,
"force": false,
"foregroundScripts": false,
"formatPackageLock": true,
@@ -2887,9 +3051,11 @@ Object {
"gitTagVersion": true,
"global": false,
"globalconfig": "{CWD}/global/etc/npmrc",
+ "globalIgnoreFile": "{CWD}/global/etc/npmignore",
"heading": "npm",
"httpsProxy": null,
"ifPresent": false,
+ "ignoreExtension": false,
"ignoreScripts": false,
"includeAttestations": false,
"includeStaged": false,
@@ -2933,6 +3099,7 @@ Object {
"packDestination": ".",
"parseable": false,
"password": null,
+ "patchesDir": "patches",
"preferDedupe": false,
"preferOffline": false,
"preferOnline": false,
@@ -2972,6 +3139,7 @@ Object {
"signGitTag": false,
"silent": false,
"strictAllowScripts": false,
+ "strictNpmrc": false,
"strictPeerDeps": false,
"strictSSL": true,
"tagVersionPrefix": "v",
@@ -3073,42 +3241,6 @@ Note: This command is unaware of workspaces.
#### \`registry\`
`
-exports[`test/lib/docs.js TAP usage adduser > must match snapshot 1`] = `
-Add a registry user account
-
-Usage:
-npm adduser
-
-Options:
-[--registry <registry>] [--scope <@scope>] [--auth-type <legacy|web>]
-
- --registry
- The base URL of the npm registry.
-
- --scope
- Associate an operation with a scope for a scoped registry.
-
- --auth-type
- What authentication strategy to use with \`login\`.
-
-
-alias: add-user
-
-Run "npm help adduser" for more info
-
-\`\`\`bash
-npm adduser
-
-alias: add-user
-\`\`\`
-
-Note: This command is unaware of workspaces.
-
-#### \`registry\`
-#### \`scope\`
-#### \`auth-type\`
-`
-
exports[`test/lib/docs.js TAP usage approve-scripts > must match snapshot 1`] = `
Approve install scripts for specific dependencies
@@ -5400,6 +5532,70 @@ npm pack <package-spec>
#### \`ignore-scripts\`
`
+exports[`test/lib/docs.js TAP usage patch > must match snapshot 1`] = `
+Apply local patches to installed dependencies
+
+Usage:
+npm patch <pkg>[@<version>]
+npm patch add <pkg>[@<version>] [--edit-dir <path>] [--ignore-existing]
+npm patch commit <edit-dir> [--patches-dir <dir>] [--keep-edit-dir]
+npm patch update <pkg>[@<old-version>] [--to <new-version>] [--patches-dir <dir>]
+npm patch ls
+npm patch rm <pkg>[@<version>]
+
+Options:
+[--patches-dir <patches-dir>] [--allow-unused-patches] [--ignore-patch-failures]
+[--edit-dir <edit-dir>] [--ignore-existing] [--keep-edit-dir] [--to <version>]
+[--registry <registry>]
+
+ --patches-dir
+ The directory, relative to the project root, where \`npm patch commit\`
+
+ --allow-unused-patches
+ Install even when a registered patch in \`patchedDependencies\` matches no
+
+ --ignore-patch-failures
+ Install even when a registered patch fails to apply, with a warning per
+
+ --edit-dir
+ Override the temporary directory used by \`npm patch add\` to prepare a
+
+ --ignore-existing
+ With \`npm patch add\`, discard a previous unfinished edit directory and
+
+ --keep-edit-dir
+ With \`npm patch commit\`, do not remove the edit directory after
+
+ --to
+ Used by \`npm patch update\` to set the version to rebase a patch onto
+
+ --registry
+ The base URL of the npm registry.
+
+
+Run "npm help patch" for more info
+
+\`\`\`bash
+npm patch <pkg>[@<version>]
+npm patch add <pkg>[@<version>] [--edit-dir <path>] [--ignore-existing]
+npm patch commit <edit-dir> [--patches-dir <dir>] [--keep-edit-dir]
+npm patch update <pkg>[@<old-version>] [--to <new-version>] [--patches-dir <dir>]
+npm patch ls
+npm patch rm <pkg>[@<version>]
+\`\`\`
+
+Note: This command is unaware of workspaces.
+
+#### \`patches-dir\`
+#### \`allow-unused-patches\`
+#### \`ignore-patch-failures\`
+#### \`edit-dir\`
+#### \`ignore-existing\`
+#### \`keep-edit-dir\`
+#### \`to\`
+#### \`registry\`
+`
+
exports[`test/lib/docs.js TAP usage ping > must match snapshot 1`] = `
Ping npm registry
@@ -6068,23 +6264,6 @@ Note: This command is unaware of workspaces.
#### \`location\`
`
-exports[`test/lib/docs.js TAP usage shrinkwrap > must match snapshot 1`] = `
-Lock down dependency versions for publication
-
-Usage:
-npm shrinkwrap
-
-Run "npm help shrinkwrap" for more info
-
-\`\`\`bash
-npm shrinkwrap
-\`\`\`
-
-Note: This command is unaware of workspaces.
-
-NO PARAMS
-`
-
exports[`test/lib/docs.js TAP usage stage > must match snapshot 1`] = `
Stage packages for publishing, deferring proof-of-presence (2FA) to a later point in time
@@ -6140,62 +6319,6 @@ Note: This command is unaware of workspaces.
#### Flags
`
-exports[`test/lib/docs.js TAP usage star > must match snapshot 1`] = `
-Mark your favorite packages
-
-Usage:
-npm star [<package-spec>...]
-
-Options:
-[--registry <registry>] [--unicode] [--otp <otp>]
-
- --registry
- The base URL of the npm registry.
-
- --unicode
- When set to true, npm uses unicode characters in the tree output. When
-
- --otp
- This is a one-time password from a two-factor authenticator. It's needed
-
-
-Run "npm help star" for more info
-
-\`\`\`bash
-npm star [<package-spec>...]
-\`\`\`
-
-Note: This command is unaware of workspaces.
-
-#### \`registry\`
-#### \`unicode\`
-#### \`otp\`
-`
-
-exports[`test/lib/docs.js TAP usage stars > must match snapshot 1`] = `
-View packages marked as favorites
-
-Usage:
-npm stars [<user>]
-
-Options:
-[--registry <registry>]
-
- --registry
- The base URL of the npm registry.
-
-
-Run "npm help stars" for more info
-
-\`\`\`bash
-npm stars [<user>]
-\`\`\`
-
-Note: This command is unaware of workspaces.
-
-#### \`registry\`
-`
-
exports[`test/lib/docs.js TAP usage start > must match snapshot 1`] = `
Start a package
@@ -6334,7 +6457,7 @@ Options:
[--name <name>] [--token-description <token-description>] [--expires <expires>]
[--packages <packages> [--packages <packages> ...]] [--packages-all]
[--scopes <scopes> [--scopes <scopes> ...]] [--orgs <orgs> [--orgs <orgs> ...]]
-[--packages-and-scopes-permission <read-only|read-write|no-access>]
+[--packages-and-scopes-permission <read-only|read-write|read-write-stage-only|no-access>]
[--orgs-permission <read-only|read-write|no-access>]
[--cidr <cidr> [--cidr <cidr> ...]] [--bypass-2fa] [--password <password>]
[--registry <registry>] [--otp <otp>] [--read-only]
@@ -6573,38 +6696,6 @@ npm unpublish [<package-spec>]
#### \`workspaces\`
`
-exports[`test/lib/docs.js TAP usage unstar > must match snapshot 1`] = `
-Remove an item from your favorite packages
-
-Usage:
-npm unstar [<package-spec>...]
-
-Options:
-[--registry <registry>] [--unicode] [--otp <otp>]
-
- --registry
- The base URL of the npm registry.
-
- --unicode
- When set to true, npm uses unicode characters in the tree output. When
-
- --otp
- This is a one-time password from a two-factor authenticator. It's needed
-
-
-Run "npm help unstar" for more info
-
-\`\`\`bash
-npm unstar [<package-spec>...]
-\`\`\`
-
-Note: This command is unaware of workspaces.
-
-#### \`registry\`
-#### \`unicode\`
-#### \`otp\`
-`
-
exports[`test/lib/docs.js TAP usage update > must match snapshot 1`] = `
Update packages
diff --git a/deps/npm/tap-snapshots/test/lib/npm.js.test.cjs b/deps/npm/tap-snapshots/test/lib/npm.js.test.cjs
index a3837dc72ab..9e1ed153d1a 100644
--- a/deps/npm/tap-snapshots/test/lib/npm.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/npm.js.test.cjs
@@ -31,17 +31,16 @@ npm help npm more involved overview
All commands:
- access, adduser, approve-scripts, audit, bugs, cache, ci,
+ access, approve-scripts, audit, bugs, cache, ci,
completion, config, dedupe, deny-scripts, deprecate, diff,
dist-tag, docs, doctor, edit, exec, explain, explore,
find-dupes, fund, get, help, help-search, init, install,
install-ci-test, install-scripts, install-test, link, ll,
- login, logout, ls, org, outdated, owner, pack, ping, pkg,
- prefix, profile, prune, publish, query, rebuild, repo,
- restart, root, run, sbom, search, set, shrinkwrap, stage,
- star, stars, start, stop, team, test, token, trust,
- undeprecate, uninstall, unpublish, unstar, update, version,
- view, whoami
+ login, logout, ls, org, outdated, owner, pack, patch, ping,
+ pkg, prefix, profile, prune, publish, query, rebuild, repo,
+ restart, root, run, sbom, search, set, stage, start, stop,
+ team, test, token, trust, undeprecate, uninstall, unpublish,
+ update, version, view, whoami
Specify configs in the ini-formatted file:
{USERCONFIG}
@@ -69,7 +68,7 @@ npm help npm more involved overview
All commands:
- access, adduser,
+ access,
approve-scripts, audit,
bugs, cache, ci,
completion, config,
@@ -86,18 +85,17 @@ All commands:
install-test, link, ll,
login, logout, ls, org,
outdated, owner, pack,
- ping, pkg, prefix,
- profile, prune, publish,
- query, rebuild, repo,
- restart, root, run,
- sbom, search, set,
- shrinkwrap, stage, star,
- stars, start, stop,
+ patch, ping, pkg,
+ prefix, profile, prune,
+ publish, query, rebuild,
+ repo, restart, root,
+ run, sbom, search, set,
+ stage, start, stop,
team, test, token,
trust, undeprecate,
uninstall, unpublish,
- unstar, update, version,
- view, whoami
+ update, version, view,
+ whoami
Specify configs in the ini-formatted file:
{USERCONFIG}
@@ -125,7 +123,7 @@ npm help npm more involved overview
All commands:
- access, adduser,
+ access,
approve-scripts, audit,
bugs, cache, ci,
completion, config,
@@ -142,18 +140,17 @@ All commands:
install-test, link, ll,
login, logout, ls, org,
outdated, owner, pack,
- ping, pkg, prefix,
- profile, prune, publish,
- query, rebuild, repo,
- restart, root, run,
- sbom, search, set,
- shrinkwrap, stage, star,
- stars, start, stop,
+ patch, ping, pkg,
+ prefix, profile, prune,
+ publish, query, rebuild,
+ repo, restart, root,
+ run, sbom, search, set,
+ stage, start, stop,
team, test, token,
trust, undeprecate,
uninstall, unpublish,
- unstar, update, version,
- view, whoami
+ update, version, view,
+ whoami
Specify configs in the ini-formatted file:
{USERCONFIG}
@@ -181,17 +178,16 @@ npm help npm more involved overview
All commands:
- access, adduser, approve-scripts, audit, bugs, cache, ci,
+ access, approve-scripts, audit, bugs, cache, ci,
completion, config, dedupe, deny-scripts, deprecate, diff,
dist-tag, docs, doctor, edit, exec, explain, explore,
find-dupes, fund, get, help, help-search, init, install,
install-ci-test, install-scripts, install-test, link, ll,
- login, logout, ls, org, outdated, owner, pack, ping, pkg,
- prefix, profile, prune, publish, query, rebuild, repo,
- restart, root, run, sbom, search, set, shrinkwrap, stage,
- star, stars, start, stop, team, test, token, trust,
- undeprecate, uninstall, unpublish, unstar, update, version,
- view, whoami
+ login, logout, ls, org, outdated, owner, pack, patch, ping,
+ pkg, prefix, profile, prune, publish, query, rebuild, repo,
+ restart, root, run, sbom, search, set, stage, start, stop,
+ team, test, token, trust, undeprecate, uninstall, unpublish,
+ update, version, view, whoami
Specify configs in the ini-formatted file:
{USERCONFIG}
@@ -219,7 +215,7 @@ npm help npm more involved overview
All commands:
- access, adduser,
+ access,
approve-scripts, audit,
bugs, cache, ci,
completion, config,
@@ -236,18 +232,17 @@ All commands:
install-test, link, ll,
login, logout, ls, org,
outdated, owner, pack,
- ping, pkg, prefix,
- profile, prune, publish,
- query, rebuild, repo,
- restart, root, run,
- sbom, search, set,
- shrinkwrap, stage, star,
- stars, start, stop,
+ patch, ping, pkg,
+ prefix, profile, prune,
+ publish, query, rebuild,
+ repo, restart, root,
+ run, sbom, search, set,
+ stage, start, stop,
team, test, token,
trust, undeprecate,
uninstall, unpublish,
- unstar, update, version,
- view, whoami
+ update, version, view,
+ whoami
Specify configs in the ini-formatted file:
{USERCONFIG}
@@ -275,7 +270,7 @@ npm help npm more involved overview
All commands:
- access, adduser,
+ access,
approve-scripts, audit,
bugs, cache, ci,
completion, config,
@@ -292,18 +287,17 @@ All commands:
install-test, link, ll,
login, logout, ls, org,
outdated, owner, pack,
- ping, pkg, prefix,
- profile, prune, publish,
- query, rebuild, repo,
- restart, root, run,
- sbom, search, set,
- shrinkwrap, stage, star,
- stars, start, stop,
+ patch, ping, pkg,
+ prefix, profile, prune,
+ publish, query, rebuild,
+ repo, restart, root,
+ run, sbom, search, set,
+ stage, start, stop,
team, test, token,
trust, undeprecate,
uninstall, unpublish,
- unstar, update, version,
- view, whoami
+ update, version, view,
+ whoami
Specify configs in the ini-formatted file:
{USERCONFIG}
@@ -331,7 +325,7 @@ npm help npm more involved overview
All commands:
- access, adduser,
+ access,
approve-scripts, audit,
bugs, cache, ci,
completion, config,
@@ -347,18 +341,16 @@ All commands:
install-test, link, ll,
login, logout, ls, org,
outdated, owner, pack,
- ping, pkg, prefix,
+ patch, ping, pkg, prefix,
profile, prune, publish,
query, rebuild, repo,
restart, root, run, sbom,
- search, set, shrinkwrap,
- stage, star, stars,
+ search, set, stage,
start, stop, team, test,
token, trust,
undeprecate, uninstall,
- unpublish, unstar,
- update, version, view,
- whoami
+ unpublish, update,
+ version, view, whoami
Specify configs in the ini-formatted file:
{USERCONFIG}
@@ -386,17 +378,16 @@ npm help npm more involved overview
All commands:
- access, adduser, approve-scripts, audit, bugs, cache, ci,
+ access, approve-scripts, audit, bugs, cache, ci,
completion, config, dedupe, deny-scripts, deprecate, diff,
dist-tag, docs, doctor, edit, exec, explain, explore,
find-dupes, fund, get, help, help-search, init, install,
install-ci-test, install-scripts, install-test, link, ll,
- login, logout, ls, org, outdated, owner, pack, ping, pkg,
- prefix, profile, prune, publish, query, rebuild, repo,
- restart, root, run, sbom, search, set, shrinkwrap, stage,
- star, stars, start, stop, team, test, token, trust,
- undeprecate, uninstall, unpublish, unstar, update, version,
- view, whoami
+ login, logout, ls, org, outdated, owner, pack, patch, ping,
+ pkg, prefix, profile, prune, publish, query, rebuild, repo,
+ restart, root, run, sbom, search, set, stage, start, stop,
+ team, test, token, trust, undeprecate, uninstall,
+ unpublish, update, version, view, whoami
Specify configs in the ini-formatted file:
{USERCONFIG}
@@ -424,17 +415,16 @@ npm help npm more involved overview
All commands:
- access, adduser, approve-scripts, audit, bugs, cache, ci,
+ access, approve-scripts, audit, bugs, cache, ci,
completion, config, dedupe, deny-scripts, deprecate, diff,
dist-tag, docs, doctor, edit, exec, explain, explore,
find-dupes, fund, get, help, help-search, init, install,
install-ci-test, install-scripts, install-test, link, ll,
- login, logout, ls, org, outdated, owner, pack, ping, pkg,
- prefix, profile, prune, publish, query, rebuild, repo,
- restart, root, run, sbom, search, set, shrinkwrap, stage,
- star, stars, start, stop, team, test, token, trust,
- undeprecate, uninstall, unpublish, unstar, update, version,
- view, whoami
+ login, logout, ls, org, outdated, owner, pack, patch, ping,
+ pkg, prefix, profile, prune, publish, query, rebuild, repo,
+ restart, root, run, sbom, search, set, stage, start, stop,
+ team, test, token, trust, undeprecate, uninstall, unpublish,
+ update, version, view, whoami
Specify configs in the ini-formatted file:
{USERCONFIG}
@@ -462,17 +452,16 @@ npm help npm more involved overview
All commands:
- access, adduser, approve-scripts, audit, bugs, cache, ci,
+ access, approve-scripts, audit, bugs, cache, ci,
completion, config, dedupe, deny-scripts, deprecate, diff,
dist-tag, docs, doctor, edit, exec, explain, explore,
find-dupes, fund, get, help, help-search, init, install,
install-ci-test, install-scripts, install-test, link, ll,
- login, logout, ls, org, outdated, owner, pack, ping, pkg,
- prefix, profile, prune, publish, query, rebuild, repo,
- restart, root, run, sbom, search, set, shrinkwrap, stage,
- star, stars, start, stop, team, test, token, trust,
- undeprecate, uninstall, unpublish, unstar, update, version,
- view, whoami
+ login, logout, ls, org, outdated, owner, pack, patch, ping,
+ pkg, prefix, profile, prune, publish, query, rebuild, repo,
+ restart, root, run, sbom, search, set, stage, start, stop,
+ team, test, token, trust, undeprecate, uninstall, unpublish,
+ update, version, view, whoami
Specify configs in the ini-formatted file:
{USERCONFIG}
diff --git a/deps/npm/tap-snapshots/test/lib/utils/error-message.js.test.cjs b/deps/npm/tap-snapshots/test/lib/utils/error-message.js.test.cjs
index d41a85d99ff..d8f290fcafb 100644
--- a/deps/npm/tap-snapshots/test/lib/utils/error-message.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/utils/error-message.js.test.cjs
@@ -1553,7 +1553,7 @@ Object {
"detail": Array [
Array [
"need auth",
- "You need to authorize this machine using \`npm adduser\`",
+ "You need to authorize this machine using \`npm login\`",
],
],
"summary": Array [
diff --git a/deps/npm/tap-snapshots/test/lib/utils/explain-dep.js.test.cjs b/deps/npm/tap-snapshots/test/lib/utils/explain-dep.js.test.cjs
index 60fca466bb4..3fbe92562f8 100644
--- a/deps/npm/tap-snapshots/test/lib/utils/explain-dep.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/utils/explain-dep.js.test.cjs
@@ -161,6 +161,30 @@ exports[`test/lib/utils/explain-dep.js TAP basic manyDeps > print nocolor 1`] =
manydep@1.0.0
`
+exports[`test/lib/utils/explain-dep.js TAP basic npmExtension > explain color deep 1`] = `
+bar@1.2.3[2m[22m
+[2mnode_modules/bar[22m
+ bar@"^1.0.0" from foo@1.0.0[2m[22m
+ [2mnode_modules/foo[22m[2m (changed by .npm-extension transformManifest dependencies.bar)[22m
+`
+
+exports[`test/lib/utils/explain-dep.js TAP basic npmExtension > explain nocolor shallow 1`] = `
+bar@1.2.3
+node_modules/bar
+ bar@"^1.0.0" from foo@1.0.0
+ node_modules/foo (changed by .npm-extension transformManifest dependencies.bar)
+`
+
+exports[`test/lib/utils/explain-dep.js TAP basic npmExtension > print color 1`] = `
+bar@1.2.3[2m[22m
+[2mnode_modules/bar[22m
+`
+
+exports[`test/lib/utils/explain-dep.js TAP basic npmExtension > print nocolor 1`] = `
+bar@1.2.3
+node_modules/bar
+`
+
exports[`test/lib/utils/explain-dep.js TAP basic optional > explain color deep 1`] = `
optdep@1.0.0 [35moptional[39m[2m[22m
[2mnode_modules/optdep[22m
@@ -205,6 +229,30 @@ overridden-root@1.0.0 overridden
node_modules/overridden-root
`
+exports[`test/lib/utils/explain-dep.js TAP basic packageExtensions > explain color deep 1`] = `
+bar@1.2.3[2m[22m
+[2mnode_modules/bar[22m
+ bar@"^1.0.0" from foo@1.0.0[2m[22m
+ [2mnode_modules/foo[22m[2m (added by packageExtensions["foo@1"].dependencies.bar)[22m
+`
+
+exports[`test/lib/utils/explain-dep.js TAP basic packageExtensions > explain nocolor shallow 1`] = `
+bar@1.2.3
+node_modules/bar
+ bar@"^1.0.0" from foo@1.0.0
+ node_modules/foo (added by packageExtensions["foo@1"].dependencies.bar)
+`
+
+exports[`test/lib/utils/explain-dep.js TAP basic packageExtensions > print color 1`] = `
+bar@1.2.3[2m[22m
+[2mnode_modules/bar[22m
+`
+
+exports[`test/lib/utils/explain-dep.js TAP basic packageExtensions > print nocolor 1`] = `
+bar@1.2.3
+node_modules/bar
+`
+
exports[`test/lib/utils/explain-dep.js TAP basic peer > explain color deep 1`] = `
peer@1.0.0 [95mpeer[39m[2m[22m
[2mnode_modules/peer[22m
diff --git a/deps/npm/tap-snapshots/test/lib/utils/validate-lockfile.js.test.cjs b/deps/npm/tap-snapshots/test/lib/utils/validate-lockfile.js.test.cjs
index 98a51267b1f..5335beb3599 100644
--- a/deps/npm/tap-snapshots/test/lib/utils/validate-lockfile.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/utils/validate-lockfile.js.test.cjs
@@ -19,6 +19,20 @@ exports[`test/lib/utils/validate-lockfile.js TAP identical inventory for both id
Array []
`
+exports[`test/lib/utils/validate-lockfile.js TAP lock file records a patch package.json no longer declares > should report a stray lock file patch 1`] = `
+Array [
+ "Invalid: lock file records a patch for foo@1.0.0 that package.json no longer declares",
+]
+`
+
+exports[`test/lib/utils/validate-lockfile.js TAP mismatching patch integrity or path > should error on integrity drift, path drift, and a newly added patch 1`] = `
+Array [
+ "Invalid: patch for foo@1.0.0 does not match the patch recorded in the lock file",
+ "Invalid: patch for bar@2.0.0 does not match the patch recorded in the lock file",
+ "Invalid: package.json declares a patch for baz@3.0.0 that the lock file does not record (it may have been skipped with --ignore-patch-failures). Fix the patch and reinstall, or remove its patchedDependencies entry",
+]
+`
+
exports[`test/lib/utils/validate-lockfile.js TAP mismatching versions on inventory > should have errors for each mismatching version 1`] = `
Array [
"Invalid: lock file's foo@1.0.0 does not satisfy foo@2.0.0",
diff --git a/deps/npm/tap-snapshots/workspaces/arborist/test/calc-dep-flags.js.test.cjs b/deps/npm/tap-snapshots/workspaces/arborist/test/calc-dep-flags.js.test.cjs
deleted file mode 100644
index acdc2a937a4..00000000000
--- a/deps/npm/tap-snapshots/workspaces/arborist/test/calc-dep-flags.js.test.cjs
+++ /dev/null
@@ -1,809 +0,0 @@
-/* IMPORTANT
- * This snapshot file is auto-generated, but designed for humans.
- * It should be checked into source control and tracked carefully.
- * Re-generate by setting TAP_SNAPSHOT=1 and running tests.
- * Make sure to inspect the output below. Do not ignore changes!
- */
-'use strict'
-exports[`workspaces/arborist/test/calc-dep-flags.js TAP flag stuff > after 1`] = `
-ArboristNode {
- "children": Map {
- "dev" => ArboristNode {
- "dev": true,
- "edgesIn": Set {
- EdgeIn {
- "from": "",
- "name": "dev",
- "spec": "*",
- "type": "dev",
- },
- },
- "edgesOut": Map {
- "devdep" => EdgeOut {
- "name": "devdep",
- "spec": "*",
- "to": "node_modules/devdep",
- "type": "prod",
- },
- },
- "location": "node_modules/dev",
- "name": "dev",
- "path": "/x/node_modules/dev",
- "version": "1.2.3",
- },
- "devandoptional" => ArboristNode {
- "dev": true,
- "edgesIn": Set {
- EdgeIn {
- "from": "node_modules/devdep",
- "name": "devandoptional",
- "spec": "*",
- "type": "optional",
- },
- },
- "location": "node_modules/devandoptional",
- "name": "devandoptional",
- "optional": true,
- "path": "/x/node_modules/devandoptional",
- "version": "1.2.3",
- },
- "devdep" => ArboristNode {
- "children": Map {
- "linky" => ArboristLink {
- "dev": true,
- "edgesIn": Set {
- EdgeIn {
- "from": "node_modules/devdep",
- "name": "linky",
- "spec": "*",
- "type": "prod",
- },
- },
- "location": "node_modules/devdep/node_modules/linky",
- "name": "linky",
- "path": "/x/node_modules/devdep/node_modules/linky",
- "realpath": "/x/y/z",
- "resolved": "file:../../../y/z",
- "target": ArboristNode {
- "location": "y/z",
- },
- "version": "1.2.3",
- },
- },
- "dev": true,
- "edgesIn": Set {
- EdgeIn {
- "from": "node_modules/dev",
- "name": "devdep",
- "spec": "*",
- "type": "prod",
- },
- },
- "edgesOut": Map {
- "devandoptional" => EdgeOut {
- "name": "devandoptional",
- "spec": "*",
- "to": "node_modules/devandoptional",
- "type": "optional",
- },
- "devoptional" => EdgeOut {
- "name": "devoptional",
- "spec": "*",
- "to": "node_modules/devoptional",
- "type": "prod",
- },
- "linky" => EdgeOut {
- "name": "linky",
- "spec": "*",
- "to": "node_modules/devdep/node_modules/linky",
- "type": "prod",
- },
- "proddep" => EdgeOut {
- "name": "proddep",
- "spec": "*",
- "to": "node_modules/proddep",
- "type": "prod",
- },
- },
- "location": "node_modules/devdep",
- "name": "devdep",
- "path": "/x/node_modules/devdep",
- "version": "1.2.3",
- },
- "devoptional" => ArboristNode {
- "devOptional": true,
- "edgesIn": Set {
- EdgeIn {
- "from": "node_modules/devdep",
- "name": "devoptional",
- "spec": "*",
- "type": "prod",
- },
- EdgeIn {
- "from": "node_modules/optional",
- "name": "devoptional",
- "spec": "*",
- "type": "prod",
- },
- },
- "location": "node_modules/devoptional",
- "name": "devoptional",
- "path": "/x/node_modules/devoptional",
- "version": "1.2.3",
- },
- "extraneous" => ArboristNode {
- "dev": true,
- "extraneous": true,
- "location": "node_modules/extraneous",
- "name": "extraneous",
- "optional": true,
- "path": "/x/node_modules/extraneous",
- "peer": true,
- },
- "metapeer" => ArboristNode {
- "edgesIn": Set {
- EdgeIn {
- "from": "node_modules/prod",
- "name": "metapeer",
- "spec": "*",
- "type": "peer",
- },
- },
- "edgesOut": Map {
- "metapeerdep" => EdgeOut {
- "name": "metapeerdep",
- "spec": "*",
- "to": "node_modules/metapeerdep",
- "type": "prod",
- },
- },
- "location": "node_modules/metapeer",
- "name": "metapeer",
- "path": "/x/node_modules/metapeer",
- "peer": true,
- "version": "1.2.3",
- },
- "metapeerdep" => ArboristNode {
- "edgesIn": Set {
- EdgeIn {
- "from": "node_modules/metapeer",
- "name": "metapeerdep",
- "spec": "*",
- "type": "prod",
- },
- },
- "location": "node_modules/metapeerdep",
- "name": "metapeerdep",
- "path": "/x/node_modules/metapeerdep",
- "version": "1.2.3",
- },
- "optional" => ArboristNode {
- "edgesIn": Set {
- EdgeIn {
- "from": "",
- "name": "optional",
- "spec": "*",
- "type": "optional",
- },
- },
- "edgesOut": Map {
- "devoptional" => EdgeOut {
- "name": "devoptional",
- "spec": "*",
- "to": "node_modules/devoptional",
- "type": "prod",
- },
- "missing" => EdgeOut {
- "error": "MISSING",
- "name": "missing",
- "spec": "*",
- "to": null,
- "type": "prod",
- },
- },
- "location": "node_modules/optional",
- "name": "optional",
- "optional": true,
- "path": "/x/node_modules/optional",
- "version": "1.2.3",
- },
- "peer" => ArboristNode {
- "edgesIn": Set {
- EdgeIn {
- "from": "",
- "name": "peer",
- "spec": "*",
- "type": "peer",
- },
- },
- "edgesOut": Map {
- "peerdep" => EdgeOut {
- "name": "peerdep",
- "spec": "*",
- "to": "node_modules/peerdep",
- "type": "prod",
- },
- },
- "location": "node_modules/peer",
- "name": "peer",
- "path": "/x/node_modules/peer",
- "peer": true,
- "version": "1.2.3",
- },
- "peerdep" => ArboristNode {
- "edgesIn": Set {
- EdgeIn {
- "from": "node_modules/peer",
- "name": "peerdep",
- "spec": "*",
- "type": "prod",
- },
- },
- "location": "node_modules/peerdep",
- "name": "peerdep",
- "path": "/x/node_modules/peerdep",
- "version": "1.2.3",
- },
- "prod" => ArboristNode {
- "edgesIn": Set {
- EdgeIn {
- "from": "",
- "name": "prod",
- "spec": "*",
- "type": "prod",
- },
- },
- "edgesOut": Map {
- "metapeer" => EdgeOut {
- "name": "metapeer",
- "spec": "*",
- "to": "node_modules/metapeer",
- "type": "peer",
- },
- "proddep" => EdgeOut {
- "name": "proddep",
- "spec": "*",
- "to": "node_modules/proddep",
- "type": "prod",
- },
- },
- "location": "node_modules/prod",
- "name": "prod",
- "path": "/x/node_modules/prod",
- "version": "1.2.3",
- },
- "proddep" => ArboristNode {
- "edgesIn": Set {
- EdgeIn {
- "from": "node_modules/devdep",
- "name": "proddep",
- "spec": "*",
- "type": "prod",
- },
- EdgeIn {
- "from": "node_modules/prod",
- "name": "proddep",
- "spec": "*",
- "type": "prod",
- },
- EdgeIn {
- "from": "node_modules/proddep",
- "name": "proddep",
- "spec": "*",
- "type": "prod",
- },
- },
- "edgesOut": Map {
- "proddep" => EdgeOut {
- "name": "proddep",
- "spec": "*",
- "to": "node_modules/proddep",
- "type": "prod",
- },
- },
- "location": "node_modules/proddep",
- "name": "proddep",
- "path": "/x/node_modules/proddep",
- "version": "1.2.3",
- },
- },
- "edgesOut": Map {
- "dev" => EdgeOut {
- "name": "dev",
- "spec": "*",
- "to": "node_modules/dev",
- "type": "dev",
- },
- "optional" => EdgeOut {
- "name": "optional",
- "spec": "*",
- "to": "node_modules/optional",
- "type": "optional",
- },
- "peer" => EdgeOut {
- "name": "peer",
- "spec": "*",
- "to": "node_modules/peer",
- "type": "peer",
- },
- "prod" => EdgeOut {
- "name": "prod",
- "spec": "*",
- "to": "node_modules/prod",
- "type": "prod",
- },
- },
- "fsChildren": Set {
- ArboristNode {
- "children": Map {
- "linklink" => ArboristLink {
- "dev": true,
- "edgesIn": Set {
- EdgeIn {
- "from": "y/z",
- "name": "linklink",
- "spec": "*",
- "type": "prod",
- },
- },
- "location": "y/z/node_modules/linklink",
- "name": "linklink",
- "path": "/x/y/z/node_modules/linklink",
- "realpath": "/l/i/n/k/link",
- "resolved": "file:../../../../l/i/n/k/link",
- "target": ArboristNode {
- "dev": true,
- "location": "../l/i/n/k/link",
- "name": "link",
- "packageName": "linklink",
- "path": "/l/i/n/k/link",
- "version": "1.2.3",
- },
- "version": "1.2.3",
- },
- },
- "dev": true,
- "edgesOut": Map {
- "linklink" => EdgeOut {
- "name": "linklink",
- "spec": "*",
- "to": "y/z/node_modules/linklink",
- "type": "prod",
- },
- },
- "location": "y/z",
- "name": "z",
- "packageName": "linky",
- "path": "/x/y/z",
- "version": "1.2.3",
- },
- },
- "isProjectRoot": true,
- "location": "",
- "name": "x",
- "path": "/x",
-}
-`
-
-exports[`workspaces/arborist/test/calc-dep-flags.js TAP no reset > after 1`] = `
-ArboristNode {
- "children": Map {
- "foo" => ArboristNode {
- "dev": true,
- "edgesIn": Set {
- EdgeIn {
- "from": "",
- "name": "foo",
- "spec": "*",
- "type": "prod",
- },
- },
- "location": "node_modules/foo",
- "name": "foo",
- "path": "/some/path/node_modules/foo",
- "version": "1.2.3",
- },
- },
- "dev": true,
- "edgesOut": Map {
- "foo" => EdgeOut {
- "name": "foo",
- "spec": "*",
- "to": "node_modules/foo",
- "type": "prod",
- },
- },
- "isProjectRoot": true,
- "location": "",
- "name": "path",
- "path": "/some/path",
-}
-`
-
-exports[`workspaces/arborist/test/calc-dep-flags.js TAP peer dependency with optional dependency > after calcDepFlags 1`] = `
-ArboristNode {
- "children": Map {
- "B" => ArboristNode {
- "edgesIn": Set {
- EdgeIn {
- "from": "",
- "name": "B",
- "spec": "1.0.0",
- "type": "prod",
- },
- },
- "edgesOut": Map {
- "C" => EdgeOut {
- "name": "C",
- "spec": "1.0.0",
- "to": "node_modules/C",
- "type": "peer",
- },
- },
- "location": "node_modules/B",
- "name": "B",
- "path": "/project/node_modules/B",
- "version": "1.0.0",
- },
- "C" => ArboristNode {
- "edgesIn": Set {
- EdgeIn {
- "from": "node_modules/B",
- "name": "C",
- "spec": "1.0.0",
- "type": "peer",
- },
- },
- "edgesOut": Map {
- "D" => EdgeOut {
- "name": "D",
- "spec": "1.0.0",
- "to": "node_modules/D",
- "type": "optional",
- },
- },
- "location": "node_modules/C",
- "name": "C",
- "path": "/project/node_modules/C",
- "peer": true,
- "version": "1.0.0",
- },
- "D" => ArboristNode {
- "edgesIn": Set {
- EdgeIn {
- "from": "node_modules/C",
- "name": "D",
- "spec": "1.0.0",
- "type": "optional",
- },
- },
- "location": "node_modules/D",
- "name": "D",
- "optional": true,
- "path": "/project/node_modules/D",
- "version": "1.0.0",
- },
- },
- "edgesOut": Map {
- "B" => EdgeOut {
- "name": "B",
- "spec": "1.0.0",
- "to": "node_modules/B",
- "type": "prod",
- },
- },
- "isProjectRoot": true,
- "location": "",
- "name": "project",
- "packageName": "A",
- "path": "/project",
- "version": "1.0.0",
-}
-`
-
-exports[`workspaces/arborist/test/calc-dep-flags.js TAP peer dependency with optional dependency > before calcDepFlags 1`] = `
-ArboristNode {
- "children": Map {
- "B" => ArboristNode {
- "dev": true,
- "edgesIn": Set {
- EdgeIn {
- "from": "",
- "name": "B",
- "spec": "1.0.0",
- "type": "prod",
- },
- },
- "edgesOut": Map {
- "C" => EdgeOut {
- "name": "C",
- "spec": "1.0.0",
- "to": "node_modules/C",
- "type": "peer",
- },
- },
- "extraneous": true,
- "location": "node_modules/B",
- "name": "B",
- "optional": true,
- "path": "/project/node_modules/B",
- "peer": true,
- "version": "1.0.0",
- },
- "C" => ArboristNode {
- "dev": true,
- "edgesIn": Set {
- EdgeIn {
- "from": "node_modules/B",
- "name": "C",
- "spec": "1.0.0",
- "type": "peer",
- },
- },
- "edgesOut": Map {
- "D" => EdgeOut {
- "name": "D",
- "spec": "1.0.0",
- "to": "node_modules/D",
- "type": "optional",
- },
- },
- "extraneous": true,
- "location": "node_modules/C",
- "name": "C",
- "optional": true,
- "path": "/project/node_modules/C",
- "peer": true,
- "version": "1.0.0",
- },
- "D" => ArboristNode {
- "dev": true,
- "edgesIn": Set {
- EdgeIn {
- "from": "node_modules/C",
- "name": "D",
- "spec": "1.0.0",
- "type": "optional",
- },
- },
- "extraneous": true,
- "location": "node_modules/D",
- "name": "D",
- "optional": true,
- "path": "/project/node_modules/D",
- "peer": true,
- "version": "1.0.0",
- },
- },
- "dev": true,
- "edgesOut": Map {
- "B" => EdgeOut {
- "name": "B",
- "spec": "1.0.0",
- "to": "node_modules/B",
- "type": "prod",
- },
- },
- "extraneous": true,
- "isProjectRoot": true,
- "location": "",
- "name": "project",
- "optional": true,
- "packageName": "A",
- "path": "/project",
- "peer": true,
- "version": "1.0.0",
-}
-`
-
-exports[`workspaces/arborist/test/calc-dep-flags.js TAP set parents to not extraneous when visiting > after 1`] = `
-ArboristNode {
- "children": Map {
- "asdf" => ArboristNode {
- "children": Map {
- "baz" => ArboristNode {
- "location": "node_modules/asdf/node_modules/baz",
- "name": "baz",
- "path": "/some/path/node_modules/asdf/node_modules/baz",
- "version": "1.2.3",
- },
- },
- "location": "node_modules/asdf",
- "name": "asdf",
- "path": "/some/path/node_modules/asdf",
- "version": "1.2.3",
- },
- "baz" => ArboristLink {
- "edgesIn": Set {
- EdgeIn {
- "from": "",
- "name": "baz",
- "spec": "file:node_modules/asdf/node_modules/baz",
- "type": "prod",
- },
- },
- "location": "node_modules/baz",
- "name": "baz",
- "path": "/some/path/node_modules/baz",
- "realpath": "/some/path/node_modules/asdf/node_modules/baz",
- "resolved": "file:asdf/node_modules/baz",
- "target": ArboristNode {
- "location": "node_modules/asdf/node_modules/baz",
- },
- "version": "1.2.3",
- },
- "foo" => ArboristLink {
- "edgesIn": Set {
- EdgeIn {
- "from": "",
- "name": "foo",
- "spec": "file:bar/foo",
- "type": "prod",
- },
- },
- "location": "node_modules/foo",
- "name": "foo",
- "path": "/some/path/node_modules/foo",
- "realpath": "/some/path/bar/foo",
- "resolved": "file:../bar/foo",
- "target": ArboristNode {
- "location": "bar/foo",
- },
- "version": "1.2.3",
- },
- },
- "edgesOut": Map {
- "baz" => EdgeOut {
- "name": "baz",
- "spec": "file:node_modules/asdf/node_modules/baz",
- "to": "node_modules/baz",
- "type": "prod",
- },
- "foo" => EdgeOut {
- "name": "foo",
- "spec": "file:bar/foo",
- "to": "node_modules/foo",
- "type": "prod",
- },
- },
- "fsChildren": Set {
- ArboristNode {
- "fsChildren": Set {
- ArboristNode {
- "location": "bar/foo",
- "name": "foo",
- "path": "/some/path/bar/foo",
- "version": "1.2.3",
- },
- },
- "location": "bar",
- "name": "bar",
- "path": "/some/path/bar",
- },
- },
- "isProjectRoot": true,
- "location": "",
- "name": "path",
- "path": "/some/path",
-}
-`
-
-exports[`workspaces/arborist/test/calc-dep-flags.js TAP set parents to not extraneous when visiting > before 1`] = `
-ArboristNode {
- "children": Map {
- "asdf" => ArboristNode {
- "children": Map {
- "baz" => ArboristNode {
- "dev": true,
- "extraneous": true,
- "location": "node_modules/asdf/node_modules/baz",
- "name": "baz",
- "optional": true,
- "path": "/some/path/node_modules/asdf/node_modules/baz",
- "peer": true,
- "version": "1.2.3",
- },
- },
- "dev": true,
- "extraneous": true,
- "location": "node_modules/asdf",
- "name": "asdf",
- "optional": true,
- "path": "/some/path/node_modules/asdf",
- "peer": true,
- "version": "1.2.3",
- },
- "baz" => ArboristLink {
- "dev": true,
- "edgesIn": Set {
- EdgeIn {
- "from": "",
- "name": "baz",
- "spec": "file:node_modules/asdf/node_modules/baz",
- "type": "prod",
- },
- },
- "extraneous": true,
- "location": "node_modules/baz",
- "name": "baz",
- "optional": true,
- "path": "/some/path/node_modules/baz",
- "peer": true,
- "realpath": "/some/path/node_modules/asdf/node_modules/baz",
- "resolved": "file:asdf/node_modules/baz",
- "target": ArboristNode {
- "location": "node_modules/asdf/node_modules/baz",
- },
- "version": "1.2.3",
- },
- "foo" => ArboristLink {
- "dev": true,
- "edgesIn": Set {
- EdgeIn {
- "from": "",
- "name": "foo",
- "spec": "file:bar/foo",
- "type": "prod",
- },
- },
- "extraneous": true,
- "location": "node_modules/foo",
- "name": "foo",
- "optional": true,
- "path": "/some/path/node_modules/foo",
- "peer": true,
- "realpath": "/some/path/bar/foo",
- "resolved": "file:../bar/foo",
- "target": ArboristNode {
- "location": "bar/foo",
- },
- "version": "1.2.3",
- },
- },
- "dev": true,
- "edgesOut": Map {
- "baz" => EdgeOut {
- "name": "baz",
- "spec": "file:node_modules/asdf/node_modules/baz",
- "to": "node_modules/baz",
- "type": "prod",
- },
- "foo" => EdgeOut {
- "name": "foo",
- "spec": "file:bar/foo",
- "to": "node_modules/foo",
- "type": "prod",
- },
- },
- "extraneous": true,
- "fsChildren": Set {
- ArboristNode {
- "dev": true,
- "extraneous": true,
- "fsChildren": Set {
- ArboristNode {
- "dev": true,
- "extraneous": true,
- "location": "bar/foo",
- "name": "foo",
- "optional": true,
- "path": "/some/path/bar/foo",
- "peer": true,
- "version": "1.2.3",
- },
- },
- "location": "bar",
- "name": "bar",
- "optional": true,
- "path": "/some/path/bar",
- "peer": true,
- },
- },
- "isProjectRoot": true,
- "location": "",
- "name": "path",
- "optional": true,
- "path": "/some/path",
- "peer": true,
-}
-`
diff --git a/deps/npm/test/bin/windows-shims.js b/deps/npm/test/bin/windows-shims.js
index a97caf7a7c8..d785fbe7b1c 100644
--- a/deps/npm/test/bin/windows-shims.js
+++ b/deps/npm/test/bin/windows-shims.js
@@ -259,9 +259,15 @@ t.test('run shims', t => {
const result = spawnPath(cmd, [...args, ...params], opts)
- // skip the first 3 lines of "npm test" to get the actual script output
- if (params[0].startsWith('test')) {
- result.stdout = result.stdout?.toString().split('\n').slice(3).join('\n').trim()
+ // run-script@11 emits its run banners as notice logs on stderr, e.g.
+ // "npm notice run test@1.0.0 test". Strip them so we can assert on the
+ // script's actual output.
+ if (result.stderr) {
+ result.stderr = result.stderr.toString()
+ .split('\n')
+ .filter(line => !line.startsWith('npm notice run'))
+ .join('\n')
+ .trim()
}
t.match(result, {
diff --git a/deps/npm/test/fixtures/mock-oidc.js b/deps/npm/test/fixtures/mock-oidc.js
index d15d52c1b81..e2e11b27224 100644
--- a/deps/npm/test/fixtures/mock-oidc.js
+++ b/deps/npm/test/fixtures/mock-oidc.js
@@ -101,7 +101,7 @@ const mockOidc = async (t, {
ciInfo.CIRCLE = CIRCLE
})
- const { npm, registry, joinedOutput, logs } = await loadNpmWithRegistry(t, {
+ const { npm, registry, joinedOutput, logs, prefix } = await loadNpmWithRegistry(t, {
config: {
loglevel: 'silly',
...config,
@@ -117,11 +117,12 @@ const mockOidc = async (t, {
})
if (mockGithubOidcOptions) {
- const { idToken, audience, statusCode = 200 } = mockGithubOidcOptions
+ const { idToken, audience, statusCode = 200, times = 1 } = mockGithubOidcOptions
const url = new URL(ACTIONS_ID_TOKEN_REQUEST_URL)
nock(url.origin)
.get(url.pathname)
.query({ audience })
+ .times(times)
.matchHeader('authorization', `Bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}`)
.matchHeader('accept', 'application/json')
.reply(statusCode, statusCode !== 500 ? { value: idToken } : { message: 'Internal Server Error' })
@@ -160,7 +161,7 @@ const mockOidc = async (t, {
})
}
- return { npm, joinedOutput, logs, ACTIONS_ID_TOKEN_REQUEST_URL }
+ return { npm, registry, prefix, joinedOutput, logs, ACTIONS_ID_TOKEN_REQUEST_URL }
}
const oidcPublishTest = (opts) => {
diff --git a/deps/npm/test/lib/base-cmd.js b/deps/npm/test/lib/base-cmd.js
index 41bade7298b..ebe33b1b5ab 100644
--- a/deps/npm/test/lib/base-cmd.js
+++ b/deps/npm/test/lib/base-cmd.js
@@ -118,7 +118,9 @@ t.test('flags() method with no definitions', async t => {
})
t.test('flags() throws error for unknown flags', async t => {
- const { npm } = await loadMockNpm(t)
+ const { npm } = await loadMockNpm(t, {
+ npm: { argv: ['test-command', '--unknown-flag'] },
+ })
class TestCommand extends BaseCommand {
static name = 'test-command'
@@ -139,14 +141,14 @@ t.test('flags() throws error for unknown flags', async t => {
}
}
- // Manually set config.argv to simulate command-line with unknown flag
- npm.config.argv = ['node', 'npm', 'test-command', '--unknown-flag']
-
const command = new TestCommand(npm)
await t.rejects(
command.exec(),
- { message: /Unknown flag.*--unknown-flag/ },
- 'throws error for unknown flag'
+ {
+ code: 'EUNKNOWNCONFIG',
+ message: /Unknown cli flag:[\s\S]*--unknown-flag/,
+ },
+ 'throws EUNKNOWNCONFIG for unknown flag'
)
})
@@ -416,7 +418,9 @@ t.test('flags() returns defaults when argv is empty', async t => {
})
t.test('flags() throws error for multiple unknown flags with pluralization', async t => {
- const { npm } = await loadMockNpm(t)
+ const { npm } = await loadMockNpm(t, {
+ npm: { argv: ['test-command', '--unknown-one', '--unknown-two'] },
+ })
class TestCommand extends BaseCommand {
static name = 'test-command'
@@ -442,8 +446,11 @@ t.test('flags() throws error for multiple unknown flags with pluralization', asy
const command = new TestCommand(npm)
await t.rejects(
command.exec(),
- { message: /Unknown flags:.*--unknown-one.*--unknown-two/ },
- 'throws error with pluralized "flags" for multiple unknown flags'
+ {
+ code: 'EUNKNOWNCONFIG',
+ message: /Unknown cli flags:[\s\S]*--unknown-one[\s\S]*--unknown-two/,
+ },
+ 'throws EUNKNOWNCONFIG with pluralized "flags" for multiple unknown flags'
)
})
@@ -636,8 +643,8 @@ t.test('flags() throws error for extra positional arguments beyond expected coun
// Should throw error for extra positional
await t.rejects(
command.exec(),
- { message: 'Unknown positional argument: extra1' },
- 'throws error for first extra positional'
+ { message: 'Unknown positional arguments: extra1, extra2' },
+ 'throws error for extra positionals'
)
})
@@ -677,3 +684,239 @@ t.test('flags() does not throw when positionals is null (unlimited)', async t =>
t.same(remains, ['pkg1', 'extra1', 'extra2'], 'all positionals are in remains')
t.equal(flags.id, null, 'id flag uses default')
})
+
+t.test('validateCli warns (does not throw) for unknown file configs', async t => {
+ const { npm, logs } = await loadMockNpm(t, {
+ homeDir: {
+ '.npmrc': [
+ 'bogus-user-key=yes',
+ '@scope:bogus-scoped=no',
+ ].join('\n'),
+ },
+ })
+
+ class TestCommand extends BaseCommand {
+ static name = 'test-command'
+ static description = 'Test command'
+ }
+
+ const command = new TestCommand(npm)
+ t.doesNotThrow(() => command.validateCli(), 'unknown file configs do not throw')
+
+ const warningLogs = logs.warn
+ t.ok(warningLogs.some(msg => msg.includes('bogus-user-key') && msg.includes('npm help npmrc')),
+ 'warns about plain unknown key')
+ t.ok(warningLogs.some(msg => msg.includes('bogus-scoped')),
+ 'warns about scoped unknown key')
+})
+
+t.test('validateCli unknown file config warning respects loglevel suppression', async t => {
+ const { npm, logs } = await loadMockNpm(t, {
+ homeDir: {
+ '.npmrc': 'bogus-user-key=yes',
+ },
+ config: { loglevel: 'error' },
+ })
+
+ class TestCommand extends BaseCommand {
+ static name = 'test-command'
+ static description = 'Test command'
+ }
+
+ const command = new TestCommand(npm)
+ t.doesNotThrow(() => command.validateCli(), 'still does not throw')
+ t.notOk(logs.warn.some(msg => msg.includes('bogus-user-key')),
+ 'unknown file config warning is suppressed at loglevel=error')
+})
+
+t.test('validateCli errors on unknown file configs when strict-npmrc is set', async t => {
+ const { npm } = await loadMockNpm(t, {
+ homeDir: {
+ '.npmrc': [
+ 'bogus-user-key=yes',
+ '@scope:bogus-scoped=no',
+ ].join('\n'),
+ },
+ config: { 'strict-npmrc': true },
+ })
+
+ class TestCommand extends BaseCommand {
+ static name = 'test-command'
+ static description = 'Test command'
+ }
+
+ const command = new TestCommand(npm)
+ await t.rejects(
+ (async () => command.validateCli())(),
+ {
+ code: 'EUNKNOWNCONFIG',
+ message: /Unknown npm configuration keys:[\s\S]*bogus-user-key[\s\S]*bogus-scoped[\s\S]*npm help npmrc/,
+ },
+ 'throws EUNKNOWNCONFIG aggregating plain and scoped keys under strict-npmrc'
+ )
+})
+
+t.test('validateCli combines cli and file unknowns under strict-npmrc', async t => {
+ const { npm } = await loadMockNpm(t, {
+ homeDir: {
+ '.npmrc': [
+ 'strict-npmrc=true',
+ 'bogus-user-key=yes',
+ ].join('\n'),
+ },
+ npm: { argv: ['test-command', '--unknown-cli'] },
+ })
+
+ class TestCommand extends BaseCommand {
+ static name = 'test-command'
+ static description = 'Test command'
+ async exec () {
+ return this.flags()
+ }
+ }
+
+ const command = new TestCommand(npm)
+ let err
+ try {
+ command.validateCli()
+ t.fail('expected throw')
+ } catch (e) {
+ err = e
+ }
+ t.equal(err.code, 'EUNKNOWNCONFIG')
+ t.match(err.message, /Unknown cli flag:[\s\S]*--unknown-cli/,
+ 'message contains the cli section')
+ t.match(err.message, /Unknown npm configuration key:[\s\S]*bogus-user-key/,
+ 'message contains the singular file section')
+ t.match(err.unknownConfigs, [
+ { where: 'cli', key: 'unknown-cli' },
+ { where: 'user', key: 'bogus-user-key' },
+ ], 'structured payload contains both cli and file entries')
+})
+
+t.test('validateCli bypasses checks when skipConfigValidation is set', async t => {
+ const { npm } = await loadMockNpm(t, {
+ homeDir: {
+ '.npmrc': 'bogus-user-key=yes',
+ },
+ })
+
+ class TestCommand extends BaseCommand {
+ static name = 'test-command'
+ static description = 'Test command'
+ static skipConfigValidation = true
+ }
+
+ const command = new TestCommand(npm)
+ t.doesNotThrow(() => command.validateCli(), 'skipConfigValidation bypasses unknown-file-config check')
+})
+
+t.test('validateCli throws only on cli unknowns while warning on file unknowns', async t => {
+ const { npm, logs } = await loadMockNpm(t, {
+ homeDir: {
+ '.npmrc': 'bogus-user-key=yes',
+ },
+ npm: { argv: ['test-command', '--unknown-cli'] },
+ })
+
+ class TestCommand extends BaseCommand {
+ static name = 'test-command'
+ static description = 'Test command'
+ async exec () {
+ return this.flags()
+ }
+ }
+
+ const command = new TestCommand(npm)
+ let err
+ try {
+ command.validateCli()
+ t.fail('expected throw')
+ } catch (e) {
+ err = e
+ }
+ t.equal(err.code, 'EUNKNOWNCONFIG')
+ t.match(err.message, /Unknown cli flag:[\s\S]*--unknown-cli/,
+ 'message contains the cli section')
+ t.notMatch(err.message, /bogus-user-key/,
+ 'error message does not contain the file config')
+ t.match(err.unknownConfigs, [
+ { where: 'cli', key: 'unknown-cli' },
+ ], 'structured payload contains only cli entries')
+ t.ok(logs.warn.some(msg => msg.includes('bogus-user-key')),
+ 'file unknown is warned, not thrown')
+})
+
+t.test('validateCli does not throw on unknown env (npm_config_*) configs', async t => {
+ // Env unknowns warn but never error — they are excluded from getUnknownConfigs() by default.
+ // This test locks in the carve-out at the validateCli boundary so the env→warn behavior cannot silently flip if the filter changes.
+ const { npm } = await loadMockNpm(t, {
+ globals: {
+ 'process.env.npm_config_bogus_env': 'yes',
+ },
+ })
+
+ class TestCommand extends BaseCommand {
+ static name = 'test-command'
+ static description = 'Test command'
+ }
+
+ const command = new TestCommand(npm)
+ t.doesNotThrow(() => command.validateCli(),
+ 'unknown env-set config does not throw at validateCli')
+ // sanity: the unknown was in fact seen by Config, just filtered from getUnknownConfigs()
+ t.ok(
+ npm.config.getUnknownConfigs('env').some(u => u.key === 'bogus-env'),
+ 'env unknown is still tracked internally'
+ )
+})
+
+t.test('flags() throws with scoped (nerfdart) display for unknown cli config', async t => {
+ const { npm } = await loadMockNpm(t, {
+ argv: ['--@scope:bogus=yes'],
+ })
+
+ class TestCommand extends BaseCommand {
+ static name = 'test-command'
+ static description = 'Test command'
+
+ async exec () {
+ return this.flags()
+ }
+ }
+
+ npm.config.argv = ['node', 'npm', 'test-command', '--@scope:bogus=yes']
+ const command = new TestCommand(npm)
+ await t.rejects(
+ command.exec(),
+ {
+ code: 'EUNKNOWNCONFIG',
+ message: /Unknown cli flag:[\s\S]*--bogus \(@scope:bogus\)/,
+ },
+ 'scoped display form uses baseKey (key) layout, throws EUNKNOWNCONFIG'
+ )
+})
+
+t.test('flags() throws singular "argument" for a single extra positional', async t => {
+ const { npm } = await loadMockNpm(t, {
+ argv: ['pkg1', 'extra1'],
+ })
+
+ class TestCommand extends BaseCommand {
+ static name = 'test-command'
+ static description = 'Test command'
+ static positionals = 1
+
+ async exec () {
+ return this.flags()
+ }
+ }
+
+ npm.config.argv = ['node', 'npm', 'test-command', 'pkg1', 'extra1']
+ const command = new TestCommand(npm)
+ await t.rejects(
+ command.exec(),
+ { message: 'Unknown positional argument: extra1' },
+ 'singular phrasing when only one extra positional'
+ )
+})
diff --git a/deps/npm/test/lib/commands/adduser.js b/deps/npm/test/lib/commands/adduser.js
deleted file mode 100644
index c69d996f914..00000000000
--- a/deps/npm/test/lib/commands/adduser.js
+++ /dev/null
@@ -1,181 +0,0 @@
-const t = require('tap')
-const fs = require('node:fs')
-const path = require('node:path')
-const ini = require('ini')
-
-const { load: loadMockNpm } = require('../../fixtures/mock-npm.js')
-const mockGlobals = require('@npmcli/mock-globals')
-const MockRegistry = require('@npmcli/mock-registry')
-const stream = require('node:stream')
-
-const mockAddUser = async (t, { stdin: stdinLines, registry: registryUrl, ...options } = {}) => {
- if (stdinLines) {
- const stdin = new stream.PassThrough()
- for (const l of stdinLines) {
- stdin.write(l + '\n')
- }
- mockGlobals(t, {
- 'process.stdin': stdin,
- 'process.stdout': new stream.PassThrough(), // to quiet readline
- }, { replace: true })
- }
- const mock = await loadMockNpm(t, {
- ...options,
- command: 'adduser',
- })
- const registry = new MockRegistry({
- tap: t,
- registry: registryUrl ?? mock.npm.config.get('registry'),
- })
- return {
- registry,
- rc: () => ini.parse(fs.readFileSync(path.join(mock.home, '.npmrc'), 'utf8')),
- ...mock,
- }
-}
-
-t.test('usage', async t => {
- const { adduser } = await loadMockNpm(t, { command: 'adduser' })
- t.match(adduser.usage, 'adduser', 'usage has command name in it')
-})
-
-t.test('legacy', async t => {
- t.test('simple adduser', async t => {
- const { npm, rc, registry, adduser } = await mockAddUser(t, {
- stdin: ['test-user', 'test-password', 'test-email@npmjs.org'],
- config: { 'auth-type': 'legacy' },
- homeDir: {
- '.npmrc': [
- '//registry.npmjs.org/:_authToken=user',
- '//registry.npmjs.org/:always-auth=user',
- '//registry.npmjs.org/:email=test-email-old@npmjs.org',
- ].join('\n'),
- },
- })
- registry.couchadduser({
- username: 'test-user',
- password: 'test-password',
- email: 'test-email@npmjs.org',
- token: 'npm_test-token',
- })
- await adduser.exec([])
- t.same(npm.config.get('email'), 'test-email-old@npmjs.org')
- t.same(npm.config.get('//registry.npmjs.org/:_authToken'), 'npm_test-token')
- t.same(rc(), {
- '//registry.npmjs.org/:_authToken': 'npm_test-token',
- email: 'test-email-old@npmjs.org',
- }, 'should only have token and un-nerfed old email')
- })
-
- t.test('scoped adduser', async t => {
- const { npm, rc, registry, adduser } = await mockAddUser(t, {
- stdin: ['test-user', 'test-password', 'test-email@npmjs.org'],
- config: {
- 'auth-type': 'legacy',
- scope: '@myscope',
- },
- })
- registry.couchadduser({
- username: 'test-user',
- password: 'test-password',
- email: 'test-email@npmjs.org',
- token: 'npm_test-token',
- })
- await adduser.exec([])
- t.same(npm.config.get('//registry.npmjs.org/:_authToken'), 'npm_test-token')
- t.same(npm.config.get('@myscope:registry'), 'https://registry.npmjs.org/')
- t.same(rc(), {
- '//registry.npmjs.org/:_authToken': 'npm_test-token',
- '@myscope:registry': 'https://registry.npmjs.org/',
- }, 'should only have token and scope:registry')
- })
-
- t.test('scoped adduser with valid scoped registry config', async t => {
- const { npm, rc, registry, adduser } = await mockAddUser(t, {
- stdin: ['test-user', 'test-password', 'test-email@npmjs.org'],
- registry: 'https://diff-registry.npmjs.org',
- homeDir: {
- '.npmrc': '@myscope:registry=https://diff-registry.npmjs.org',
- },
- config: {
- 'auth-type': 'legacy',
- scope: '@myscope',
- },
- })
- registry.couchadduser({
- username: 'test-user',
- password: 'test-password',
- email: 'test-email@npmjs.org',
- token: 'npm_test-token',
- })
- await adduser.exec([])
- t.same(npm.config.get('//diff-registry.npmjs.org/:_authToken'), 'npm_test-token')
- t.same(npm.config.get('@myscope:registry'), 'https://diff-registry.npmjs.org')
- t.same(rc(), {
- '@myscope:registry': 'https://diff-registry.npmjs.org',
- '//diff-registry.npmjs.org/:_authToken': 'npm_test-token',
- }, 'should only have token and scope:registry')
- })
-
- t.test('save config failure', async t => {
- const { registry, adduser } = await mockAddUser(t, {
- stdin: ['test-user', 'test-password', 'test-email@npmjs.org'],
- config: { 'auth-type': 'legacy' },
- homeDir: {
- '.npmrc': {},
- },
- })
- registry.couchadduser({
- username: 'test-user',
- password: 'test-password',
- email: 'test-email@npmjs.org',
- token: 'npm_test-token',
- })
- await t.rejects(adduser.exec([]))
- })
- t.end()
-})
-
-t.test('web', t => {
- t.test('basic adduser', async t => {
- const { npm, rc, registry, adduser } = await mockAddUser(t, {
- config: { 'auth-type': 'web' },
- })
- registry.webadduser({ token: 'npm_test-token' })
- await adduser.exec([])
- t.same(npm.config.get('//registry.npmjs.org/:_authToken'), 'npm_test-token')
- t.same(rc(), {
- '//registry.npmjs.org/:_authToken': 'npm_test-token',
- })
- })
-
- t.test('server error', async t => {
- const { adduser, registry } = await mockAddUser(t, {
- config: { 'auth-type': 'web' },
- })
- registry.nock.post(registry.fullPath('/-/v1/login'))
- .reply(503, {})
- await t.rejects(
- adduser.exec([]),
- { message: /503/ }
- )
- })
-
- t.test('fallback', async t => {
- const { npm, registry, adduser } = await mockAddUser(t, {
- stdin: ['test-user', 'test-password', 'test-email@npmjs.org'],
- config: { 'auth-type': 'web' },
- })
- registry.nock.post(registry.fullPath('/-/v1/login'))
- .reply(404, {})
- registry.couchadduser({
- username: 'test-user',
- password: 'test-password',
- email: 'test-email@npmjs.org',
- token: 'npm_test-token',
- })
- await adduser.exec([])
- t.same(npm.config.get('//registry.npmjs.org/:_authToken'), 'npm_test-token')
- })
- t.end()
-})
diff --git a/deps/npm/test/lib/commands/approve-scripts.js b/deps/npm/test/lib/commands/approve-scripts.js
index 1f29cb89894..449382d19e9 100644
--- a/deps/npm/test/lib/commands/approve-scripts.js
+++ b/deps/npm/test/lib/commands/approve-scripts.js
@@ -60,7 +60,7 @@ t.test('approve-scripts --pending lists unreviewed packages', async t => {
})
await npm.exec('approve-scripts', [])
const out = joinedOutput()
- t.match(out, /2 packages have install scripts not yet covered/)
+ t.match(out, /2 packages have install scripts blocked because they are not covered by allowScripts/)
t.match(out, /canvas@1\.0\.0/)
t.match(out, /sharp@1\.0\.0/)
})
@@ -72,7 +72,7 @@ t.test('approve-scripts --pending lists unreviewed packages even with ignore-scr
})
await npm.exec('approve-scripts', [])
const out = joinedOutput()
- t.match(out, /2 packages have install scripts not yet covered/)
+ t.match(out, /2 packages have install scripts blocked because they are not covered by allowScripts/)
t.match(out, /canvas@1\.0\.0/)
t.match(out, /sharp@1\.0\.0/)
})
diff --git a/deps/npm/test/lib/commands/audit.js b/deps/npm/test/lib/commands/audit.js
index 61887417216..196888c9b67 100644
--- a/deps/npm/test/lib/commands/audit.js
+++ b/deps/npm/test/lib/commands/audit.js
@@ -7,6 +7,13 @@ const { default: tufmock } = require('@tufjs/repo-mock')
const { load: loadMockNpm } = require('../../fixtures/mock-npm')
const MockRegistry = require('@npmcli/mock-registry')
+// pacote bundles its own copy of sigstore, which may be nested rather than
+// hoisted. Resolve sigstore relative to pacote so test mocks replace the copy
+// pacote actually requires.
+const pacoteSigstore = require.resolve('sigstore', {
+ paths: [path.dirname(require.resolve('pacote'))],
+})
+
const gunzip = zlib.gunzipSync
const gzip = zlib.gzipSync
@@ -1933,7 +1940,7 @@ t.test('audit signatures', async t => {
prefixDir: installWithValidAttestations,
mocks: {
pacote: t.mock('pacote', {
- sigstore: { verify: async () => true },
+ [pacoteSigstore]: { verify: async () => true },
}),
},
})
@@ -1962,7 +1969,7 @@ t.test('audit signatures', async t => {
},
mocks: {
pacote: t.mock('pacote', {
- sigstore: { verify: async () => true },
+ [pacoteSigstore]: { verify: async () => true },
}),
},
})
@@ -1991,7 +1998,7 @@ t.test('audit signatures', async t => {
},
mocks: {
pacote: t.mock('pacote', {
- sigstore: { verify: async () => true },
+ [pacoteSigstore]: { verify: async () => true },
}),
},
})
@@ -2023,7 +2030,7 @@ t.test('audit signatures', async t => {
},
mocks: {
pacote: t.mock('pacote', {
- sigstore: { verify: async () => true },
+ [pacoteSigstore]: { verify: async () => true },
}),
},
})
@@ -2048,7 +2055,7 @@ t.test('audit signatures', async t => {
prefixDir: installWithValidAttestations,
mocks: {
pacote: t.mock('pacote', {
- sigstore: { verify: async () => true },
+ [pacoteSigstore]: { verify: async () => true },
}),
},
})
@@ -2089,7 +2096,7 @@ t.test('audit signatures', async t => {
prefixDir: installWithMultipleValidAttestations,
mocks: {
pacote: t.mock('pacote', {
- sigstore: { verify: async () => true },
+ [pacoteSigstore]: { verify: async () => true },
}),
},
})
@@ -2119,7 +2126,7 @@ t.test('audit signatures', async t => {
prefixDir: installWithValidAttestations,
mocks: {
pacote: t.mock('pacote', {
- sigstore: {
+ [pacoteSigstore]: {
verify: async () => {
throw new Error(`artifact signature verification failed`)
},
@@ -2154,7 +2161,7 @@ t.test('audit signatures', async t => {
},
mocks: {
pacote: t.mock('pacote', {
- sigstore: {
+ [pacoteSigstore]: {
verify: async () => {
throw new Error(`artifact signature verification failed`)
},
@@ -2183,7 +2190,7 @@ t.test('audit signatures', async t => {
prefixDir: installWithMultipleValidAttestations,
mocks: {
pacote: t.mock('pacote', {
- sigstore: {
+ [pacoteSigstore]: {
verify: async () => {
throw new Error(`artifact signature verification failed`)
},
diff --git a/deps/npm/test/lib/commands/cache.js b/deps/npm/test/lib/commands/cache.js
index 7b79e111cd2..dc4b0388f9d 100644
--- a/deps/npm/test/lib/commands/cache.js
+++ b/deps/npm/test/lib/commands/cache.js
@@ -9,16 +9,16 @@ const { cleanCwd } = require('../../fixtures/clean-snapshot.js')
const pkg = 'test-package'
-const createNpxCacheEntry = (npxCacheDir, hash, pkgJson, shrinkwrapJson) => {
+const createNpxCacheEntry = (npxCacheDir, hash, pkgJson, lockJson) => {
fs.mkdirSync(path.join(npxCacheDir, hash))
fs.writeFileSync(
path.join(npxCacheDir, hash, 'package.json'),
JSON.stringify(pkgJson)
)
- if (shrinkwrapJson) {
+ if (lockJson) {
fs.writeFileSync(
- path.join(npxCacheDir, hash, 'npm-shrinkwrap.json'),
- JSON.stringify(shrinkwrapJson)
+ path.join(npxCacheDir, hash, 'package-lock.json'),
+ JSON.stringify(lockJson)
)
}
}
@@ -685,7 +685,7 @@ t.test('cache npx info: valid entry with a link dependency', async t => {
)
fs.writeFileSync(
- path.join(pkgDir, 'npm-shrinkwrap.json'),
+ path.join(pkgDir, 'package-lock.json'),
JSON.stringify({
name: 'link-package',
version: '1.0.0',
diff --git a/deps/npm/test/lib/commands/ci.js b/deps/npm/test/lib/commands/ci.js
index bc645c5cc40..a90ca4b0cff 100644
--- a/deps/npm/test/lib/commands/ci.js
+++ b/deps/npm/test/lib/commands/ci.js
@@ -122,6 +122,41 @@ t.test('reifies, audits, removes node_modules on repeat run', async t => {
t.equal(fs.existsSync(nmAbbrev), true, 'installs abbrev')
})
+t.test('fails when packageExtensions are out of sync with the lock file', async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { audit: false },
+ prefixDir: {
+ abbrev,
+ // packageExtensions present in package.json but the lock file records no hash
+ 'package.json': JSON.stringify({ ...packageJson, packageExtensions: {} }),
+ 'package-lock.json': JSON.stringify(packageLock),
+ },
+ })
+ await t.rejects(
+ npm.exec('ci', []),
+ /packageExtensions state from lock file/,
+ 'ci refuses to install with stale packageExtensions state'
+ )
+})
+
+t.test('fails when both .npm-extension files are present', async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { audit: false },
+ prefixDir: {
+ abbrev,
+ 'package.json': JSON.stringify(packageJson),
+ 'package-lock.json': JSON.stringify(packageLock),
+ '.npm-extension.mjs': 'export function transformManifest (p) { return p }\n',
+ '.npm-extension.cjs': 'module.exports = { transformManifest (p) { return p } }\n',
+ },
+ })
+ await t.rejects(
+ npm.exec('ci', []),
+ /keep only one/,
+ 'ci surfaces the ambiguous extension file error'
+ )
+})
+
t.test('--no-audit and --ignore-scripts', async t => {
const { npm, joinedOutput, registry } = await loadMockNpm(t, {
config: {
@@ -213,7 +248,116 @@ t.test('lifecycle scripts', async t => {
], 'runs appropriate scripts, in order')
})
-t.test('should throw if package-lock.json or npm-shrinkwrap missing', async t => {
+// Regression test: `npm ci` must run root `preinstall` before reify populates node_modules, matching `npm install` behavior.
+t.test('preinstall runs before reify for npm ci', async t => {
+ const events = []
+ const { npm, registry } = await loadMockNpm(t, {
+ prefixDir: {
+ abbrev: abbrev,
+ 'package.json': JSON.stringify({
+ ...packageJson,
+ scripts: {
+ preinstall: 'echo preinstall',
+ postinstall: 'echo postinstall',
+ },
+ }),
+ 'package-lock.json': JSON.stringify(packageLock),
+ },
+ mocks: {
+ '@npmcli/run-script': async (opts) => {
+ if (opts.path === npm.prefix) {
+ const abbrevPkg = path.join(npm.prefix, 'node_modules', 'abbrev', 'package.json')
+ events.push({ event: opts.event, depInstalled: fs.existsSync(abbrevPkg) })
+ }
+ },
+ },
+ })
+ const manifest = registry.manifest({ name: 'abbrev' })
+ await registry.tarball({
+ manifest: manifest.versions['1.0.0'],
+ tarball: path.join(npm.prefix, 'abbrev'),
+ })
+ registry.nock.post('/-/npm/v1/security/advisories/bulk').reply(200, {})
+ await npm.exec('ci', [])
+
+ const pre = events.find(e => e.event === 'preinstall')
+ const post = events.find(e => e.event === 'postinstall')
+ t.ok(pre, 'preinstall ran')
+ t.ok(post, 'postinstall ran')
+ t.equal(pre.depInstalled, false, 'preinstall runs before dependencies are installed')
+ t.equal(post.depInstalled, true, 'postinstall runs after dependencies are installed')
+})
+
+// Regression test: --ignore-scripts must suppress the new pre-reify `preinstall` path in `npm ci`, matching the symmetric guarantee in `npm install`.
+t.test('--ignore-scripts skips preinstall entirely for npm ci', async t => {
+ const events = []
+ const { npm, registry } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: {
+ abbrev: abbrev,
+ 'package.json': JSON.stringify({
+ ...packageJson,
+ scripts: {
+ preinstall: 'echo preinstall',
+ postinstall: 'echo postinstall',
+ },
+ }),
+ 'package-lock.json': JSON.stringify(packageLock),
+ },
+ mocks: {
+ '@npmcli/run-script': async (opts) => {
+ if (opts.path === npm.prefix) {
+ events.push(opts.event)
+ }
+ },
+ },
+ })
+ const manifest = registry.manifest({ name: 'abbrev' })
+ await registry.tarball({
+ manifest: manifest.versions['1.0.0'],
+ tarball: path.join(npm.prefix, 'abbrev'),
+ })
+ await npm.exec('ci', [])
+ t.strictSame(events, [], 'no root lifecycle scripts run when --ignore-scripts is set')
+})
+
+// Regression test: symmetric to the install-side guarantee — a failing root `preinstall` must short-circuit before reify runs in `npm ci`, so dependencies never reach disk on failure.
+t.test('a failing preinstall prevents reify for npm ci', async t => {
+ const events = []
+ const { npm } = await loadMockNpm(t, {
+ prefixDir: {
+ abbrev: abbrev,
+ 'package.json': JSON.stringify({
+ ...packageJson,
+ scripts: {
+ preinstall: 'exit 1',
+ postinstall: 'echo postinstall',
+ },
+ }),
+ 'package-lock.json': JSON.stringify(packageLock),
+ },
+ mocks: {
+ '@npmcli/run-script': async (opts) => {
+ if (opts.path === npm.prefix) {
+ events.push(opts.event)
+ if (opts.event === 'preinstall') {
+ throw Object.assign(new Error('preinstall failed'), { code: 'ELIFECYCLE' })
+ }
+ }
+ },
+ },
+ })
+
+ await t.rejects(npm.exec('ci', []), /preinstall failed/, 'ci rejects when preinstall fails')
+ t.strictSame(events, ['preinstall'], 'only preinstall ran; no post-reify scripts')
+ t.equal(
+ fs.existsSync(path.join(npm.prefix, 'node_modules', 'abbrev', 'package.json')),
+ false,
+ 'no dependency reached disk after preinstall failure'
+ )
+})
+
+t.test('should throw if package-lock.json is missing', async t => {
const { npm } = await loadMockNpm(t, {
prefixDir: {
'package.json': JSON.stringify(packageJson),
@@ -234,6 +378,17 @@ t.test('should throw ECIGLOBAL', async t => {
await t.rejects(npm.exec('ci', []), { code: 'ECIGLOBAL' })
})
+t.test('rejects the patch relax flags', async t => {
+ for (const flag of ['allow-unused-patches', 'ignore-patch-failures']) {
+ t.test(flag, async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { [flag]: true },
+ })
+ await t.rejects(npm.exec('ci', []), { code: 'ECIPATCHFLAG' })
+ })
+ }
+})
+
t.test('should throw error when ideal inventory mismatches virtual', async t => {
const { npm, registry } = await loadMockNpm(t, {
prefixDir: {
diff --git a/deps/npm/test/lib/commands/completion.js b/deps/npm/test/lib/commands/completion.js
index f3a2c4e12ff..1f07f651296 100644
--- a/deps/npm/test/lib/commands/completion.js
+++ b/deps/npm/test/lib/commands/completion.js
@@ -152,10 +152,10 @@ t.test('completion', async t => {
})
t.test('commands with no completion', async t => {
- const { outputs, completion } = await loadMockCompletionComp(t, 2, 'npm adduser ')
+ const { outputs, completion } = await loadMockCompletionComp(t, 2, 'npm whoami ')
- // quotes around adduser are to ensure coverage when unescaping commands
- await completion.exec(['npm', "'adduser'", ''])
+ // quotes around whoami are to ensure coverage when unescaping commands
+ await completion.exec(['npm', "'whoami'", ''])
t.matchSnapshot(outputs, 'no results')
})
diff --git a/deps/npm/test/lib/commands/config.js b/deps/npm/test/lib/commands/config.js
index 8237ffff22a..1ab9bbae67b 100644
--- a/deps/npm/test/lib/commands/config.js
+++ b/deps/npm/test/lib/commands/config.js
@@ -72,19 +72,17 @@ t.test('config ignores workspaces', async t => {
t.test('config list', async t => {
const { npm, joinedOutput } = await loadMockNpm(t, {
prefixDir: {
- '.npmrc': 'projectloaded=yes',
+ '.npmrc': 'tag=from-project',
},
globalPrefixDir: {
etc: {
- npmrc: 'globalloaded=yes',
+ npmrc: 'init-license=from-global',
},
},
homeDir: {
'.npmrc': [
- 'userloaded=yes',
- 'auth=bad',
+ 'init-author-name=from-user',
'_auth=bad',
- '//nerfdart:auth=bad',
'//nerfdart:_auth=bad',
].join('\n'),
},
@@ -94,9 +92,9 @@ t.test('config list', async t => {
const output = joinedOutput()
- t.match(output, 'projectloaded = "yes"')
- t.match(output, 'globalloaded = "yes"')
- t.match(output, 'userloaded = "yes"')
+ t.match(output, 'tag = "from-project"')
+ t.match(output, 'init-license = "from-global"')
+ t.match(output, 'init-author-name = "from-user"')
t.matchSnapshot(output, 'output matches snapshot')
})
@@ -130,7 +128,7 @@ t.test('config list with proxy environment variables', async t => {
const { npm, joinedOutput } = await loadMockNpm(t, {
prefixDir: {
- '.npmrc': 'test=value',
+ '.npmrc': 'tag=value',
},
})
@@ -147,15 +145,15 @@ t.test('config list with proxy environment variables', async t => {
t.test('config list --long', async t => {
const { npm, joinedOutput } = await loadMockNpm(t, {
prefixDir: {
- '.npmrc': 'projectloaded=yes',
+ '.npmrc': 'tag=from-project',
},
globalPrefixDir: {
etc: {
- npmrc: 'globalloaded=yes',
+ npmrc: 'init-license=from-global',
},
},
homeDir: {
- '.npmrc': 'userloaded=yes',
+ '.npmrc': 'init-author-name=from-user',
},
config: {
long: true,
@@ -166,9 +164,9 @@ t.test('config list --long', async t => {
const output = joinedOutput()
- t.match(output, 'projectloaded = "yes"')
- t.match(output, 'globalloaded = "yes"')
- t.match(output, 'userloaded = "yes"')
+ t.match(output, 'tag = "from-project"')
+ t.match(output, 'init-license = "from-global"')
+ t.match(output, 'init-author-name = "from-user"')
t.matchSnapshot(output, 'output matches snapshot')
})
@@ -176,15 +174,15 @@ t.test('config list --long', async t => {
t.test('config list --json', async t => {
const { npm, joinedOutput } = await loadMockNpm(t, {
prefixDir: {
- '.npmrc': 'projectloaded=yes',
+ '.npmrc': 'tag=from-project',
},
globalPrefixDir: {
etc: {
- npmrc: 'globalloaded=yes',
+ npmrc: 'init-license=from-global',
},
},
homeDir: {
- '.npmrc': 'userloaded=yes',
+ '.npmrc': 'init-author-name=from-user',
},
config: {
json: true,
@@ -195,9 +193,9 @@ t.test('config list --json', async t => {
const output = joinedOutput()
- t.match(output, '"projectloaded": "yes",')
- t.match(output, '"globalloaded": "yes",')
- t.match(output, '"userloaded": "yes",')
+ t.match(output, '"tag": "from-project"')
+ t.match(output, '"init-license": "from-global"')
+ t.match(output, '"init-author-name": "from-user"')
t.matchSnapshot(output, 'output matches snapshot')
})
@@ -342,14 +340,6 @@ t.test('config set invalid option', async t => {
)
})
-t.test('config set deprecated option', async t => {
- const { npm } = await loadMockNpm(t)
- await t.rejects(
- npm.exec('config', ['set', 'shrinkwrap', 'true']),
- /deprecated/
- )
-})
-
t.test('config set nerf-darted option', async t => {
const { npm } = await loadMockNpm(t)
await npm.exec('config', ['set', '//npm.pkg.github.com/:_authToken', '0xdeadbeef'])
@@ -577,9 +567,7 @@ t.test('config edit', async t => {
homeDir: {
'.npmrc': 'foo=bar\nbar=baz',
},
- config: {
- editor: EDITOR,
- },
+ npm: { argv: ['config', 'edit', '--editor=' + EDITOR] },
})
const inputEvents = []
@@ -651,6 +639,7 @@ t.test('config fix', (t) => {
homeDir: {
'.npmrc': '_authtoken=thisisinvalid\n_auth=beef',
},
+ npm: { argv: ['config', 'fix'] },
})
const registry = `//registry.npmjs.org/`
@@ -694,6 +683,7 @@ t.test('config fix', (t) => {
config: {
location: 'user',
},
+ npm: { argv: ['config', 'fix', '--location=user'] },
})
const registry = `//registry.npmjs.org/`
diff --git a/deps/npm/test/lib/commands/diff.js b/deps/npm/test/lib/commands/diff.js
index 3d55cd7879b..0e30ac9b71c 100644
--- a/deps/npm/test/lib/commands/diff.js
+++ b/deps/npm/test/lib/commands/diff.js
@@ -943,11 +943,11 @@ t.test('various options', async t => {
t.test('using diff option', async t => {
const { output } = await mockOptions(t, {
- 'diff-context': 5,
- 'diff-ignore-whitespace': true,
+ 'diff-unified': 5,
+ 'diff-ignore-all-space': true,
'diff-no-prefix': false,
- 'diff-drc-prefix': 'foo/',
- 'diff-fst-prefix': 'bar/',
+ 'diff-dst-prefix': 'foo/',
+ 'diff-src-prefix': 'bar/',
'diff-text': true,
})
diff --git a/deps/npm/test/lib/commands/doctor.js b/deps/npm/test/lib/commands/doctor.js
index 5d912d8b82f..659b465a25a 100644
--- a/deps/npm/test/lib/commands/doctor.js
+++ b/deps/npm/test/lib/commands/doctor.js
@@ -198,7 +198,7 @@ t.test('ping exception with code', async t => {
...dirs,
})
tnock(t, npm.config.get('registry'))
- .get('/-/ping').replyWithError({ message: 'Test Error', code: 'TEST' })
+ .get('/-/ping').replyWithError(Object.assign(new Error('Test Error'), { code: 'TEST' }))
.get('/npm').reply(200, npmManifest(npm.version))
tnock(t, 'https://nodejs.org')
.get('/dist/index.json').reply(200, nodeVersions)
@@ -214,7 +214,7 @@ t.test('ping exception without code', async t => {
...dirs,
})
tnock(t, npm.config.get('registry'))
- .get('/-/ping').replyWithError({ message: 'Test Error', code: false })
+ .get('/-/ping').replyWithError(Object.assign(new Error('Test Error'), { code: false }))
.get('/npm').reply(200, npmManifest(npm.version))
tnock(t, 'https://nodejs.org')
.get('/dist/index.json').reply(200, nodeVersions)
diff --git a/deps/npm/test/lib/commands/edit.js b/deps/npm/test/lib/commands/edit.js
index 915241c82f6..167b77a674c 100644
--- a/deps/npm/test/lib/commands/edit.js
+++ b/deps/npm/test/lib/commands/edit.js
@@ -22,6 +22,11 @@ const spawk = tspawk(t)
const npmConfig = {
config: {
'ignore-scripts': false,
+ // Phase 2 gates dependency install scripts by default. `npm edit`
+ // rebuilds the edited package via `npm rebuild`, which honors the
+ // allowScripts gate, so opt every script in for these tests to exercise
+ // the editor -> rebuild -> install-script flow.
+ 'dangerously-allow-all-scripts': true,
editor: 'testeditor',
'script-shell': process.platform === 'win32' ? process.env.COMSPEC : 'sh',
},
diff --git a/deps/npm/test/lib/commands/exec.js b/deps/npm/test/lib/commands/exec.js
index 45e7634da5e..87422d1519a 100644
--- a/deps/npm/test/lib/commands/exec.js
+++ b/deps/npm/test/lib/commands/exec.js
@@ -303,6 +303,7 @@ t.test('packs from git spec', async t => {
config: {
audit: false,
yes: true,
+ 'allow-git': 'all',
},
})
try {
diff --git a/deps/npm/test/lib/commands/help.js b/deps/npm/test/lib/commands/help.js
index 3fda9fb6e07..77d05d7b504 100644
--- a/deps/npm/test/lib/commands/help.js
+++ b/deps/npm/test/lib/commands/help.js
@@ -30,7 +30,7 @@ const genManPages = (obj) => {
const mockHelp = async (t, {
man = {
5: ['npmrc', 'install', 'package-json'],
- 1: ['whoami', 'install', 'star', 'unstar', 'uninstall', 'unpublish'].map(p => `npm-${p}`),
+ 1: ['whoami', 'install', 'uninstall', 'unpublish'].map(p => `npm-${p}`),
7: ['disputes', 'config'],
},
browser = false,
@@ -153,9 +153,9 @@ t.test('npm help package.json redirects to package-json', async t => {
t.match(spawnArgs[0], /package-json\.5$/)
})
-t.test('npm help ?(un)star', async t => {
+t.test('npm help ?(un)publish with woman', async t => {
const { getArgs } = await mockHelp(t, {
- exec: ['?(un)star'],
+ exec: ['?(un)publish'],
woman: true,
})
@@ -163,7 +163,7 @@ t.test('npm help ?(un)star', async t => {
t.equal(spawnBin, 'emacsclient', 'maps woman to emacs correctly')
t.equal(spawnArgs.length, 2)
t.match(spawnArgs[1], /^\(woman-find-file '/)
- t.match(spawnArgs[1], /npm-star.1'\)$/)
+ t.match(spawnArgs[1], /npm-unpublish.1'\)$/)
})
t.test('npm help un*', async t => {
diff --git a/deps/npm/test/lib/commands/init.js b/deps/npm/test/lib/commands/init.js
index 1b59cc418c6..7e79098a558 100644
--- a/deps/npm/test/lib/commands/init.js
+++ b/deps/npm/test/lib/commands/init.js
@@ -43,7 +43,7 @@ t.test('classic npm init -y', async t => {
const pkg = require(resolve(prefix, 'package.json'))
t.equal(pkg.version, '1.0.0')
- t.equal(pkg.license, 'ISC')
+ t.equal(pkg.license, undefined, 'license is omitted by default')
})
t.test('classic interactive npm init', async t => {
@@ -273,7 +273,7 @@ t.test('workspaces', async t => {
const pkg = require(resolve(prefix, 'a/package.json'))
t.equal(pkg.name, 'a')
t.equal(pkg.version, '1.0.0')
- t.equal(pkg.license, 'ISC')
+ t.equal(pkg.license, undefined, 'license is omitted by default')
t.matchSnapshot(joinedOutput(), 'should print helper info')
@@ -306,7 +306,7 @@ t.test('workspaces', async t => {
const pkg = require(resolve(prefix, 'packages/a/package.json'))
t.equal(pkg.name, 'a')
t.equal(pkg.version, '2.0.0')
- t.equal(pkg.license, 'ISC')
+ t.equal(pkg.license, undefined, 'license is omitted by default')
})
await t.test('fail parsing top-level package.json to set workspace', async t => {
@@ -422,12 +422,12 @@ t.test('workspaces', async t => {
const pkg = require(resolve(npm.localPrefix, 'package.json'))
t.equal(pkg.version, '1.0.0')
- t.equal(pkg.license, 'ISC')
+ t.equal(pkg.license, undefined, 'license is omitted by default')
t.strictSame(pkg.workspaces, ['packages/a'])
const ws = require(resolve(npm.localPrefix, 'packages/a/package.json'))
t.equal(ws.version, '1.0.0')
- t.equal(ws.license, 'ISC')
+ t.equal(ws.license, undefined, 'license is omitted by default')
})
t.test('init pkg - installed workspace package', async t => {
const { npm } = await mockNpm(t, {
diff --git a/deps/npm/test/lib/commands/install-scripts.js b/deps/npm/test/lib/commands/install-scripts.js
index 523aba42bdd..cf7063b5957 100644
--- a/deps/npm/test/lib/commands/install-scripts.js
+++ b/deps/npm/test/lib/commands/install-scripts.js
@@ -135,7 +135,7 @@ t.test('install-scripts ls lists unreviewed packages', async t => {
})
await npm.exec('install-scripts', ['ls'])
const out = joinedOutput()
- t.match(out, /2 packages have install scripts not yet covered by allowScripts/)
+ t.match(out, /2 packages have install scripts blocked because they are not covered by allowScripts/)
t.match(out, /canvas@1\.0\.0/)
t.match(out, /sharp@1\.0\.0/)
})
diff --git a/deps/npm/test/lib/commands/install.js b/deps/npm/test/lib/commands/install.js
index 2aa56a3dcd1..3961b7f02e0 100644
--- a/deps/npm/test/lib/commands/install.js
+++ b/deps/npm/test/lib/commands/install.js
@@ -101,6 +101,118 @@ t.test('exec commands', async t => {
t.strictSame(lifecycleScripts, runOrder, 'all script ran in the correct order')
})
+ // Regression test: root `preinstall` must run before any dependency is fetched/unpacked, while `install` and `postinstall` run after reify has populated node_modules.
+ await t.test('preinstall runs before reify, post-reify scripts run after', async t => {
+ const events = []
+ const { npm, registry } = await loadMockNpm(t, {
+ config: { audit: false },
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ ...packageJson,
+ scripts: {
+ preinstall: 'echo preinstall',
+ install: 'echo install',
+ postinstall: 'echo postinstall',
+ },
+ }),
+ abbrev,
+ },
+ mocks: {
+ '@npmcli/run-script': async (opts) => {
+ // Only record scripts targeted at the project root, not any that arborist may run for dependencies during reify.
+ if (opts.path === npm.prefix) {
+ const abbrevPkg = path.join(npm.prefix, 'node_modules', 'abbrev', 'package.json')
+ events.push({ event: opts.event, depInstalled: fs.existsSync(abbrevPkg) })
+ }
+ },
+ },
+ })
+ const manifest = registry.manifest({ name: 'abbrev' })
+ await registry.package({ manifest })
+ await registry.tarball({
+ manifest: manifest.versions['1.0.0'],
+ tarball: path.join(npm.prefix, 'abbrev'),
+ })
+
+ await npm.exec('install')
+
+ const pre = events.find(e => e.event === 'preinstall')
+ const post = events.find(e => e.event === 'postinstall')
+ t.ok(pre, 'preinstall ran')
+ t.ok(post, 'postinstall ran')
+ t.equal(pre.depInstalled, false, 'preinstall runs before dependencies are installed')
+ t.equal(post.depInstalled, true, 'postinstall runs after dependencies are installed')
+ })
+
+ await t.test('without args, --ignore-scripts skips preinstall entirely', async t => {
+ const events = []
+ const { npm, registry } = await loadMockNpm(t, {
+ config: { audit: false, 'ignore-scripts': true },
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ ...packageJson,
+ scripts: {
+ preinstall: 'echo preinstall',
+ postinstall: 'echo postinstall',
+ },
+ }),
+ abbrev,
+ },
+ mocks: {
+ '@npmcli/run-script': async (opts) => {
+ if (opts.path === npm.prefix) {
+ events.push(opts.event)
+ }
+ },
+ },
+ })
+ const manifest = registry.manifest({ name: 'abbrev' })
+ await registry.package({ manifest })
+ await registry.tarball({
+ manifest: manifest.versions['1.0.0'],
+ tarball: path.join(npm.prefix, 'abbrev'),
+ })
+
+ await npm.exec('install')
+ t.strictSame(events, [], 'no root lifecycle scripts run when --ignore-scripts is set')
+ })
+
+ // Regression test: a failing root `preinstall` must short-circuit before reify runs, so dependencies never reach disk on failure. This is the cleaner failure mode the PR was motivated by; future refactors that swallow the rejection and still call reify must fail here.
+ await t.test('a failing preinstall prevents reify', async t => {
+ const events = []
+ const { npm } = await loadMockNpm(t, {
+ config: { audit: false },
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ ...packageJson,
+ scripts: {
+ preinstall: 'exit 1',
+ postinstall: 'echo postinstall',
+ },
+ }),
+ abbrev,
+ },
+ mocks: {
+ '@npmcli/run-script': async (opts) => {
+ if (opts.path === npm.prefix) {
+ events.push(opts.event)
+ if (opts.event === 'preinstall') {
+ throw Object.assign(new Error('preinstall failed'), { code: 'ELIFECYCLE' })
+ }
+ }
+ },
+ },
+ })
+
+ await t.rejects(npm.exec('install'), /preinstall failed/, 'install rejects when preinstall fails')
+ t.strictSame(events, ['preinstall'], 'only preinstall ran; no post-reify scripts')
+ t.equal(
+ fs.existsSync(path.join(npm.prefix, 'node_modules', 'abbrev', 'package.json')),
+ false,
+ 'no dependency reached disk after preinstall failure'
+ )
+ })
+
await t.test('should ignore scripts with --ignore-scripts', async t => {
const { npm, registry } = await loadMockNpm(t, {
config: {
@@ -255,6 +367,20 @@ t.test('exec commands', async t => {
)
})
+ t.test('allow-git default rejects git deps', async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { audit: false },
+ })
+ await t.rejects(
+ npm.exec('install', ['npm/npm']),
+ {
+ code: 'EALLOWGIT',
+ package: 'github:npm/npm',
+ },
+ 'no explicit allow-git config still blocks git installs'
+ )
+ })
+
t.test('allow-git=root refuses non-root git dependency', async t => {
const { npm } = await loadMockNpm(t, {
config: {
@@ -395,6 +521,24 @@ t.test('exec commands', async t => {
'user-supplied remote URL is still blocked'
)
})
+
+ t.test('allow-remote default rejects a user-supplied remote URL', async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { audit: false },
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: '@npmcli/test-package',
+ version: '1.0.0',
+ dependencies: { abbrev: 'https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz' },
+ }),
+ },
+ })
+ await t.rejects(
+ npm.exec('install', []),
+ { code: 'EALLOWREMOTE' },
+ 'no explicit allow-remote config still blocks user-supplied tarball URLs'
+ )
+ })
})
t.test('completion', async t => {
diff --git a/deps/npm/test/lib/commands/login.js b/deps/npm/test/lib/commands/login.js
index 4ebc7147e46..623bc584570 100644
--- a/deps/npm/test/lib/commands/login.js
+++ b/deps/npm/test/lib/commands/login.js
@@ -49,7 +49,6 @@ t.test('legacy', t => {
homeDir: {
'.npmrc': [
'//registry.npmjs.org/:_authToken=user',
- '//registry.npmjs.org/:always-auth=user',
'//registry.npmjs.org/:email=test-email-old@npmjs.org',
].join('\n'),
},
@@ -63,8 +62,8 @@ t.test('legacy', t => {
t.same(npm.config.get('//registry.npmjs.org/:_authToken'), 'npm_test-token')
t.same(rc(), {
'//registry.npmjs.org/:_authToken': 'npm_test-token',
- email: 'test-email-old@npmjs.org',
- }, 'should only have token and un-nerfed old email')
+ '//registry.npmjs.org/:email': 'test-email-old@npmjs.org',
+ }, 'should only have token and nerfed email')
})
t.test('scoped login default registry', async t => {
diff --git a/deps/npm/test/lib/commands/logout.js b/deps/npm/test/lib/commands/logout.js
index 840c92274ba..b18b84ca483 100644
--- a/deps/npm/test/lib/commands/logout.js
+++ b/deps/npm/test/lib/commands/logout.js
@@ -9,7 +9,7 @@ t.test('token logout - user config', async t => {
homeDir: {
'.npmrc': [
'//registry.npmjs.org/:_authToken=@foo/',
- 'other-config=true',
+ 'fund=true',
].join('\n'),
},
})
@@ -23,7 +23,7 @@ t.test('token logout - user config', async t => {
'should log message with correct registry'
)
const userRc = await fs.readFile(join(home, '.npmrc'), 'utf-8')
- t.equal(userRc.trim(), 'other-config=true')
+ t.equal(userRc.trim(), 'fund=true')
})
t.test('token scoped logout - user config', async t => {
@@ -60,7 +60,7 @@ t.test('user/pass logout - user config', async t => {
'.npmrc': [
'//registry.npmjs.org/:username=foo',
'//registry.npmjs.org/:_password=bar',
- 'other-config=true',
+ 'fund=true',
].join('\n'),
},
})
@@ -73,7 +73,7 @@ t.test('user/pass logout - user config', async t => {
)
const userRc = await fs.readFile(join(home, '.npmrc'), 'utf-8')
- t.equal(userRc.trim(), 'other-config=true')
+ t.equal(userRc.trim(), 'fund=true')
})
t.test('missing credentials', async t => {
@@ -95,7 +95,7 @@ t.test('ignore invalid scoped registry config', async t => {
homeDir: {
'.npmrc': [
'//registry.npmjs.org/:_authToken=@foo/',
- 'other-config=true',
+ 'fund=true',
].join('\n'),
},
@@ -111,7 +111,7 @@ t.test('ignore invalid scoped registry config', async t => {
'should log message with correct registry'
)
const userRc = await fs.readFile(join(home, '.npmrc'), 'utf-8')
- t.equal(userRc.trim(), 'other-config=true')
+ t.equal(userRc.trim(), 'fund=true')
})
t.test('token logout - project config', async t => {
@@ -119,13 +119,13 @@ t.test('token logout - project config', async t => {
homeDir: {
'.npmrc': [
'//registry.npmjs.org/:_authToken=@foo/',
- 'other-config=true',
+ 'fund=true',
].join('\n'),
},
prefixDir: {
'.npmrc': [
'//registry.npmjs.org/:_authToken=@bar/',
- 'other-config=true',
+ 'fund=true',
].join('\n'),
},
})
@@ -142,7 +142,7 @@ t.test('token logout - project config', async t => {
const userRc = await fs.readFile(join(home, '.npmrc'), 'utf-8')
t.equal(userRc.trim(), [
'//registry.npmjs.org/:_authToken=@foo/',
- 'other-config=true',
+ 'fund=true',
].join('\n'), 'leaves user config alone')
t.equal(
logs.verbose.byTitle('logout')[0],
@@ -150,5 +150,5 @@ t.test('token logout - project config', async t => {
'should log message with correct registry'
)
const projectRc = await fs.readFile(join(prefix, '.npmrc'), 'utf-8')
- t.equal(projectRc.trim(), 'other-config=true', 'removes project config')
+ t.equal(projectRc.trim(), 'fund=true', 'removes project config')
})
diff --git a/deps/npm/test/lib/commands/ls.js b/deps/npm/test/lib/commands/ls.js
index 899a2b81690..9f97d33f8d9 100644
--- a/deps/npm/test/lib/commands/ls.js
+++ b/deps/npm/test/lib/commands/ls.js
@@ -308,6 +308,92 @@ t.test('ls', async t => {
t.matchSnapshot(cleanCwd(result()), 'should contain overridden output')
})
+ const packageExtensionsPrefix = {
+ 'package.json': JSON.stringify({
+ name: 'test-package-extensions',
+ version: '1.0.0',
+ dependencies: { foo: '^1.0.0' },
+ packageExtensions: { 'foo@1': { dependencies: { bar: '^1.0.0' } } },
+ }),
+ node_modules: {
+ '.package-lock.json': JSON.stringify({
+ packages: {
+ 'node_modules/foo': {
+ version: '1.0.0',
+ dependencies: { bar: '^1.0.0' },
+ packageExtensionsApplied: { selector: 'foo@1', dependencies: ['bar'] },
+ },
+ 'node_modules/bar': { version: '1.0.0' },
+ },
+ }),
+ foo: {
+ 'package.json': JSON.stringify({ name: 'foo', version: '1.0.0', dependencies: { bar: '^1.0.0' } }),
+ },
+ bar: { 'package.json': JSON.stringify({ name: 'bar', version: '1.0.0' }) },
+ },
+ }
+
+ t.test('packageExtensions dep', async t => {
+ const { npm, result, ls } = await mockLs(t, { config: {}, prefixDir: packageExtensionsPrefix })
+ touchHiddenPackageLock(npm.prefix)
+ await ls.exec([])
+ t.matchSnapshot(cleanCwd(result()), 'human output annotates the extended node')
+ })
+
+ t.test('packageExtensions dep --json', async t => {
+ const { npm, result, ls } = await mockLs(t, {
+ config: { json: true },
+ prefixDir: packageExtensionsPrefix,
+ })
+ touchHiddenPackageLock(npm.prefix)
+ await ls.exec([])
+ const applied = JSON.parse(result()).dependencies.foo.packageExtensionsApplied
+ t.match(applied, { selector: 'foo@1', dependencies: ['bar'] }, 'json output includes provenance')
+ })
+
+ const npmExtensionPrefix = {
+ 'package.json': JSON.stringify({
+ name: 'test-npm-extension',
+ version: '1.0.0',
+ dependencies: { foo: '^1.0.0' },
+ }),
+ node_modules: {
+ '.package-lock.json': JSON.stringify({
+ packages: {
+ 'node_modules/foo': {
+ version: '1.0.0',
+ dependencies: { bar: '^1.0.0' },
+ npmExtensionApplied: { extensionPoint: 'transformManifest', dependencies: ['bar'] },
+ },
+ 'node_modules/bar': { version: '1.0.0' },
+ },
+ }),
+ foo: {
+ 'package.json': JSON.stringify({ name: 'foo', version: '1.0.0', dependencies: { bar: '^1.0.0' } }),
+ },
+ bar: { 'package.json': JSON.stringify({ name: 'bar', version: '1.0.0' }) },
+ },
+ }
+
+ t.test('.npm-extension dep', async t => {
+ const { npm, result, ls } = await mockLs(t, { config: {}, prefixDir: npmExtensionPrefix })
+ touchHiddenPackageLock(npm.prefix)
+ await ls.exec([])
+ t.matchSnapshot(cleanCwd(result()), 'human output annotates the transformed node')
+ })
+
+ t.test('.npm-extension dep --json', async t => {
+ const { npm, result, ls } = await mockLs(t, {
+ config: { json: true },
+ prefixDir: npmExtensionPrefix,
+ })
+ touchHiddenPackageLock(npm.prefix)
+ await ls.exec([])
+ const applied = JSON.parse(result()).dependencies.foo.npmExtensionApplied
+ t.match(applied, { extensionPoint: 'transformManifest', dependencies: ['bar'] },
+ 'json output includes provenance')
+ })
+
t.test('with filter arg', async t => {
const config = {
color: 'always',
@@ -4225,7 +4311,7 @@ t.test('ls --json', async t => {
abbrev: {
version: '1.1.1',
overridden: false,
- resolved: 'git+ssh://git@github.com/isaacs/abbrev-js.git#b8f3a2fc0c3bb8ffd8b0d0072cc6b5a3667e963c',
+ resolved: 'git+https://github.com/isaacs/abbrev-js.git#b8f3a2fc0c3bb8ffd8b0d0072cc6b5a3667e963c',
},
},
},
@@ -5332,25 +5418,6 @@ t.test('ls --install-strategy=linked', async t => {
node_modules: {
'workspace-a': t.fixture('symlink', '../packages/workspace-a'),
// workspace-b intentionally NOT linked (undeclared in dependencies)
- // The hidden lockfile a real linked install writes records only the
- // declared workspace as linked into root node_modules, so loadActual
- // resolves workspace-b's root edge as missing (the undeclared-workspace case).
- '.package-lock.json': JSON.stringify({
- lockfileVersion: 3,
- requires: true,
- packages: {
- 'node_modules/workspace-a': {
- resolved: 'packages/workspace-a',
- link: true,
- },
- 'packages/workspace-a': {
- version: '1.0.0',
- },
- 'packages/workspace-b': {
- version: '1.0.0',
- },
- },
- }),
},
},
})
@@ -5396,6 +5463,37 @@ t.test('ls --install-strategy=linked', async t => {
t.match(output, /nopt/, 'should list the dependency')
})
+ t.test('should not report devDeps of linked transitive packages as UNMET DEPENDENCY', async t => {
+ const { result, ls } = await mockLs(t, {
+ config: {
+ 'install-strategy': 'linked',
+ all: true,
+ },
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: 'test-linked-transitive',
+ version: '1.0.0',
+ dependencies: { 'pkg-a': 'file:./pkg-a' },
+ }),
+ 'pkg-a': {
+ 'package.json': JSON.stringify({
+ name: 'pkg-a',
+ version: '1.0.0',
+ devDependencies: { tap: '^16.0.0' },
+ }),
+ },
+ node_modules: {
+ 'pkg-a': t.fixture('symlink', '../pkg-a'),
+ },
+ },
+ })
+ await ls.exec([])
+ const output = cleanCwd(result())
+ t.notMatch(output, /UNMET DEPENDENCY/, 'should not report devDeps of linked transitive packages')
+ t.notMatch(output, /tap/, 'should not traverse devDeps of linked transitive packages')
+ t.match(output, /pkg-a/, 'should list the dependency')
+ })
+
t.test('should still report declared workspace as UNMET DEPENDENCY when missing', async t => {
const { ls } = await mockLs(t, {
config: {
@@ -5417,20 +5515,7 @@ t.test('ls --install-strategy=linked', async t => {
},
},
node_modules: {
- // workspace-a is declared but its symlink is missing.
- // The hidden lockfile records the workspace target without a root
- // node_modules link, so loadActual resolves the declared workspace's
- // root edge as missing (the declared-but-missing case), which must
- // still be reported as UNMET DEPENDENCY.
- '.package-lock.json': JSON.stringify({
- lockfileVersion: 3,
- requires: true,
- packages: {
- 'packages/workspace-a': {
- version: '1.0.0',
- },
- },
- }),
+ // workspace-a is declared but its symlink is missing
},
},
})
@@ -5438,3 +5523,47 @@ t.test('ls --install-strategy=linked', async t => {
'should report declared workspace as UNMET DEPENDENCY')
})
})
+
+t.test('patched dependency annotation', async t => {
+ const patchedLock = {
+ name: 'test-npm-ls',
+ version: '1.0.0',
+ lockfileVersion: 4,
+ requires: true,
+ packages: {
+ '': { name: 'test-npm-ls', version: '1.0.0', dependencies: { foo: '^1.0.0' } },
+ 'node_modules/foo': {
+ version: '1.0.0',
+ resolved: 'https://registry.npmjs.org/foo/-/foo-1.0.0.tgz',
+ integrity: 'sha512-deadbeef',
+ patched: { path: 'patches/foo@1.0.0.patch', integrity: 'sha512-abc' },
+ },
+ },
+ }
+ const prefixDir = {
+ 'package.json': JSON.stringify({
+ name: 'test-npm-ls',
+ version: '1.0.0',
+ dependencies: { foo: '^1.0.0' },
+ patchedDependencies: { 'foo@1.0.0': 'patches/foo@1.0.0.patch' },
+ }),
+ node_modules: {
+ '.package-lock.json': JSON.stringify(patchedLock),
+ foo: { 'package.json': JSON.stringify({ name: 'foo', version: '1.0.0' }) },
+ },
+ }
+
+ t.test('human output annotates the patched dependency', async t => {
+ const { npm, result, ls } = await mockLs(t, { config: {}, prefixDir })
+ touchHiddenPackageLock(npm.prefix)
+ await ls.exec([])
+ t.match(result(), /foo@1\.0\.0 \[patched: patches\/foo@1\.0\.0\.patch\]/)
+ })
+
+ t.test('json output records the patch path', async t => {
+ const { npm, result, ls } = await mockLs(t, { config: { json: true }, prefixDir })
+ touchHiddenPackageLock(npm.prefix)
+ await ls.exec([])
+ t.equal(JSON.parse(result()).dependencies.foo.patched, 'patches/foo@1.0.0.patch')
+ })
+})
diff --git a/deps/npm/test/lib/commands/pack.js b/deps/npm/test/lib/commands/pack.js
index 21d961ebef6..fa53c4da785 100644
--- a/deps/npm/test/lib/commands/pack.js
+++ b/deps/npm/test/lib/commands/pack.js
@@ -73,7 +73,7 @@ t.test('should log output as valid json', async t => {
})
t.test('should log scoped package output as valid json', async t => {
- const { npm, outputs, outputErrors, logs } = await loadMockNpm(t, {
+ const { npm, outputs, logs } = await loadMockNpm(t, {
prefixDir: {
'package.json': JSON.stringify({
name: '@myscope/test-package',
@@ -91,7 +91,6 @@ t.test('should log scoped package output as valid json', async t => {
await npm.exec('pack', [])
const filename = 'myscope-test-package-1.0.0.tgz'
t.matchSnapshot(outputs.map(JSON.parse), 'outputs as json')
- t.matchSnapshot(outputErrors, 'stderr has banners')
t.matchSnapshot(logs.notice, 'logs pack contents')
t.ok(fs.statSync(path.resolve(npm.prefix, filename)))
})
@@ -152,12 +151,8 @@ t.test('foreground-scripts defaults to true', async t => {
const filename = 'test-fg-scripts-0.0.0.tgz'
t.strictSame(
outputs,
- [
- '\n> test-fg-scripts@0.0.0 prepack\n> echo prepack!\n',
- '\n> test-fg-scripts@0.0.0 postpack\n> echo postpack!\n',
- filename,
- ],
- 'prepack and postpack log to stdout'
+ [filename],
+ 'tarball filename is the only stdout output'
)
t.matchSnapshot(logs.notice, 'logs pack contents')
t.throws(() => fs.statSync(path.resolve(npm.prefix, filename)))
@@ -256,7 +251,7 @@ t.test('invalid packument', async t => {
})
t.test('workspaces', async t => {
- const loadWorkspaces = (t) => loadMockNpm(t, {
+ const loadWorkspaces = (t, config = { workspaces: true }) => loadMockNpm(t, {
prefixDir: {
'package.json': JSON.stringify(
{
@@ -281,7 +276,7 @@ t.test('workspaces', async t => {
},
},
config: {
- workspaces: true,
+ ...config,
// TODO: this is a workaround for npm run test-all
// somehow leaking include-workspace-root
'include-workspace-root': false,
@@ -301,8 +296,10 @@ t.test('workspaces', async t => {
})
t.test('one workspace', async t => {
- const { npm, outputs } = await loadWorkspaces(t)
- await npm.exec('pack', ['workspace-a'])
+ const { npm, outputs } = await loadWorkspaces(t, {
+ workspace: ['workspace-a'],
+ })
+ await npm.exec('pack', [])
t.strictSame(outputs, ['workspace-a-1.0.0.tgz'])
})
diff --git a/deps/npm/test/lib/commands/patch.js b/deps/npm/test/lib/commands/patch.js
new file mode 100644
index 00000000000..ac409bf2d17
--- /dev/null
+++ b/deps/npm/test/lib/commands/patch.js
@@ -0,0 +1,1328 @@
+const fs = require('node:fs')
+const path = require('node:path')
+const t = require('tap')
+const Arborist = require('@npmcli/arborist')
+const pacote = require('pacote')
+
+const { loadNpmWithRegistry: loadMockNpm } = require('../../fixtures/mock-npm')
+const Patch = require('../../../lib/commands/patch.js')
+
+// Tiny dependency served by the mock registry so pacote can extract it.
+const DEP_NAME = 'patch-me'
+const DEP_VERSION = '1.0.0'
+const DEP_SRC = 'module.exports = function () { return "original" }\n'
+
+// On-disk tarball contents for the dependency.
+const depTarball = {
+ 'package.json': JSON.stringify({ name: DEP_NAME, version: DEP_VERSION }),
+ 'index.js': DEP_SRC,
+}
+
+// Root project package.json depending on the patchable dep.
+const rootPackageJson = {
+ name: 'root-project',
+ version: '1.0.0',
+ dependencies: { [DEP_NAME]: `^${DEP_VERSION}` },
+}
+
+// Lockfile pre-resolving the dep so installs/reifies are deterministic.
+const rootPackageLock = {
+ name: 'root-project',
+ version: '1.0.0',
+ lockfileVersion: 3,
+ requires: true,
+ packages: {
+ '': {
+ name: 'root-project',
+ version: '1.0.0',
+ dependencies: { [DEP_NAME]: `^${DEP_VERSION}` },
+ },
+ [`node_modules/${DEP_NAME}`]: {
+ version: DEP_VERSION,
+ resolved: `https://registry.npmjs.org/${DEP_NAME}/-/${DEP_NAME}-${DEP_VERSION}.tgz`,
+ },
+ },
+}
+
+// Persist the manifest and tarball so the many extract and reify passes (add, commit baseline, reify, rm reify, install) all find a tarball without having to count requests precisely.
+const setupDep = async (npm, registry) => {
+ const manifest = registry.manifest({ name: DEP_NAME, versions: [DEP_VERSION] })
+ const dist = new URL(manifest.versions[DEP_VERSION].dist.tarball)
+ const tar = await pacote.tarball(path.join(npm.prefix, 'dep-tarball'), { Arborist })
+ registry.nock.get(`/${DEP_NAME}`).reply(200, manifest).persist()
+ registry.nock.get(dist.pathname).reply(200, tar).persist()
+ return manifest
+}
+
+const basePrefix = () => ({
+ 'dep-tarball': depTarball,
+ 'package.json': JSON.stringify(rootPackageJson),
+ 'package-lock.json': JSON.stringify(rootPackageLock),
+})
+
+const readJson = file => JSON.parse(fs.readFileSync(file, 'utf8'))
+
+t.test('no args rejects with EUSAGE', async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: basePrefix(),
+ })
+ await t.rejects(npm.exec('patch', []), { code: 'EUSAGE' }, 'bare npm patch is a usage error')
+})
+
+t.test('add with no pkg rejects with EUSAGE', async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: basePrefix(),
+ })
+ await t.rejects(npm.exec('patch', ['add']), { code: 'EUSAGE' })
+})
+
+t.test('add rejects non-registry spec with EPATCHNONREGISTRY', async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: basePrefix(),
+ })
+ await t.rejects(
+ npm.exec('patch', ['add', 'file:./dep-tarball']),
+ { code: 'EPATCHNONREGISTRY' },
+ 'file: spec is rejected'
+ )
+})
+
+t.test('add accepts an edgeless installed node (extraneous / linked store)', async t => {
+ // an installed-but-undeclared dep has no edges, so isRegistryDependency is false;
+ // it must not be misread as non-registry the way a linked store node or extraneous install would be
+ const { npm, joinedOutput, registry } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ strictRegistryNock: false,
+ prefixDir: {
+ 'dep-tarball': depTarball,
+ 'package.json': JSON.stringify({ name: 'root-project', version: '1.0.0' }),
+ node_modules: {
+ [DEP_NAME]: { 'package.json': JSON.stringify({ name: DEP_NAME, version: DEP_VERSION }) },
+ },
+ },
+ })
+ await setupDep(npm, registry)
+ await npm.exec('patch', ['add', DEP_NAME])
+ t.match(joinedOutput(), /You can now edit the following directory: /, 'edgeless node is patchable')
+})
+
+t.test('full round-trip: install, add, edit, commit, ls, rm', async t => {
+ const { npm, joinedOutput, registry, outputs } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ strictRegistryNock: false,
+ prefixDir: basePrefix(),
+ })
+ await setupDep(npm, registry)
+
+ // install the dep so it is present on disk
+ await npm.exec('install', [])
+ const installedIndex = path.join(npm.prefix, 'node_modules', DEP_NAME, 'index.js')
+ t.equal(fs.readFileSync(installedIndex, 'utf8'), DEP_SRC, 'installed clean')
+
+ // npm patch add <dep> prints the edit dir and commit hint
+ outputs.length = 0
+ await npm.exec('patch', ['add', DEP_NAME])
+ const addOut = joinedOutput()
+ t.match(addOut, /You can now edit the following directory: /, 'prints edit dir line')
+ t.match(addOut, /When done, run: npm patch commit /, 'prints commit hint line')
+
+ const editDirMatch = addOut.match(/You can now edit the following directory: (.+)/)
+ const editDir = editDirMatch[1].trim()
+ t.ok(fs.existsSync(path.join(editDir, 'package.json')), 'extracted package.json to edit dir')
+
+ // edit a file in the printed edit dir
+ const edited = 'module.exports = function () { return "patched" }\n'
+ fs.writeFileSync(path.join(editDir, 'index.js'), edited)
+
+ // npm patch commit <dir>
+ outputs.length = 0
+ await npm.exec('patch', ['commit', editDir])
+
+ // patches/<dep>@<ver>.patch exists
+ const patchFile = path.join(npm.prefix, 'patches', `${DEP_NAME}@${DEP_VERSION}.patch`)
+ t.ok(fs.existsSync(patchFile), 'patch file written under patches/')
+ t.match(fs.readFileSync(patchFile, 'utf8'), /patched/, 'patch file contains the edit')
+
+ // package.json has the relative patchedDependencies entry
+ const pkg = readJson(path.join(npm.prefix, 'package.json'))
+ t.same(
+ pkg.patchedDependencies,
+ { [`${DEP_NAME}@${DEP_VERSION}`]: `patches/${DEP_NAME}@${DEP_VERSION}.patch` },
+ 'patchedDependencies has the relative posix entry'
+ )
+
+ // package-lock.json: lockfileVersion 4 and packages[node_modules/<dep>].patched
+ const lock = readJson(path.join(npm.prefix, 'package-lock.json'))
+ t.equal(lock.lockfileVersion, 4, 'lockfile bumped to v4')
+ const lockNode = lock.packages[`node_modules/${DEP_NAME}`]
+ t.ok(lockNode.patched, 'lockfile node has patched block')
+ t.equal(lockNode.patched.path, `patches/${DEP_NAME}@${DEP_VERSION}.patch`, 'patched.path set')
+ t.match(lockNode.patched.integrity, /^sha512-/, 'patched.integrity is an SSRI')
+
+ // the installed file on disk contains the edit
+ t.equal(fs.readFileSync(installedIndex, 'utf8'), edited, 'installed file is patched on disk')
+
+ // edit dir removed by default
+ t.notOk(fs.existsSync(editDir), 'edit dir removed when keep-edit-dir not set')
+
+ // npm patch ls lists the entry
+ outputs.length = 0
+ await npm.exec('patch', ['ls'])
+ const lsOut = joinedOutput()
+ t.match(lsOut, new RegExp(`patches/${DEP_NAME}@${DEP_VERSION}\\.patch`), 'ls shows patch path')
+ t.match(lsOut, new RegExp(`${DEP_NAME}@${DEP_VERSION}`), 'ls shows selector')
+ t.match(lsOut, /\(1 node\)/, 'ls shows node count')
+
+ // npm patch rm removes the entry from package.json and deletes the file
+ outputs.length = 0
+ await npm.exec('patch', ['rm', DEP_NAME])
+ const pkgAfter = readJson(path.join(npm.prefix, 'package.json'))
+ t.notOk(pkgAfter.patchedDependencies, 'patchedDependencies removed from package.json')
+ t.notOk(fs.existsSync(patchFile), 'patch file deleted')
+
+ // rm clears the patch record from the lockfile and reverts the installed file
+ const lockAfter = readJson(path.join(npm.prefix, 'package-lock.json'))
+ t.notOk(
+ lockAfter.packages[`node_modules/${DEP_NAME}`].patched,
+ 'lockfile patched block removed'
+ )
+ t.equal(
+ fs.readFileSync(installedIndex, 'utf8'),
+ DEP_SRC,
+ 'installed file reverted to original'
+ )
+})
+
+t.test('bare form routes to add', async t => {
+ const { npm, joinedOutput, registry } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ strictRegistryNock: false,
+ prefixDir: basePrefix(),
+ })
+ await setupDep(npm, registry)
+ await npm.exec('install', [])
+
+ // npm patch <dep> behaves like npm patch add <dep>
+ await npm.exec('patch', [DEP_NAME])
+ t.match(joinedOutput(), /You can now edit the following directory: /, 'bare form extracts like add')
+})
+
+t.test('npm ci rejects patch path drift from the lockfile', async t => {
+ const { npm, registry } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ strictRegistryNock: false,
+ prefixDir: basePrefix(),
+ })
+ await setupDep(npm, registry)
+ await npm.exec('install', [])
+
+ // commit a real patch so the lockfile records patched.path
+ const editDir = path.join(npm.prefix, 'edit')
+ await pacote.extract(`${DEP_NAME}@${DEP_VERSION}`, editDir, npm.flatOptions)
+ fs.writeFileSync(path.join(editDir, 'index.js'), 'module.exports = () => "patched"\n')
+ await npm.exec('patch', ['commit', editDir])
+
+ // move the patch file and repoint package.json without updating the lockfile
+ const pkgPath = path.join(npm.prefix, 'package.json')
+ const pkg = readJson(pkgPath)
+ const key = `${DEP_NAME}@${DEP_VERSION}`
+ const oldPath = path.join(npm.prefix, pkg.patchedDependencies[key])
+ const newRel = 'patches/renamed.patch'
+ fs.renameSync(oldPath, path.join(npm.prefix, newRel))
+ pkg.patchedDependencies[key] = newRel
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg))
+
+ await t.rejects(
+ npm.exec('ci', []),
+ /package-lock\.json are in sync/,
+ 'npm ci refuses when the patch path diverges from the lockfile'
+ )
+})
+
+t.test('rm with no registered patch rejects with EPATCHNOTFOUND', async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: basePrefix(),
+ })
+ await t.rejects(
+ npm.exec('patch', ['rm', DEP_NAME]),
+ { code: 'EPATCHNOTFOUND' },
+ 'rm errors when nothing matches'
+ )
+})
+
+t.test('ls with no patches prints nothing', async t => {
+ const { npm, joinedOutput } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: basePrefix(),
+ })
+ await npm.exec('patch', ['ls'])
+ t.equal(joinedOutput(), '', 'no output when no patchedDependencies')
+})
+
+t.test('ls with no package.json prints nothing', async t => {
+ const { npm, joinedOutput } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: {},
+ })
+ await npm.exec('patch', ['ls'])
+ t.equal(joinedOutput(), '', 'no output and no crash without a package.json')
+})
+
+t.test('add with edit-dir config uses that directory', async t => {
+ const { npm, joinedOutput, registry } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ strictRegistryNock: false,
+ prefixDir: basePrefix(),
+ })
+ await setupDep(npm, registry)
+ await npm.exec('install', [])
+
+ const customDir = path.join(npm.prefix, 'my-edit-dir')
+ npm.config.set('edit-dir', customDir)
+ await npm.exec('patch', ['add', DEP_NAME])
+ t.match(joinedOutput(), new RegExp('my-edit-dir'), 'uses configured edit dir')
+ t.ok(fs.existsSync(path.join(customDir, 'package.json')), 'extracted into configured dir')
+})
+
+t.test('add: not-installed bare name rejects with EPATCHNOTINSTALLED', async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: {
+ 'package.json': JSON.stringify({ name: 'root-project', version: '1.0.0' }),
+ },
+ })
+ await t.rejects(
+ npm.exec('patch', ['add', DEP_NAME]),
+ { code: 'EPATCHNOTINSTALLED' },
+ 'errors when no installed version and no explicit version'
+ )
+})
+
+t.test('add: ambiguous when multiple versions installed', async t => {
+ // root-direct 1.0.0 plus two nested 2.0.0 copies, so the dedup guard and the root-dependant label are both exercised while listing the ambiguity
+ const nestedDep = v => ({
+ node_modules: { [DEP_NAME]: { 'package.json': JSON.stringify({ name: DEP_NAME, version: v }) } },
+ })
+ const { npm } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: 'root-project',
+ version: '1.0.0',
+ dependencies: { [DEP_NAME]: '1.0.0', b: '1.0.0', c: '1.0.0' },
+ }),
+ node_modules: {
+ [DEP_NAME]: { 'package.json': JSON.stringify({ name: DEP_NAME, version: '1.0.0' }) },
+ b: {
+ 'package.json': JSON.stringify({ name: 'b', version: '1.0.0', dependencies: { [DEP_NAME]: '2.0.0' } }),
+ ...nestedDep('2.0.0'),
+ },
+ c: {
+ 'package.json': JSON.stringify({ name: 'c', version: '1.0.0', dependencies: { [DEP_NAME]: '2.0.0' } }),
+ ...nestedDep('2.0.0'),
+ },
+ },
+ },
+ })
+ await t.rejects(
+ npm.exec('patch', ['add', DEP_NAME]),
+ { code: 'EPATCHAMBIGUOUS' },
+ 'errors when multiple versions are installed for a bare name'
+ )
+})
+
+t.test('add: an installed file: dependency is rejected as non-registry', async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: 'root-project', version: '1.0.0', dependencies: { [DEP_NAME]: 'file:./local' },
+ }),
+ local: { 'package.json': JSON.stringify({ name: DEP_NAME, version: DEP_VERSION }) },
+ node_modules: {
+ [DEP_NAME]: { 'package.json': JSON.stringify({ name: DEP_NAME, version: DEP_VERSION }) },
+ },
+ },
+ })
+ await t.rejects(
+ npm.exec('patch', ['add', DEP_NAME]),
+ { code: 'EPATCHNONREGISTRY' },
+ 'cannot patch a file: dependency that is already installed'
+ )
+})
+
+t.test('add: a version installed as both registry and file: is rejected', async t => {
+ // one consumer pulls the registry copy, another pulls a file: copy of the same version;
+ // the file: edge must still cause a rejection even though a registry edge also exists
+ const { npm } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: 'root-project',
+ version: '1.0.0',
+ dependencies: { [DEP_NAME]: '1.0.0', b: '1.0.0' },
+ }),
+ local: { 'package.json': JSON.stringify({ name: DEP_NAME, version: DEP_VERSION }) },
+ node_modules: {
+ [DEP_NAME]: { 'package.json': JSON.stringify({ name: DEP_NAME, version: DEP_VERSION }) },
+ b: {
+ 'package.json': JSON.stringify({
+ name: 'b', version: '1.0.0', dependencies: { [DEP_NAME]: 'file:../../local' },
+ }),
+ node_modules: {
+ [DEP_NAME]: { 'package.json': JSON.stringify({ name: DEP_NAME, version: DEP_VERSION }) },
+ },
+ },
+ },
+ },
+ })
+ await t.rejects(
+ npm.exec('patch', ['add', DEP_NAME]),
+ { code: 'EPATCHNONREGISTRY' },
+ 'a version with any file: consumer cannot be patched'
+ )
+})
+
+t.test('add: a range matching multiple installed versions is ambiguous', async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: 'root-project',
+ version: '1.0.0',
+ dependencies: { [DEP_NAME]: '1.0.0', b: '1.0.0' },
+ }),
+ node_modules: {
+ [DEP_NAME]: { 'package.json': JSON.stringify({ name: DEP_NAME, version: '1.0.0' }) },
+ b: {
+ 'package.json': JSON.stringify({ name: 'b', version: '1.0.0', dependencies: { [DEP_NAME]: '2.0.0' } }),
+ node_modules: { [DEP_NAME]: { 'package.json': JSON.stringify({ name: DEP_NAME, version: '2.0.0' }) } },
+ },
+ },
+ },
+ })
+ await t.rejects(
+ npm.exec('patch', ['add', `${DEP_NAME}@>=1.0.0`]),
+ { code: 'EPATCHAMBIGUOUS' },
+ 'a range matching two installed versions errors'
+ )
+})
+
+t.test('add: explicit exact version is honored without install', async t => {
+ const { npm, joinedOutput, registry } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ strictRegistryNock: false,
+ prefixDir: basePrefix(),
+ })
+ await setupDep(npm, registry)
+ // no install; explicit exact version path returns { name, version } directly
+ await npm.exec('patch', ['add', `${DEP_NAME}@${DEP_VERSION}`])
+ t.match(joinedOutput(), /You can now edit the following directory: /, 'extracts the exact version')
+})
+
+t.test('commit: no edit dir arg rejects with EUSAGE', async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: basePrefix(),
+ })
+ await t.rejects(npm.exec('patch', ['commit']), { code: 'EUSAGE' })
+})
+
+t.test('commit: missing package.json in edit dir rejects with EPATCHNOEDITDIR', async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: { 'package.json': JSON.stringify(rootPackageJson), 'empty-dir': {} },
+ })
+ await t.rejects(
+ npm.exec('patch', ['commit', path.join(npm.prefix, 'empty-dir')]),
+ { code: 'EPATCHNOEDITDIR' }
+ )
+})
+
+t.test('commit: no changes logs a warning and does not write a patch', async t => {
+ const { npm, registry } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ strictRegistryNock: false,
+ prefixDir: basePrefix(),
+ })
+ await setupDep(npm, registry)
+ await npm.exec('install', [])
+
+ // add then commit without editing anything
+ await npm.exec('patch', ['add', DEP_NAME])
+ // the edit dir is a tmp path; re-extract a fresh clean copy to a known dir
+ const editDir = path.join(npm.prefix, 'clean-edit')
+ await pacote.extract(`${DEP_NAME}@${DEP_VERSION}`, editDir, npm.flatOptions)
+
+ await npm.exec('patch', ['commit', editDir])
+ t.notOk(
+ fs.existsSync(path.join(npm.prefix, 'patches', `${DEP_NAME}@${DEP_VERSION}.patch`)),
+ 'no patch file written when there are no changes'
+ )
+ const pkg = readJson(path.join(npm.prefix, 'package.json'))
+ t.notOk(pkg.patchedDependencies, 'no patchedDependencies added when nothing changed')
+})
+
+t.test('commit: only package.json changed warns and writes no patch', async t => {
+ const { npm, logs, registry } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ strictRegistryNock: false,
+ prefixDir: basePrefix(),
+ })
+ await setupDep(npm, registry)
+ await npm.exec('install', [])
+
+ await npm.exec('patch', ['add', DEP_NAME])
+ const editDir = path.join(npm.prefix, 'clean-edit')
+ await pacote.extract(`${DEP_NAME}@${DEP_VERSION}`, editDir, npm.flatOptions)
+
+ // edit only package.json, which is excluded from patches
+ const pkgPath = path.join(editDir, 'package.json')
+ const edited = readJson(pkgPath)
+ edited.description = 'edited'
+ fs.writeFileSync(pkgPath, JSON.stringify(edited))
+
+ await npm.exec('patch', ['commit', editDir])
+ t.notOk(
+ fs.existsSync(path.join(npm.prefix, 'patches', `${DEP_NAME}@${DEP_VERSION}.patch`)),
+ 'no patch file written when only package.json changed'
+ )
+ t.match(logs.warn.join('\n'), /only package.json changed/, 'warns package.json is not patchable')
+})
+
+t.test('commit: package.json change alongside code is dropped with a warning', async t => {
+ const { npm, logs, registry } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ strictRegistryNock: false,
+ prefixDir: basePrefix(),
+ })
+ await setupDep(npm, registry)
+ await npm.exec('install', [])
+
+ await npm.exec('patch', ['add', DEP_NAME])
+ const editDir = path.join(npm.prefix, 'clean-edit')
+ await pacote.extract(`${DEP_NAME}@${DEP_VERSION}`, editDir, npm.flatOptions)
+
+ // edit both package.json and a real file
+ const pkgPath = path.join(editDir, 'package.json')
+ const edited = readJson(pkgPath)
+ edited.description = 'edited'
+ fs.writeFileSync(pkgPath, JSON.stringify(edited))
+ fs.writeFileSync(path.join(editDir, 'index.js'), 'module.exports = () => "patched"\n')
+
+ await npm.exec('patch', ['commit', editDir])
+ const patchPath = path.join(npm.prefix, 'patches', `${DEP_NAME}@${DEP_VERSION}.patch`)
+ t.ok(fs.existsSync(patchPath), 'patch written for the code change')
+ t.notMatch(fs.readFileSync(patchPath, 'utf8'), 'package.json', 'patch excludes package.json')
+ t.match(
+ logs.warn.join('\n'),
+ /changes to package.json are not included/,
+ 'warns the package.json edit was ignored'
+ )
+})
+
+// Serve several versions of a package, each with its own index.js source.
+const setupVersions = async (npm, registry, name, sources) => {
+ const versions = Object.keys(sources)
+ const manifest = registry.manifest({ name, versions })
+ for (const version of versions) {
+ const dir = path.join(npm.prefix, `pkg-${name}-${version}`)
+ fs.mkdirSync(dir, { recursive: true })
+ fs.writeFileSync(path.join(dir, 'package.json'), JSON.stringify({ name, version }))
+ fs.writeFileSync(path.join(dir, 'index.js'), sources[version])
+ const tar = await pacote.tarball(dir, { Arborist })
+ const { pathname } = new URL(manifest.versions[version].dist.tarball)
+ registry.nock.get(pathname).reply(200, tar).persist()
+ }
+ registry.nock.get(`/${name}`).reply(200, manifest).persist()
+ return manifest
+}
+
+const rootWith = dep => ({
+ 'package.json': JSON.stringify({
+ name: 'root-project', version: '1.0.0', dependencies: dep,
+ }),
+})
+
+const updatePrefix = patchedDependencies => ({
+ 'package.json': JSON.stringify({
+ name: 'root-project', version: '1.0.0', patchedDependencies,
+ }),
+})
+
+t.test('update --to rebases an exact patch onto a new version', async t => {
+ const name = 'upd-exact'
+ const { npm, joinedOutput, outputs, registry } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ strictRegistryNock: false,
+ prefixDir: rootWith({ [name]: '^1.0.0' }),
+ })
+ // v2 differs from v1 only on the last line; the patch edits the first line -> clean 3-way merge
+ await setupVersions(npm, registry, name, { '1.0.0': 'a\nb\nc\n', '2.0.0': 'a\nb\nCC\n' })
+ await npm.exec('install', [])
+
+ outputs.length = 0
+ await npm.exec('patch', ['add', name])
+ const editDir = joinedOutput().match(/directory: (.+)/)[1].trim()
+ fs.writeFileSync(path.join(editDir, 'index.js'), 'AA\nb\nc\n')
+ await npm.exec('patch', ['commit', editDir])
+
+ npm.config.set('to', '2.0.0')
+ await npm.exec('patch', ['update', name])
+
+ const pkg = readJson(path.join(npm.prefix, 'package.json'))
+ t.same(pkg.patchedDependencies, { [`${name}@2.0.0`]: `patches/${name}@2.0.0.patch` },
+ 'selector renamed to the new version')
+ t.notOk(fs.existsSync(path.join(npm.prefix, 'patches', `${name}@1.0.0.patch`)), 'old patch file removed')
+ t.match(fs.readFileSync(path.join(npm.prefix, 'patches', `${name}@2.0.0.patch`), 'utf8'), /\+AA/,
+ 'rebased patch keeps the edit')
+})
+
+t.test('update --to warns when the target version is not installed', async t => {
+ const name = 'upd-uninstalled'
+ const { npm, joinedOutput, outputs, registry, logs } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ strictRegistryNock: false,
+ prefixDir: rootWith({ [name]: '1.0.0' }),
+ })
+ await setupVersions(npm, registry, name, { '1.0.0': 'a\nb\nc\n', '2.0.0': 'a\nb\nCC\n' })
+ await npm.exec('install', [])
+
+ outputs.length = 0
+ await npm.exec('patch', ['add', name])
+ const editDir = joinedOutput().match(/directory: (.+)/)[1].trim()
+ fs.writeFileSync(path.join(editDir, 'index.js'), 'AA\nb\nc\n')
+ await npm.exec('patch', ['commit', editDir])
+
+ // dependency is pinned to 1.0.0, so rebasing onto 2.0.0 targets an uninstalled version
+ npm.config.set('to', '2.0.0')
+ await npm.exec('patch', ['update', name])
+
+ t.match(logs.warn.byTitle('patch'),
+ [new RegExp(`${name}@2\\.0\\.0 is not installed.*EPATCHUNUSED`)],
+ 'warns that the target version is not installed')
+})
+
+t.test('update --to is silent when the target version is installed', async t => {
+ const name = 'upd-installed'
+ const { npm, registry, logs } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ strictRegistryNock: false,
+ prefixDir: rootWith({ [name]: '^2.0.0' }),
+ })
+ await setupVersions(npm, registry, name, { '1.0.0': 'x\n', '2.0.0': 'x\n' })
+ // 2.0.0 is the installed version; hand-author a patch against 1.0.0 that adds a file (applies to any version)
+ await npm.exec('install', [])
+ fs.mkdirSync(path.join(npm.prefix, 'patches'), { recursive: true })
+ fs.writeFileSync(path.join(npm.prefix, 'patches', `${name}@1.0.0.patch`),
+ '--- /dev/null\t\n+++ b/EXTRA.txt\t\n@@ -0,0 +1 @@\n+extra\n')
+ const pkg = readJson(path.join(npm.prefix, 'package.json'))
+ pkg.patchedDependencies = { [`${name}@1.0.0`]: `patches/${name}@1.0.0.patch` }
+ fs.writeFileSync(path.join(npm.prefix, 'package.json'), JSON.stringify(pkg))
+
+ // rebasing onto 2.0.0, which is installed, must not warn
+ npm.config.set('to', '2.0.0')
+ await npm.exec('patch', ['update', name])
+ t.strictSame(logs.warn.byTitle('patch'), [], 'no warning when --to matches the installed version')
+})
+
+t.test('update auto-detects the new version and drops a fully-shadowed range', async t => {
+ const name = 'upd-range'
+ const { npm, joinedOutput, outputs, registry } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ strictRegistryNock: false,
+ prefixDir: rootWith({ [name]: '1.0.0' }),
+ })
+ await setupVersions(npm, registry, name, { '1.0.0': 'x\n', '1.1.0': 'x\n' })
+ await npm.exec('install', [])
+ // a patch that adds a file applies to any version, so the dep can float
+ outputs.length = 0
+ await npm.exec('patch', ['add', name])
+ const editDir = joinedOutput().match(/directory: (.+)/)[1].trim()
+ fs.writeFileSync(path.join(editDir, 'EXTRA.txt'), 'extra\n')
+ await npm.exec('patch', ['commit', editDir])
+
+ // turn the exact selector into a range and float the lockfile to 1.1.0
+ const pkg = readJson(path.join(npm.prefix, 'package.json'))
+ pkg.dependencies[name] = '^1.0.0'
+ pkg.patchedDependencies = { [`${name}@^1.0.0`]: pkg.patchedDependencies[`${name}@1.0.0`] }
+ fs.writeFileSync(path.join(npm.prefix, 'package.json'), JSON.stringify(pkg))
+ // clear the resolved tree so a fresh install floats the range up to 1.1.0
+ fs.rmSync(path.join(npm.prefix, 'package-lock.json'))
+ fs.rmSync(path.join(npm.prefix, 'node_modules'), { recursive: true, force: true })
+ await npm.exec('install', [])
+
+ await npm.exec('patch', ['update', name])
+ t.same(readJson(path.join(npm.prefix, 'package.json')).patchedDependencies,
+ { [`${name}@1.1.0`]: `patches/${name}@1.1.0.patch` }, 'shadowed range dropped, new exact entry added')
+})
+
+t.test('update conflict leaves an edit dir; commit finalizes the rename', async t => {
+ const name = 'upd-conflict'
+ const { npm, joinedOutput, outputs, registry } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ strictRegistryNock: false,
+ prefixDir: rootWith({ [name]: '^1.0.0' }),
+ })
+ // v2 changes the same line the patch edits -> conflict
+ await setupVersions(npm, registry, name, { '1.0.0': 'a\nb\nc\n', '2.0.0': 'a\nBB\nc\n' })
+ await npm.exec('install', [])
+ outputs.length = 0
+ await npm.exec('patch', ['add', name])
+ const addDir = joinedOutput().match(/directory: (.+)/)[1].trim()
+ fs.writeFileSync(path.join(addDir, 'index.js'), 'a\nMINE\nc\n')
+ await npm.exec('patch', ['commit', addDir])
+
+ npm.config.set('to', '2.0.0')
+ outputs.length = 0
+ await npm.exec('patch', ['update', name])
+ const editDir = joinedOutput().match(/Resolve the conflicts in: (.+)/)[1].trim()
+ t.ok(fs.existsSync(path.join(editDir, '.npm-patch-update.json')), 'cleanup marker written')
+ t.match(fs.readFileSync(path.join(editDir, 'index.js'), 'utf8'), /<<<<<<</, 'conflict markers present')
+ t.same(readJson(path.join(npm.prefix, 'package.json')).patchedDependencies,
+ { [`${name}@1.0.0`]: `patches/${name}@1.0.0.patch` }, 'manifest unchanged on conflict')
+
+ // resolve by keeping our line, then commit
+ let src = fs.readFileSync(path.join(editDir, 'index.js'), 'utf8')
+ src = src.replace(/<<<<<<<[^\n]*\n[\s\S]*?=======\n([\s\S]*?)>>>>>>>[^\n]*\n/, '$1')
+ fs.writeFileSync(path.join(editDir, 'index.js'), src)
+ await npm.exec('patch', ['commit', editDir])
+ t.same(readJson(path.join(npm.prefix, 'package.json')).patchedDependencies,
+ { [`${name}@2.0.0`]: `patches/${name}@2.0.0.patch` }, 'renamed after the resolving commit')
+ t.notOk(fs.existsSync(path.join(npm.prefix, 'patches', `${name}@1.0.0.patch`)), 'old patch file removed')
+})
+
+t.test('a no-op resolving commit keeps the marker so a corrected retry still finalizes', async t => {
+ const name = 'upd-noop-retry'
+ const { npm, joinedOutput, outputs, registry } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ strictRegistryNock: false,
+ prefixDir: rootWith({ [name]: '^1.0.0' }),
+ })
+ await setupVersions(npm, registry, name, { '1.0.0': 'a\nb\nc\n', '2.0.0': 'a\nBB\nc\n' })
+ await npm.exec('install', [])
+ outputs.length = 0
+ await npm.exec('patch', ['add', name])
+ const addDir = joinedOutput().match(/directory: (.+)/)[1].trim()
+ fs.writeFileSync(path.join(addDir, 'index.js'), 'a\nMINE\nc\n')
+ await npm.exec('patch', ['commit', addDir])
+
+ npm.config.set('to', '2.0.0')
+ outputs.length = 0
+ await npm.exec('patch', ['update', name])
+ const editDir = joinedOutput().match(/Resolve the conflicts in: (.+)/)[1].trim()
+ const markerPath = path.join(editDir, '.npm-patch-update.json')
+ t.ok(fs.existsSync(markerPath), 'marker written on conflict')
+
+ // resolve to the new version verbatim (no net change) and commit: a no-op
+ let src = fs.readFileSync(path.join(editDir, 'index.js'), 'utf8')
+ src = src.replace(/<<<<<<<[^\n]*\n([\s\S]*?)=======\n[\s\S]*?>>>>>>>[^\n]*\n/, '$1')
+ fs.writeFileSync(path.join(editDir, 'index.js'), src)
+ await npm.exec('patch', ['commit', editDir])
+ t.ok(fs.existsSync(markerPath), 'marker survives a no-op commit so the update context is not lost')
+
+ // now resolve properly and commit again: must finalize the rename, not throw EPATCHUNUSED on the uninstalled 2.0.0
+ fs.writeFileSync(path.join(editDir, 'index.js'), src.replace('BB', 'MINE'))
+ await npm.exec('patch', ['commit', editDir])
+ t.same(readJson(path.join(npm.prefix, 'package.json')).patchedDependencies,
+ { [`${name}@2.0.0`]: `patches/${name}@2.0.0.patch` }, 'finalized: old selector dropped, new one added')
+})
+
+t.test('update conflict on a name-only selector forks and commits without EPATCHUNUSED', async t => {
+ const name = 'upd-rconflict'
+ const { npm, joinedOutput, outputs, registry } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ strictRegistryNock: false,
+ prefixDir: rootWith({ [name]: '^1.0.0' }),
+ })
+ await setupVersions(npm, registry, name, { '1.0.0': 'a\nb\nc\n', '2.0.0': 'a\nBB\nc\n' })
+ await npm.exec('install', [])
+ outputs.length = 0
+ await npm.exec('patch', ['add', name])
+ const addDir = joinedOutput().match(/directory: (.+)/)[1].trim()
+ fs.writeFileSync(path.join(addDir, 'index.js'), 'a\nMINE\nc\n')
+ await npm.exec('patch', ['commit', addDir])
+ // turn it into a name-only selector so the conflict path takes the fork (non-exact) branch
+ const pkg = readJson(path.join(npm.prefix, 'package.json'))
+ pkg.patchedDependencies = { [name]: pkg.patchedDependencies[`${name}@1.0.0`] }
+ fs.writeFileSync(path.join(npm.prefix, 'package.json'), JSON.stringify(pkg))
+
+ // --to 2.0.0 is not installed and conflicts; the fork must still leave a marker
+ npm.config.set('to', '2.0.0')
+ outputs.length = 0
+ await npm.exec('patch', ['update', name])
+ const editDir = joinedOutput().match(/Resolve the conflicts in: (.+)/)[1].trim()
+ t.same(readJson(path.join(editDir, '.npm-patch-update.json')), { name, removeKey: null },
+ 'a fork still writes a marker, with removeKey null')
+
+ // resolve and commit: must finalize metadata-only, not fail with EPATCHUNUSED on the uninstalled 2.0.0
+ let src = fs.readFileSync(path.join(editDir, 'index.js'), 'utf8')
+ src = src.replace(/<<<<<<<[^\n]*\n[\s\S]*?=======\n([\s\S]*?)>>>>>>>[^\n]*\n/, '$1')
+ fs.writeFileSync(path.join(editDir, 'index.js'), src)
+ await npm.exec('patch', ['commit', editDir])
+
+ const after = readJson(path.join(npm.prefix, 'package.json')).patchedDependencies
+ t.ok(after[name], 'the name-only selector is kept')
+ t.ok(after[`${name}@2.0.0`], 'the new exact selector is added')
+})
+
+t.test('update: no registered patch rejects with EPATCHNOTFOUND', async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: { 'package.json': JSON.stringify({ name: 'r', version: '1.0.0' }) },
+ })
+ await t.rejects(npm.exec('patch', ['update', 'nope']), { code: 'EPATCHNOTFOUND' })
+})
+
+t.test('update: an unknown explicit selector rejects with EPATCHNOTFOUND', async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: updatePrefix({ 'foo@1.0.0': 'patches/foo@1.0.0.patch' }),
+ })
+ await t.rejects(npm.exec('patch', ['update', 'foo@9.9.9']), { code: 'EPATCHNOTFOUND' })
+})
+
+t.test('update: multiple entries for a bare name reject with EPATCHAMBIGUOUS', async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: updatePrefix({ 'foo@1.0.0': 'patches/foo@1.0.0.patch', 'foo@2.0.0': 'patches/foo@2.0.0.patch' }),
+ })
+ await t.rejects(npm.exec('patch', ['update', 'foo']), { code: 'EPATCHAMBIGUOUS' })
+})
+
+t.test('update: an unparseable patch filename rejects with EPATCHBASE', async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: updatePrefix({ 'foo@1.0.0': 'patches/custom.patch' }),
+ })
+ await t.rejects(npm.exec('patch', ['update', 'foo@1.0.0']), { code: 'EPATCHBASE' })
+})
+
+t.test('update: --to equal to the baseline rejects with EPATCHNOOP', async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: updatePrefix({ 'foo@1.0.0': 'patches/foo@1.0.0.patch' }),
+ })
+ npm.config.set('to', '1.0.0')
+ await t.rejects(npm.exec('patch', ['update', 'foo@1.0.0']), { code: 'EPATCHNOOP' })
+})
+
+t.test('update: an invalid --to rejects with EPATCHBADTO', async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: updatePrefix({ 'foo@1.0.0': 'patches/foo@1.0.0.patch' }),
+ })
+ npm.config.set('to', 'not-a-version')
+ await t.rejects(npm.exec('patch', ['update', 'foo@1.0.0']), { code: 'EPATCHBADTO' })
+})
+
+t.test('update: an existing target entry rejects with EPATCHEXISTS', async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: updatePrefix({ 'foo@1.0.0': 'patches/foo@1.0.0.patch', 'foo@2.0.0': 'patches/foo@2.0.0.patch' }),
+ })
+ npm.config.set('to', '2.0.0')
+ await t.rejects(npm.exec('patch', ['update', 'foo@1.0.0']), { code: 'EPATCHEXISTS' })
+})
+
+t.test('update: a missing lockfile with no --to rejects with EPATCHSTALE', async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: updatePrefix({ 'foo@^1.0.0': 'patches/foo@1.0.0.patch' }),
+ })
+ await t.rejects(npm.exec('patch', ['update', 'foo']),
+ { code: 'EPATCHSTALE', message: /could not read the lockfile/ })
+})
+
+t.test('update: wrong arg count rejects with EUSAGE', async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: { 'package.json': JSON.stringify({ name: 'r', version: '1.0.0' }) },
+ })
+ await t.rejects(npm.exec('patch', ['update']), { code: 'EUSAGE' })
+})
+
+// install a single version of `name` and commit a patch, then hand-edit the selector to `selectorKey`.
+const installAndPatch = async (t, name, { src = 'x\n', addFile, selectorKey } = {}) => {
+ const { npm, joinedOutput, outputs, registry } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ strictRegistryNock: false,
+ prefixDir: rootWith({ [name]: '^1.0.0' }),
+ })
+ await setupVersions(npm, registry, name, { '1.0.0': src })
+ await npm.exec('install', [])
+ outputs.length = 0
+ await npm.exec('patch', ['add', name])
+ const editDir = joinedOutput().match(/directory: (.+)/)[1].trim()
+ if (addFile) {
+ fs.writeFileSync(path.join(editDir, addFile), 'extra\n')
+ } else {
+ fs.writeFileSync(path.join(editDir, 'index.js'), 'A\n')
+ }
+ await npm.exec('patch', ['commit', editDir])
+ if (selectorKey) {
+ const pkg = readJson(path.join(npm.prefix, 'package.json'))
+ pkg.patchedDependencies = { [selectorKey]: pkg.patchedDependencies[`${name}@1.0.0`] }
+ fs.writeFileSync(path.join(npm.prefix, 'package.json'), JSON.stringify(pkg))
+ }
+ return { npm, joinedOutput, outputs }
+}
+
+t.test('update: exact selector with no --to is a no-op', async t => {
+ const { npm } = await installAndPatch(t, 'upd-noop')
+ await t.rejects(npm.exec('patch', ['update', 'upd-noop']), { code: 'EPATCHNOOP' })
+})
+
+t.test('update: a name-only selector resolves the installed version', async t => {
+ const { npm } = await installAndPatch(t, 'upd-nameonly', { selectorKey: 'upd-nameonly' })
+ // only 1.0.0 installed, so the name-only selector resolves to it -> no-op
+ await t.rejects(npm.exec('patch', ['update', 'upd-nameonly']), { code: 'EPATCHNOOP' })
+})
+
+t.test('update: a range matching no installed version rejects with EPATCHSTALE', async t => {
+ const { npm } = await installAndPatch(t, 'upd-norange', { selectorKey: 'upd-norange@^5.0.0' })
+ await t.rejects(npm.exec('patch', ['update', 'upd-norange']),
+ { code: 'EPATCHSTALE', message: /no installed version matches the patch selector "upd-norange@\^5.0.0"/ })
+})
+
+t.test('update: a patch that no longer applies to its baseline rejects with EPATCHBASE', async t => {
+ const name = 'upd-drift'
+ const { npm, registry } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ strictRegistryNock: false,
+ prefixDir: rootWith({ [name]: '^1.0.0' }),
+ })
+ await setupVersions(npm, registry, name, { '1.0.0': 'real\n', '2.0.0': 'real2\n' })
+ await npm.exec('install', [])
+ // a patch whose context does not exist in the baseline tarball cannot be re-applied during rebase
+ fs.mkdirSync(path.join(npm.prefix, 'patches'), { recursive: true })
+ fs.writeFileSync(path.join(npm.prefix, 'patches', `${name}@1.0.0.patch`),
+ '--- a/index.js\t\n+++ b/index.js\t\n@@ -1,1 +1,1 @@\n-NOT-THE-REAL-LINE\n+changed\n')
+ const pkg = readJson(path.join(npm.prefix, 'package.json'))
+ pkg.patchedDependencies = { [`${name}@1.0.0`]: `patches/${name}@1.0.0.patch` }
+ fs.writeFileSync(path.join(npm.prefix, 'package.json'), JSON.stringify(pkg))
+ npm.config.set('to', '2.0.0')
+ await t.rejects(npm.exec('patch', ['update', name]), { code: 'EPATCHBASE' })
+})
+
+t.test('update: when the new version already contains the patch, reports EPATCHEMPTY', async t => {
+ const name = 'upd-empty'
+ const { npm, joinedOutput, outputs, registry } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ strictRegistryNock: false,
+ prefixDir: rootWith({ [name]: '^1.0.0' }),
+ })
+ // v2 already has the value the patch sets, so the rebase yields nothing
+ await setupVersions(npm, registry, name, { '1.0.0': 'old\n', '2.0.0': 'new\n' })
+ await npm.exec('install', [])
+ outputs.length = 0
+ await npm.exec('patch', ['add', name])
+ const editDir = joinedOutput().match(/directory: (.+)/)[1].trim()
+ fs.writeFileSync(path.join(editDir, 'index.js'), 'new\n')
+ await npm.exec('patch', ['commit', editDir])
+ npm.config.set('to', '2.0.0')
+ await t.rejects(npm.exec('patch', ['update', name]), { code: 'EPATCHEMPTY' })
+})
+
+t.test('update: a patches-dir outside the project is rejected', async t => {
+ const name = 'upd-unsafe'
+ const { npm, joinedOutput, outputs, registry } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ strictRegistryNock: false,
+ prefixDir: rootWith({ [name]: '^1.0.0' }),
+ })
+ await setupVersions(npm, registry, name, { '1.0.0': 'a\nb\nc\n', '2.0.0': 'a\nb\nCC\n' })
+ await npm.exec('install', [])
+ outputs.length = 0
+ await npm.exec('patch', ['add', name])
+ const editDir = joinedOutput().match(/directory: (.+)/)[1].trim()
+ fs.writeFileSync(path.join(editDir, 'index.js'), 'AA\nb\nc\n')
+ await npm.exec('patch', ['commit', editDir])
+ npm.config.set('to', '2.0.0')
+ npm.config.set('patches-dir', '../outside')
+ await t.rejects(npm.exec('patch', ['update', name]), { code: 'EPATCHUNSAFE' })
+})
+
+t.test('update --to keeps a range selector when the lockfile is unknown', async t => {
+ const name = 'upd-keep'
+ const { npm, registry } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ strictRegistryNock: false,
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: 'root-project',
+ version: '1.0.0',
+ dependencies: { [name]: '*' },
+ patchedDependencies: { [`${name}@^1.0.0`]: `patches/${name}@1.0.0.patch` },
+ }),
+ patches: { [`${name}@1.0.0.patch`]: '--- /dev/null\t\n+++ b/EXTRA.txt\t\n@@ -0,0 +1 @@\n+extra\n' },
+ },
+ })
+ await setupVersions(npm, registry, name, { '1.0.0': 'x\n', '2.0.0': 'x\n' })
+ // no install -> no lockfile -> installed versions unknown; --to drives the target
+ npm.config.set('to', '2.0.0')
+ await npm.exec('patch', ['update', name])
+ t.same(readJson(path.join(npm.prefix, 'package.json')).patchedDependencies, {
+ [`${name}@^1.0.0`]: `patches/${name}@1.0.0.patch`,
+ [`${name}@2.0.0`]: `patches/${name}@2.0.0.patch`,
+ }, 'range kept, new exact entry added')
+})
+
+t.test('commit: a foreign update marker does not hijack a normal commit', async t => {
+ const name = 'upd-foreign'
+ const { npm, joinedOutput, outputs, registry } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ strictRegistryNock: false,
+ prefixDir: rootWith({ [name]: '^1.0.0' }),
+ })
+ await setupVersions(npm, registry, name, { '1.0.0': 'a\n' })
+ await npm.exec('install', [])
+ outputs.length = 0
+ await npm.exec('patch', ['add', name])
+ const editDir = joinedOutput().match(/directory: (.+)/)[1].trim()
+ fs.writeFileSync(path.join(editDir, 'index.js'), 'patched\n')
+ // a valid marker naming a different package must be ignored, not acted on
+ fs.writeFileSync(path.join(editDir, '.npm-patch-update.json'),
+ JSON.stringify({ name: 'other-pkg', removeKey: 'other-pkg@9.9.9' }))
+ await npm.exec('patch', ['commit', editDir])
+
+ const pkg = readJson(path.join(npm.prefix, 'package.json'))
+ t.ok(pkg.patchedDependencies[`${name}@1.0.0`], 'normal commit recorded its own selector')
+ // a normal commit does a full reify, so node_modules is patched (not the metadata-only update path)
+ t.equal(fs.readFileSync(path.join(npm.prefix, 'node_modules', name, 'index.js'), 'utf8'), 'patched\n',
+ 'node_modules is patched despite the foreign marker')
+})
+
+t.test('commit: an invalid update marker rejects with EPATCHBADMARKER', async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: { 'package.json': JSON.stringify({ name: 'r', version: '1.0.0' }) },
+ })
+ const editDir = path.join(npm.prefix, 'ed')
+ fs.mkdirSync(editDir, { recursive: true })
+ fs.writeFileSync(path.join(editDir, 'package.json'), JSON.stringify({ name: 'foo', version: '1.0.0' }))
+ fs.writeFileSync(path.join(editDir, '.npm-patch-update.json'), 'not json')
+ await t.rejects(npm.exec('patch', ['commit', editDir]), { code: 'EPATCHBADMARKER' })
+})
+
+t.test('rm: no pkg arg rejects with EUSAGE', async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: basePrefix(),
+ })
+ await t.rejects(npm.exec('patch', ['rm']), { code: 'EUSAGE' })
+})
+
+t.test('completion lists subcommands at the right depth', async t => {
+ t.same(
+ await Patch.completion({ conf: { argv: { remain: ['npm', 'patch'] } } }),
+ ['add', 'commit', 'update', 'ls', 'rm']
+ )
+ t.same(await Patch.completion({ conf: { argv: { remain: ['npm', 'patch', 'add', 'x'] } } }), [])
+})
+
+t.test('add: ignore-existing wipes a pre-existing edit dir', async t => {
+ const { npm, registry } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ strictRegistryNock: false,
+ prefixDir: basePrefix(),
+ })
+ await setupDep(npm, registry)
+ await npm.exec('install', [])
+
+ const customDir = path.join(npm.prefix, 'reuse-edit')
+ fs.mkdirSync(customDir, { recursive: true })
+ fs.writeFileSync(path.join(customDir, 'stale.txt'), 'old')
+ npm.config.set('edit-dir', customDir)
+ npm.config.set('ignore-existing', true)
+ await npm.exec('patch', ['add', DEP_NAME])
+ t.notOk(fs.existsSync(path.join(customDir, 'stale.txt')), 'stale file removed')
+ t.ok(fs.existsSync(path.join(customDir, 'package.json')), 'fresh extract present')
+})
+
+t.test('add: range matching an installed version resolves to it', async t => {
+ const { npm, joinedOutput, registry } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ strictRegistryNock: false,
+ prefixDir: basePrefix(),
+ })
+ await setupDep(npm, registry)
+ await npm.exec('install', [])
+ await npm.exec('patch', ['add', `${DEP_NAME}@^${DEP_VERSION}`])
+ t.match(joinedOutput(), /You can now edit the following directory: /, 'range matched the installed version')
+})
+
+t.test('add: range not installed resolves against the registry', async t => {
+ const { npm, joinedOutput, registry } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ strictRegistryNock: false,
+ prefixDir: {
+ 'dep-tarball': { 'package.json': JSON.stringify({ name: DEP_NAME, version: '2.0.0' }), 'index.js': DEP_SRC },
+ 'package.json': JSON.stringify({ name: 'root-project', version: '1.0.0' }),
+ },
+ })
+ const manifest = registry.manifest({ name: DEP_NAME, versions: ['2.0.0'] })
+ const dist = new URL(manifest.versions['2.0.0'].dist.tarball)
+ const tar = await pacote.tarball(path.join(npm.prefix, 'dep-tarball'), { Arborist })
+ registry.nock.get(`/${DEP_NAME}`).reply(200, manifest).persist()
+ registry.nock.get(dist.pathname).reply(200, tar).persist()
+
+ await npm.exec('patch', ['add', `${DEP_NAME}@^2.0.0`])
+ t.match(joinedOutput(), /You can now edit the following directory: /, 'resolved the range via the registry')
+})
+
+t.test('commit: a patches-dir outside the project is rejected', async t => {
+ const { npm, registry } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false, 'patches-dir': '../outside' },
+ strictRegistryNock: false,
+ prefixDir: basePrefix(),
+ })
+ await setupDep(npm, registry)
+ await npm.exec('install', [])
+
+ const editDir = path.join(npm.prefix, 'edit')
+ await pacote.extract(`${DEP_NAME}@${DEP_VERSION}`, editDir, npm.flatOptions)
+ fs.writeFileSync(path.join(editDir, 'index.js'), 'module.exports = () => "patched"\n')
+ await t.rejects(
+ npm.exec('patch', ['commit', editDir]),
+ { code: 'EPATCHUNSAFE' },
+ 'commit refuses to write the patch outside the project root'
+ )
+})
+
+t.test('commit: edit dir package.json missing version rejects', async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: {
+ 'package.json': JSON.stringify(rootPackageJson),
+ 'bad-edit': { 'package.json': JSON.stringify({ name: 'no-version' }) },
+ },
+ })
+ await t.rejects(
+ npm.exec('patch', ['commit', path.join(npm.prefix, 'bad-edit')]),
+ /missing name or version/
+ )
+})
+
+t.test('commit: keep-edit-dir leaves the edit directory in place', async t => {
+ const { npm, registry } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false, 'keep-edit-dir': true },
+ strictRegistryNock: false,
+ prefixDir: basePrefix(),
+ })
+ await setupDep(npm, registry)
+ await npm.exec('install', [])
+
+ const editDir = path.join(npm.prefix, 'kept-edit')
+ await pacote.extract(`${DEP_NAME}@${DEP_VERSION}`, editDir, npm.flatOptions)
+ fs.writeFileSync(path.join(editDir, 'index.js'), 'module.exports = () => "patched"\n')
+ await npm.exec('patch', ['commit', editDir])
+ t.ok(fs.existsSync(editDir), 'edit dir kept when keep-edit-dir is set')
+})
+
+t.test('ls counts nodes for a range selector', async t => {
+ // offline fixture: ls reads the installed tree from disk, no registry needed
+ const { npm, joinedOutput } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ ...rootPackageJson,
+ patchedDependencies: { [`${DEP_NAME}@^1.0.0`]: `patches/${DEP_NAME}.patch` },
+ }),
+ 'package-lock.json': JSON.stringify(rootPackageLock),
+ node_modules: {
+ [DEP_NAME]: { 'package.json': JSON.stringify({ name: DEP_NAME, version: DEP_VERSION }) },
+ },
+ },
+ })
+ await npm.exec('patch', ['ls'])
+ t.match(joinedOutput(), /\(1 node\)/, 'range selector matches the installed version')
+})
+
+t.test('ls tolerates ambiguous overlapping range selectors', async t => {
+ // two overlapping non-subset ranges make matchSelector throw; ls must not crash
+ const { npm, joinedOutput } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: 'root-project',
+ version: '1.0.0',
+ dependencies: { [DEP_NAME]: '1.5.0' },
+ patchedDependencies: {
+ [`${DEP_NAME}@>=1.0.0 <2.0.0`]: 'patches/a.patch',
+ [`${DEP_NAME}@>=1.4.0 <3.0.0`]: 'patches/b.patch',
+ },
+ }),
+ node_modules: {
+ [DEP_NAME]: { 'package.json': JSON.stringify({ name: DEP_NAME, version: '1.5.0' }) },
+ },
+ },
+ })
+ await npm.exec('patch', ['ls'])
+ t.match(joinedOutput(), /\(error: ambiguous selectors\)/, 'ls surfaces the ambiguity')
+})
+
+t.test('ls flags only the conflicting range selectors, not an exact one', async t => {
+ // an exact selector for the same name must not be reported as ambiguous
+ const { npm, joinedOutput } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: 'root-project',
+ version: '1.0.0',
+ dependencies: { [DEP_NAME]: '1.0.0', b: '1.0.0' },
+ patchedDependencies: {
+ [`${DEP_NAME}@1.0.0`]: 'patches/exact.patch',
+ [`${DEP_NAME}@>=2.0.0 <4.0.0`]: 'patches/a.patch',
+ [`${DEP_NAME}@>=3.0.0 <5.0.0`]: 'patches/b.patch',
+ },
+ }),
+ node_modules: {
+ [DEP_NAME]: { 'package.json': JSON.stringify({ name: DEP_NAME, version: '1.0.0' }) },
+ b: {
+ 'package.json': JSON.stringify({ name: 'b', version: '1.0.0', dependencies: { [DEP_NAME]: '3.5.0' } }),
+ node_modules: { [DEP_NAME]: { 'package.json': JSON.stringify({ name: DEP_NAME, version: '3.5.0' }) } },
+ },
+ },
+ },
+ })
+ await npm.exec('patch', ['ls'])
+ const out = joinedOutput()
+ t.match(out, new RegExp(`patches/exact\\.patch\\t${DEP_NAME}@1\\.0\\.0\\t\\(1 node\\)`), 'exact selector counts its node')
+ t.match(out, /patches\/a\.patch\t.*\(error: ambiguous selectors\)/, 'first overlapping range flagged')
+ t.match(out, /patches\/b\.patch\t.*\(error: ambiguous selectors\)/, 'second overlapping range flagged')
+})
+
+t.test('ls reports plural node counts for a name-only selector', async t => {
+ // offline fixture with two installed copies so the match count is plural
+ const { npm, joinedOutput } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: 'root-project',
+ version: '1.0.0',
+ dependencies: { [DEP_NAME]: '1.0.0', b: '1.0.0' },
+ patchedDependencies: { [DEP_NAME]: `patches/${DEP_NAME}.patch` },
+ }),
+ node_modules: {
+ [DEP_NAME]: { 'package.json': JSON.stringify({ name: DEP_NAME, version: '1.0.0' }) },
+ b: {
+ 'package.json': JSON.stringify({ name: 'b', version: '1.0.0', dependencies: { [DEP_NAME]: '2.0.0' } }),
+ node_modules: { [DEP_NAME]: { 'package.json': JSON.stringify({ name: DEP_NAME, version: '2.0.0' }) } },
+ },
+ },
+ },
+ })
+ await npm.exec('patch', ['ls'])
+ t.match(joinedOutput(), /\(2 nodes\)/, 'name-only selector matches both installed copies')
+})
+
+t.test('rm refuses to delete a patch file outside the project root', async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: 'root-project',
+ version: '1.0.0',
+ patchedDependencies: { [`${DEP_NAME}@1.0.0`]: '../escape.patch' },
+ }),
+ },
+ })
+ await t.rejects(
+ npm.exec('patch', ['rm', DEP_NAME]),
+ { code: 'EPATCHUNSAFE' },
+ 'a crafted escaping patch path is not deleted'
+ )
+})
+
+t.test('rm removes every selector for a bare name', async t => {
+ // offline: the dep is already installed and unpatched, so rm reifies without the registry
+ const { npm, joinedOutput } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ ...rootPackageJson,
+ patchedDependencies: {
+ [`${DEP_NAME}@1.0.0`]: 'patches/one.patch',
+ [`${DEP_NAME}@2.0.0`]: 'patches/two.patch',
+ },
+ }),
+ 'package-lock.json': JSON.stringify(rootPackageLock),
+ patches: { 'one.patch': '', 'two.patch': '' },
+ node_modules: {
+ [DEP_NAME]: { 'package.json': JSON.stringify({ name: DEP_NAME, version: DEP_VERSION }) },
+ },
+ },
+ })
+ await npm.exec('patch', ['rm', DEP_NAME])
+ t.match(joinedOutput(), /Removed patches:/, 'reports plural removal')
+ t.notOk(readJson(path.join(npm.prefix, 'package.json')).patchedDependencies, 'all selectors removed')
+})
+
+t.test('rm keeps a patch file still referenced by another selector', async t => {
+ const { npm, registry } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ strictRegistryNock: false,
+ prefixDir: basePrefix(),
+ })
+ await setupDep(npm, registry)
+ await npm.exec('install', [])
+
+ // create a real patch via the normal flow
+ await npm.exec('patch', ['add', DEP_NAME])
+ const editDir = path.join(npm.prefix, 'edit')
+ await pacote.extract(`${DEP_NAME}@${DEP_VERSION}`, editDir, npm.flatOptions)
+ fs.writeFileSync(path.join(editDir, 'index.js'), 'module.exports = () => "patched"\n')
+ await npm.exec('patch', ['commit', editDir])
+
+ // add a second name-only selector pointing at the same patch file
+ const pkgPath = path.join(npm.prefix, 'package.json')
+ const pkg = readJson(pkgPath)
+ const patchPath = pkg.patchedDependencies[`${DEP_NAME}@${DEP_VERSION}`]
+ pkg.patchedDependencies[DEP_NAME] = patchPath
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg))
+
+ // removing the exact selector leaves the name-only one, so the file stays
+ await npm.exec('patch', ['rm', `${DEP_NAME}@${DEP_VERSION}`])
+ t.ok(fs.existsSync(path.join(npm.prefix, patchPath)), 'shared patch file retained')
+ const after = readJson(pkgPath)
+ t.ok(after.patchedDependencies[DEP_NAME], 'name-only selector kept')
+ t.notOk(after.patchedDependencies[`${DEP_NAME}@${DEP_VERSION}`], 'exact selector removed')
+})
+
+t.test('install honors --allow-unused-patches only from the cli', async t => {
+ // an empty project with a ghost patch entry triggers EPATCHUNUSED entirely offline
+ const prefixDir = {
+ 'package.json': JSON.stringify({
+ name: 'root',
+ version: '1.0.0',
+ patchedDependencies: { 'ghost@1.0.0': 'patches/ghost.patch' },
+ }),
+ patches: { 'ghost.patch': '--- a/x\n+++ b/x\n' },
+ }
+
+ t.test('unused patch is a hard error by default', async t => {
+ const { npm } = await loadMockNpm(t, { config: { 'ignore-scripts': true, audit: false }, prefixDir })
+ await t.rejects(npm.exec('install', []), { code: 'EPATCHUNUSED' })
+ })
+
+ t.test('the cli flag suppresses the error', async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false, 'allow-unused-patches': true },
+ prefixDir,
+ })
+ await t.resolves(npm.exec('install', []))
+ })
+
+ t.test('the same flag in .npmrc is ignored', async t => {
+ const { npm } = await loadMockNpm(t, {
+ config: { 'ignore-scripts': true, audit: false },
+ prefixDir: { ...prefixDir, '.npmrc': 'allow-unused-patches=true' },
+ })
+ await t.rejects(npm.exec('install', []), { code: 'EPATCHUNUSED' })
+ })
+})
diff --git a/deps/npm/test/lib/commands/pkg.js b/deps/npm/test/lib/commands/pkg.js
index f4d0278b04d..50288cc4236 100644
--- a/deps/npm/test/lib/commands/pkg.js
+++ b/deps/npm/test/lib/commands/pkg.js
@@ -1,604 +1,510 @@
const { resolve } = require('node:path')
const { readFileSync } = require('node:fs')
const t = require('tap')
-const _mockNpm = require('../../fixtures/mock-npm')
+const { load: loadMockNpm } = require('../../fixtures/mock-npm')
const { cleanCwd } = require('../../fixtures/clean-snapshot')
t.cleanSnapshot = (str) => cleanCwd(str)
-const mockNpm = async (t, { ...opts } = {}) => {
- const res = await _mockNpm(t, {
- ...opts,
- command: 'pkg',
- })
-
- const readPackageJson = (dir = '') =>
- JSON.parse(readFileSync(resolve(res.prefix, dir, 'package.json'), 'utf8'))
-
- return {
- ...res,
- pkg: (...args) => res.npm.exec('pkg', args),
- readPackageJson,
- OUTPUT: () => res.joinedOutput(),
- }
-}
+const readPackageJson = (prefix, dir = '') =>
+ JSON.parse(readFileSync(resolve(prefix, dir, 'package.json'), 'utf8'))
t.test('no args', async t => {
- const { pkg } = await mockNpm(t)
+ const { npm } = await loadMockNpm(t)
await t.rejects(
- pkg(),
+ npm.exec('pkg'),
{ code: 'EUSAGE' },
'should throw usage error'
)
})
t.test('no global mode', async t => {
- const { pkg } = await mockNpm(t, {
- config: { global: true },
+ const { npm } = await loadMockNpm(t, {
+ config: {
+ global: true,
+ },
})
await t.rejects(
- pkg('get', 'foo'),
+ npm.exec('pkg'),
{ code: 'EPKGGLOBAL' },
'should throw no global mode error'
)
})
-t.test('get no args', async t => {
- const { pkg, OUTPUT } = await mockNpm(t, {
- prefixDir: {
- 'package.json': JSON.stringify({
- name: 'foo',
- version: '1.1.1',
- }),
- },
+t.test('get', t => {
+ t.test('no args', async t => {
+ const { npm, joinedOutput } = await loadMockNpm(t, {
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: 'foo',
+ version: '1.1.1',
+ }),
+ },
+ })
+ await npm.exec('pkg', ['get'])
+
+ t.matchSnapshot(
+ joinedOutput(),
+ 'should print package.json content'
+ )
})
- await pkg('get')
+ t.test('single arg', async t => {
+ const { npm, joinedOutput } = await loadMockNpm(t, {
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: 'foo',
+ version: '1.1.1',
+ }),
+ },
+ })
- t.strictSame(
- JSON.parse(OUTPUT()),
- {
- name: 'foo',
- version: '1.1.1',
- },
- 'should print package.json content'
- )
-})
+ await npm.exec('pkg', ['get', 'version'])
-t.test('get single arg', async t => {
- const { pkg, OUTPUT } = await mockNpm(t, {
- prefixDir: {
- 'package.json': JSON.stringify({
- name: 'foo',
- version: '1.1.1',
- }),
- },
+ t.matchSnapshot(
+ joinedOutput(),
+ 'should print retrieved package.json field'
+ )
})
- await pkg('get', 'version')
+ t.test('non string', async t => {
+ const { npm, joinedOutput } = await loadMockNpm(t, {
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: 'foo',
+ version: '1.1.1',
+ dependencies: {
+ '@npmcli/test': '*',
+ },
+ }),
+ },
+ })
- t.strictSame(
- JSON.parse(OUTPUT()),
- '1.1.1',
- 'should print retrieved package.json field'
- )
-})
+ await npm.exec('pkg', ['get', 'dependencies'])
-t.test('get multiple arg', async t => {
- const { pkg, OUTPUT } = await mockNpm(t, {
- prefixDir: {
- 'package.json': JSON.stringify({
- name: 'foo',
- version: '1.1.1',
- }),
- },
+ t.matchSnapshot(
+ joinedOutput(),
+ 'should print retrieved package.json field'
+ )
})
+ t.test('multiple arg', async t => {
+ const { npm, joinedOutput } = await loadMockNpm(t, {
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: 'foo',
+ version: '1.1.1',
+ }),
+ },
+ })
- await pkg('get', 'name', 'version')
-
- t.strictSame(
- JSON.parse(OUTPUT()),
- {
- name: 'foo',
- version: '1.1.1',
- },
- 'should print retrieved package.json field'
- )
-})
+ await npm.exec('pkg', ['get', 'name', 'version'])
-t.test('get multiple arg with only one arg existing', async t => {
- const { pkg, OUTPUT } = await mockNpm(t, {
- prefixDir: {
- 'package.json': JSON.stringify({
- name: 'foo',
- }),
- },
+ t.matchSnapshot(
+ joinedOutput(),
+ 'should print retrieved package.json fields'
+ )
})
- await pkg('get', 'name', 'version', 'dependencies')
+ t.test('multiple arg with only one arg existing', async t => {
+ const { npm, joinedOutput } = await loadMockNpm(t, {
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: 'foo',
+ }),
+ },
+ })
- t.strictSame(
- JSON.parse(OUTPUT()),
- {
- name: 'foo',
- },
- 'should print retrieved package.json field'
- )
-})
+ await npm.exec('pkg', ['get', 'name', 'version', 'dependencies'])
-t.test('get multiple arg with empty value', async t => {
- const { pkg, OUTPUT } = await mockNpm(t, {
- prefixDir: {
- 'package.json': JSON.stringify({
- name: 'foo',
- author: '',
- }),
- },
+ t.matchSnapshot(
+ joinedOutput(),
+ 'should print retrieved package.json field'
+ )
})
- await pkg('get', 'name', 'author')
+ t.test('multiple arg with empty value', async t => {
+ const { npm, joinedOutput } = await loadMockNpm(t, {
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: 'foo',
+ author: '',
+ }),
+ },
+ })
- t.strictSame(
- JSON.parse(OUTPUT()),
- {
- name: 'foo',
- author: '',
- },
- 'should print retrieved package.json field regardless of empty value'
- )
-})
+ await npm.exec('pkg', ['get', 'name', 'author'])
-t.test('get nested arg', async t => {
- const { pkg, OUTPUT } = await mockNpm(t, {
- prefixDir: {
- 'package.json': JSON.stringify({
- name: 'foo',
- version: '1.1.1',
- scripts: {
- test: 'node test.js',
- },
- }),
- },
+ t.matchSnapshot(
+ joinedOutput(),
+ 'should print retrieved package.json field regardless of empty value'
+ )
})
- await pkg('get', 'scripts.test')
+ t.test('nested arg', async t => {
+ const { npm, joinedOutput } = await loadMockNpm(t, {
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: 'foo',
+ version: '1.1.1',
+ scripts: {
+ test: 'node test.js',
+ },
+ }),
+ },
+ })
- t.strictSame(
- JSON.parse(OUTPUT()),
- 'node test.js',
- 'should print retrieved nested field'
- )
-})
+ await npm.exec('pkg', ['get', 'scripts.test'])
-t.test('get array field', async t => {
- const files = [
- 'index.js',
- 'cli.js',
- ]
- const { pkg, OUTPUT } = await mockNpm(t, {
- prefixDir: {
- 'package.json': JSON.stringify({
- name: 'foo',
- version: '1.1.1',
- files,
- }),
- },
+ t.matchSnapshot(
+ joinedOutput(),
+ 'node test.js',
+ 'should print retrieved nested field'
+ )
})
- await pkg('get', 'files')
+ t.test('array field', async t => {
+ const { npm, joinedOutput } = await loadMockNpm(t, {
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: 'foo',
+ version: '1.1.1',
+ files: [
+ 'index.js',
+ 'cli.js',
+ ],
+ }),
+ },
+ })
- t.strictSame(
- JSON.parse(OUTPUT()),
- files,
- 'should print retrieved array field'
- )
-})
+ await npm.exec('pkg', ['get', 'files'])
-t.test('get array item', async t => {
- const files = [
- 'index.js',
- 'cli.js',
- ]
- const { pkg, OUTPUT } = await mockNpm(t, {
- prefixDir: {
- 'package.json': JSON.stringify({
- name: 'foo',
- version: '1.1.1',
- files,
- }),
- },
+ t.matchSnapshot(
+ joinedOutput(),
+ 'should print retrieved array field'
+ )
})
- await pkg('get', 'files[0]')
+ t.test('array item', async t => {
+ const { npm, joinedOutput } = await loadMockNpm(t, {
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: 'foo',
+ version: '1.1.1',
+ files: [
+ 'index.js',
+ 'cli.js',
+ ],
+ }),
+ },
+ })
- t.strictSame(
- JSON.parse(OUTPUT()),
- 'index.js',
- 'should print retrieved array field'
- )
-})
+ await npm.exec('pkg', ['get', 'files[0]'])
-t.test('get array nested items notation', async t => {
- const contributors = [
- {
- name: 'Ruy',
- url: 'http://example.com/ruy',
- },
- {
- name: 'Gar',
- url: 'http://example.com/gar',
- },
- ]
- const { pkg, OUTPUT } = await mockNpm(t, {
- prefixDir: {
- 'package.json': JSON.stringify({
- name: 'foo',
- version: '1.1.1',
- contributors,
- }),
- },
+ t.matchSnapshot(
+ joinedOutput(),
+ 'should print retrieved array field'
+ )
})
- await pkg('get', 'contributors.name')
- t.strictSame(
- JSON.parse(OUTPUT()),
- {
- 'contributors[0].name': 'Ruy',
- 'contributors[1].name': 'Gar',
- },
- 'should print json result containing matching results'
- )
-})
-
-t.test('set no args', async t => {
- const { pkg } = await mockNpm(t, {
- prefixDir: {
- 'package.json': JSON.stringify({ name: 'foo' }),
- },
- })
- await t.rejects(
- pkg('set'),
- { code: 'EUSAGE' },
- 'should throw an error if no args'
- )
-})
+ t.test('json no args', async t => {
+ const { npm, joinedOutput } = await loadMockNpm(t, {
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: 'foo',
+ version: '1.1.1',
+ }),
+ },
+ config: {
+ json: true,
+ },
+ })
+ await npm.exec('pkg', ['get'])
-t.test('set missing value', async t => {
- const { pkg } = await mockNpm(t, {
- prefixDir: {
- 'package.json': JSON.stringify({ name: 'foo' }),
- },
+ t.matchSnapshot(
+ joinedOutput(),
+ 'should print package.json content'
+ )
})
- await t.rejects(
- pkg('set', 'key='),
- { code: 'EUSAGE' },
- 'should throw an error if missing value'
- )
-})
-t.test('set missing key', async t => {
- const { pkg } = await mockNpm(t, {
- prefixDir: {
- 'package.json': JSON.stringify({ name: 'foo' }),
- },
- })
- await t.rejects(
- pkg('set', '=value'),
- { code: 'EUSAGE' },
- 'should throw an error if missing key'
- )
-})
+ t.test('json with args', async t => {
+ const { npm, joinedOutput } = await loadMockNpm(t, {
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: 'foo',
+ version: '1.1.1',
+ }),
+ },
+ config: {
+ json: true,
+ },
+ })
+ await npm.exec('pkg', ['get', 'name'])
-t.test('set single field', async t => {
- const json = {
- name: 'foo',
- version: '1.1.1',
- }
- const { pkg, readPackageJson } = await mockNpm(t, {
- prefixDir: {
- 'package.json': JSON.stringify(json),
- },
+ t.matchSnapshot(
+ joinedOutput(),
+ 'should print package.json content'
+ )
})
- await pkg('set', 'description=Awesome stuff')
- t.strictSame(
- readPackageJson(),
- {
- ...json,
- description: 'Awesome stuff',
- },
- 'should add single field to package.json'
- )
-})
+ t.test('get array nested items notation', async t => {
+ const { npm, joinedOutput } = await loadMockNpm(t, {
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: 'foo',
+ version: '1.1.1',
+ contributors: [
+ {
+ name: 'Ruy',
+ url: 'http://example.com/ruy',
+ },
+ {
+ name: 'Gar',
+ url: 'http://example.com/gar',
+ },
+ ],
+ }),
+ },
+ })
-t.test('push to array syntax', async t => {
- const json = {
- name: 'foo',
- version: '1.1.1',
- keywords: [
- 'foo',
- ],
- }
- const { pkg, readPackageJson } = await mockNpm(t, {
- prefixDir: {
- 'package.json': JSON.stringify(json),
- },
+ await npm.exec('pkg', ['get', 'contributors.name'])
+ t.matchSnapshot(
+ joinedOutput(),
+ 'should print json result containing matching results'
+ )
})
-
- await pkg('set', 'keywords[]=bar', 'keywords[]=baz')
- t.strictSame(
- readPackageJson(),
- {
- ...json,
- keywords: [
- 'foo',
- 'bar',
- 'baz',
- ],
- },
- 'should append to arrays using empty bracket syntax'
- )
+ t.end()
})
-t.test('set multiple fields', async t => {
- const json = {
- name: 'foo',
- version: '1.1.1',
- }
- const { pkg, readPackageJson } = await mockNpm(t, {
- prefixDir: {
- 'package.json': JSON.stringify(json),
- },
+t.test('set', t => {
+ t.test('set no args', async t => {
+ const { npm } = await loadMockNpm(t, {
+ prefixDir: {
+ 'package.json': JSON.stringify({ name: 'foo' }),
+ },
+ })
+ await t.rejects(
+ npm.exec('pkg', ['set']),
+ { code: 'EUSAGE' },
+ 'should throw an error if no args'
+ )
})
- await pkg('set', 'bin.foo=foo.js', 'scripts.test=node test.js')
- t.strictSame(
- readPackageJson(),
- {
- ...json,
- bin: {
- foo: 'foo.js',
- },
- scripts: {
- test: 'node test.js',
+ t.test('set missing value', async t => {
+ const { npm } = await loadMockNpm(t, {
+ prefixDir: {
+ 'package.json': JSON.stringify({ name: 'foo' }),
},
- },
- 'should add single field to package.json'
- )
-})
-
-t.test('set = separate value', async t => {
- const json = {
- name: 'foo',
- version: '1.1.1',
- }
- const { pkg, readPackageJson } = await mockNpm(t, {
- prefixDir: {
- 'package.json': JSON.stringify(json),
- },
+ })
+ await t.rejects(
+ npm.exec('pkg', ['set', 'key=']),
+ { code: 'EUSAGE' },
+ 'should throw an error if missing value'
+ )
})
- await pkg('set', 'tap[test-env][0]=LC_ALL=sk')
- t.strictSame(
- readPackageJson(),
- {
- ...json,
- tap: {
- 'test-env': [
- 'LC_ALL=sk',
- ],
+ t.test('set missing key', async t => {
+ const { npm } = await loadMockNpm(t, {
+ prefixDir: {
+ 'package.json': JSON.stringify({ name: 'foo' }),
},
- },
- 'should add single field to package.json'
- )
-})
-
-t.test('set --json', async t => {
- const { pkg, readPackageJson } = await mockNpm(t, {
- prefixDir: {
- 'package.json': JSON.stringify({
- name: 'foo',
- version: '1.1.1',
- }),
- },
- config: { json: true },
+ })
+ await t.rejects(
+ npm.exec('pkg', ['set', '=value']),
+ { code: 'EUSAGE' },
+ 'should throw an error if missing key'
+ )
})
- await pkg('set', 'private=true')
- t.strictSame(
- readPackageJson(),
- {
+ t.test('set single field', async t => {
+ const json = {
name: 'foo',
version: '1.1.1',
- private: true,
- },
- 'should add boolean field to package.json'
- )
-
- await pkg('set', 'tap.timeout=60')
- t.strictSame(
- readPackageJson(),
- {
- name: 'foo',
- version: '1.1.1',
- private: true,
- tap: {
- timeout: 60,
+ }
+ const { npm } = await loadMockNpm(t, {
+ prefixDir: {
+ 'package.json': JSON.stringify(json),
},
- },
- 'should add number field to package.json'
- )
+ })
+
+ await npm.exec('pkg', ['set', 'description=Awesome stuff'])
+ t.matchSnapshot(
+ readPackageJson(npm.prefix),
+ 'should add single field to package.json'
+ )
+ })
- await pkg('set', 'foo={ "bar": { "baz": "BAZ" } }')
- t.strictSame(
- readPackageJson(),
- {
+ t.test('push to array syntax', async t => {
+ const json = {
name: 'foo',
version: '1.1.1',
- private: true,
- tap: {
- timeout: 60,
- },
- foo: {
- bar: {
- baz: 'BAZ',
- },
+ keywords: [
+ 'foo',
+ ],
+ }
+ const { npm } = await loadMockNpm(t, {
+ prefixDir: {
+ 'package.json': JSON.stringify(json),
},
- },
- 'should add object field to package.json'
- )
+ })
- await pkg('set', 'workspaces=["packages/*"]')
- t.strictSame(
- readPackageJson(),
- {
+ await npm.exec('pkg', ['set', 'keywords[]=bar', 'keywords[]=baz'])
+ t.matchSnapshot(
+ readPackageJson(npm.prefix),
+ 'should append to arrays using empty bracket syntax'
+ )
+ })
+
+ t.test('set multiple fields', async t => {
+ const json = {
name: 'foo',
version: '1.1.1',
- private: true,
- workspaces: [
- 'packages/*',
- ],
- tap: {
- timeout: 60,
+ }
+ const { npm } = await loadMockNpm(t, {
+ prefixDir: {
+ 'package.json': JSON.stringify(json),
},
- foo: {
- bar: {
- baz: 'BAZ',
- },
- },
- },
- 'should add object field to package.json'
- )
+ })
- await pkg('set', 'description="awesome"')
- t.strictSame(
- readPackageJson(),
- {
+ await npm.exec('pkg', ['set', 'bin.foo=foo.js', 'scripts.test=node test.js'])
+ t.matchSnapshot(
+ readPackageJson(npm.prefix),
+ 'should add single field to package.json'
+ )
+ })
+
+ t.test('set = separate value', async t => {
+ const json = {
name: 'foo',
version: '1.1.1',
- description: 'awesome',
- private: true,
- workspaces: [
- 'packages/*',
- ],
- tap: {
- timeout: 60,
+ }
+ const { npm } = await loadMockNpm(t, {
+ prefixDir: {
+ 'package.json': JSON.stringify(json),
},
- foo: {
- bar: {
- baz: 'BAZ',
- },
+ })
+
+ await npm.exec('pkg', ['set', 'tap[test-env][0]=LC_ALL=sk'])
+ t.matchSnapshot(
+ readPackageJson(npm.prefix),
+ 'should add single field to package.json'
+ )
+ })
+
+ t.test('set --json', async t => {
+ const { npm } = await loadMockNpm(t, {
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: 'foo',
+ version: '1.1.1',
+ }),
},
- },
- 'should add object field to package.json'
- )
+ config: { json: true },
+ })
+
+ await npm.exec('pkg', ['set', 'private=true'])
+ await npm.exec('pkg', ['set', 'tap.timeout=60'])
+ await npm.exec('pkg', ['set', 'foo={ "bar": { "baz": "BAZ" } }'])
+ await npm.exec('pkg', ['set', 'workspaces=["packages/*"]'])
+ await npm.exec('pkg', ['set', 'description="awesome"'])
+ t.matchSnapshot(
+ readPackageJson(npm.prefix),
+ 'should add fields to package.json'
+ )
+ })
+ t.end()
})
-t.test('delete no args', async t => {
- const { pkg } = await mockNpm(t, {
- prefixDir: {
- 'package.json': JSON.stringify({ name: 'foo' }),
- },
+t.test('delete', t => {
+ t.test('delete no args', async t => {
+ const { npm } = await loadMockNpm(t, {
+ prefixDir: {
+ 'package.json': JSON.stringify({ name: 'foo' }),
+ },
+ })
+ await t.rejects(
+ npm.exec('pkg', ['delete']),
+ { code: 'EUSAGE' },
+ 'should throw an error if deleting no args'
+ )
})
- await t.rejects(
- pkg('delete'),
- { code: 'EUSAGE' },
- 'should throw an error if deleting no args'
- )
-})
-t.test('delete invalid key', async t => {
- const { pkg } = await mockNpm(t, {
- prefixDir: {
- 'package.json': JSON.stringify({ name: 'foo' }),
- },
+ t.test('delete invalid key', async t => {
+ const { npm } = await loadMockNpm(t, {
+ prefixDir: {
+ 'package.json': JSON.stringify({ name: 'foo' }),
+ },
+ })
+ await t.rejects(
+ npm.exec('pkg', ['delete', '']),
+ { code: 'EUSAGE' },
+ 'should throw an error if deleting invalid args'
+ )
})
- await t.rejects(
- pkg('delete', ''),
- { code: 'EUSAGE' },
- 'should throw an error if deleting invalid args'
- )
-})
-t.test('delete single field', async t => {
- const { pkg, readPackageJson } = await mockNpm(t, {
- prefixDir: {
- 'package.json': JSON.stringify({
- name: 'foo',
- version: '1.0.0',
- }),
- },
+ t.test('delete single field', async t => {
+ const { npm } = await loadMockNpm(t, {
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: 'foo',
+ version: '1.0.0',
+ }),
+ },
+ })
+ await npm.exec('pkg', ['delete', 'version'])
+ t.matchSnapshot(
+ readPackageJson(npm.prefix),
+ 'should delete single field from package.json'
+ )
})
- await pkg('delete', 'version')
- t.strictSame(
- readPackageJson(),
- {
- name: 'foo',
- },
- 'should delete single field from package.json'
- )
-})
-t.test('delete multiple field', async t => {
- const { pkg, readPackageJson } = await mockNpm(t, {
- prefixDir: {
- 'package.json': JSON.stringify({
- name: 'foo',
- version: '1.0.0',
- description: 'awesome',
- }),
- },
+ t.test('delete multiple field', async t => {
+ const { npm } = await loadMockNpm(t, {
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: 'foo',
+ version: '1.0.0',
+ description: 'awesome',
+ }),
+ },
+ })
+ await npm.exec('pkg', ['delete', 'version', 'description'])
+ t.matchSnapshot(
+ readPackageJson(npm.prefix),
+ 'should delete multiple fields from package.json'
+ )
})
- await pkg('delete', 'version', 'description')
- t.strictSame(
- readPackageJson(),
- {
- name: 'foo',
- },
- 'should delete multiple fields from package.json'
- )
-})
-t.test('delete nested field', async t => {
- const { pkg, readPackageJson } = await mockNpm(t, {
- prefixDir: {
- 'package.json': JSON.stringify({
- name: 'foo',
- version: '1.0.0',
- info: {
- foo: {
- bar: [
- {
- baz: 'deleteme',
- },
- ],
+ t.test('delete nested field', async t => {
+ const { npm } = await loadMockNpm(t, {
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: 'foo',
+ version: '1.0.0',
+ info: {
+ foo: {
+ bar: [
+ {
+ baz: 'deleteme',
+ },
+ ],
+ },
},
- },
- }),
- },
- })
- await pkg('delete', 'info.foo.bar[0].baz')
- t.strictSame(
- readPackageJson(),
- {
- name: 'foo',
- version: '1.0.0',
- info: {
- foo: {
- bar: [
- {},
- ],
- },
+ }),
},
- },
- 'should delete nested fields from package.json'
- )
+ })
+ await npm.exec('pkg', ['delete', 'info.foo.bar[0].baz'])
+ t.matchSnapshot(
+ readPackageJson(npm.prefix),
+ 'should delete nested fields from package.json'
+ )
+ })
+ t.end()
})
t.test('workspaces', async t => {
- const mockWorkspaces = (t) => mockNpm(t, {
+ const workspaceSetup = {
prefixDir: {
'package.json': JSON.stringify({
name: 'root',
@@ -623,76 +529,63 @@ t.test('workspaces', async t => {
},
},
config: { workspaces: true },
- })
+ }
t.test('get', async t => {
- const { pkg, OUTPUT } = await mockWorkspaces(t)
- await pkg('get', 'name', 'version')
- t.strictSame(
- JSON.parse(OUTPUT()),
- {
- a: {
- name: 'a',
- version: '1.0.0',
- },
- b: {
- name: 'b',
- version: '1.2.3',
- },
- },
+ const { npm, joinedOutput } = await loadMockNpm(t, workspaceSetup)
+ await npm.exec('pkg', ['get', 'name', 'version'])
+ t.matchSnapshot(
+ joinedOutput(),
'should return expected result for configured workspaces'
)
})
+ t.test('get json ', async t => {
+ const { npm, joinedOutput } = await loadMockNpm(t, {
+ ...workspaceSetup,
+ config: {
+ json: true,
+ workspaces: true,
+ },
+ })
+ await npm.exec('pkg', ['get', 'name', 'version'])
+ t.matchSnapshot(
+ joinedOutput(),
+ 'should return expected json result for configured workspaces'
+ )
+ })
+
t.test('set', async t => {
- const { pkg, readPackageJson } = await mockWorkspaces(t)
+ const { npm } = await loadMockNpm(t, workspaceSetup)
- await pkg('set', 'funding=http://example.com')
+ await npm.exec('pkg', ['set', 'funding=http://example.com'])
- t.strictSame(
- readPackageJson('packages/a'),
- {
- name: 'a',
- version: '1.0.0',
- funding: 'http://example.com',
- },
+ t.matchSnapshot(
+ readPackageJson(npm.prefix, 'packages/a'),
'should add field to workspace a'
)
- t.strictSame(
- readPackageJson('packages/b'),
- {
- name: 'b',
- version: '1.2.3',
- funding: 'http://example.com',
- },
+ t.matchSnapshot(
+ readPackageJson(npm.prefix, 'packages/b'),
'should add field to workspace b'
)
- await pkg('delete', 'version')
+ await npm.exec('pkg', ['delete', 'version'])
- t.strictSame(
- readPackageJson('packages/a'),
- {
- name: 'a',
- funding: 'http://example.com',
- },
+ t.matchSnapshot(
+ readPackageJson(npm.prefix, 'packages/a'),
'should delete version field from workspace a'
)
- t.strictSame(
- readPackageJson('packages/b'),
- {
- name: 'b',
- funding: 'http://example.com',
- },
+ t.matchSnapshot(
+ readPackageJson(npm.prefix, 'packages/b'),
'should delete version field from workspace b'
)
})
})
t.test('single workspace', async t => {
- const mockWorkspace = (t) => mockNpm(t, {
+ const workspaceSetup = {
prefixDir: {
'package.json': JSON.stringify({
name: 'root',
@@ -717,33 +610,31 @@ t.test('single workspace', async t => {
},
},
config: { workspace: ['packages/a'] },
- })
+ }
t.test('multiple args', async t => {
- const { pkg, OUTPUT } = await mockWorkspace(t)
- await pkg('get', 'name', 'version')
+ const { npm, joinedOutput } = await loadMockNpm(t, workspaceSetup)
+ await npm.exec('pkg', ['get', 'name', 'version'])
- t.strictSame(
- JSON.parse(OUTPUT()),
- { a: { name: 'a', version: '1.0.0' } },
+ t.matchSnapshot(
+ joinedOutput(),
'should only return info for one workspace'
)
})
t.test('single arg', async t => {
- const { pkg, OUTPUT } = await mockWorkspace(t)
- await pkg('get', 'version')
+ const { npm, joinedOutput } = await loadMockNpm(t, workspaceSetup)
+ await npm.exec('pkg', ['get', 'version'])
- t.strictSame(
- JSON.parse(OUTPUT()),
- { a: '1.0.0' },
+ t.matchSnapshot(
+ joinedOutput(),
'should only return info for one workspace'
)
})
})
t.test('fix', async t => {
- const { pkg, readPackageJson } = await mockNpm(t, {
+ const { npm } = await loadMockNpm(t, {
prefixDir: {
'package.json': JSON.stringify({
name: 'foo ',
@@ -752,10 +643,9 @@ t.test('fix', async t => {
},
})
- await pkg('fix')
- t.strictSame(
- readPackageJson(),
- { name: 'foo', version: '1.1.1' },
+ await npm.exec('pkg', ['fix'])
+ t.matchSnapshot(
+ readPackageJson(npm.prefix),
'fixes package.json issues'
)
})
diff --git a/deps/npm/test/lib/commands/profile.js b/deps/npm/test/lib/commands/profile.js
index e11ab4c05fa..15c4d116f25 100644
--- a/deps/npm/test/lib/commands/profile.js
+++ b/deps/npm/test/lib/commands/profile.js
@@ -55,8 +55,6 @@ const userProfile = {
cidr_whitelist: null,
fullname: 'Foo Bar',
homepage: 'https://github.com',
- freenode: 'foobar',
- twitter: 'https://twitter.com/npmjs',
github: 'https://github.com/npm',
}
diff --git a/deps/npm/test/lib/commands/publish.js b/deps/npm/test/lib/commands/publish.js
index 98576b08ea3..0a9fd2cd36f 100644
--- a/deps/npm/test/lib/commands/publish.js
+++ b/deps/npm/test/lib/commands/publish.js
@@ -3,6 +3,8 @@ const { loadNpmWithRegistry } = require('../../fixtures/mock-npm')
const { cleanZlib } = require('../../fixtures/clean-snapshot')
const pacote = require('pacote')
const Arborist = require('@npmcli/arborist')
+const npa = require('npm-package-arg')
+const ssri = require('ssri')
const path = require('node:path')
const fs = require('node:fs')
const { circleciIdToken, githubIdToken, gitlabIdToken, oidcPublishTest, mockOidc } = require('../../fixtures/mock-oidc')
@@ -193,12 +195,8 @@ t.test('foreground-scripts defaults to true', async t => {
t.matchSnapshot(logs.notice)
t.strictSame(
outputs,
- [
- '\n> test-fg-scripts@0.0.0 prepack\n> echo prepack!\n',
- '\n> test-fg-scripts@0.0.0 postpack\n> echo postpack!\n',
- `+ test-fg-scripts@0.0.0`,
- ],
- 'prepack and postpack log to stdout')
+ [`+ test-fg-scripts@0.0.0`],
+ 'published package is the only stdout output')
})
t.test('foreground-scripts can still be set to false', async t => {
@@ -237,6 +235,67 @@ t.test('shows usage with wrong set of arguments', async t => {
await t.rejects(publish.exec(['a', 'b', 'c']), publish.usage)
})
+t.test('fails for a non-private package containing packageExtensions', async t => {
+ const { npm } = await loadNpmWithRegistry(t, {
+ config: { ...auth },
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ ...pkgJson,
+ packageExtensions: { 'foo@1': { dependencies: { bar: '^1.0.0' } } },
+ }, null, 2),
+ },
+ authorization: token,
+ })
+ await t.rejects(
+ npm.exec('publish', []),
+ { code: 'EPACKAGEEXTENSIONS', message: /must not be published/ },
+ 'refuses to publish'
+ )
+})
+
+t.test('fails on --dry-run for a package containing packageExtensions', async t => {
+ const { npm } = await loadNpmWithRegistry(t, {
+ config: { 'dry-run': true, ...auth },
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ ...pkgJson,
+ packageExtensions: { 'foo@1': { dependencies: { bar: '^1.0.0' } } },
+ }, null, 2),
+ },
+ authorization: token,
+ })
+ await t.rejects(
+ npm.exec('publish', []),
+ { code: 'EPACKAGEEXTENSIONS' },
+ 'dry-run also reports the failure'
+ )
+})
+
+t.test('fails when a lifecycle script injects packageExtensions before the re-read', async t => {
+ const { npm } = await loadNpmWithRegistry(t, {
+ config: { ...auth },
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ ...pkgJson,
+ scripts: { prepublishOnly: 'node inject.js' },
+ }, null, 2),
+ // the first manifest read is clean; this hook adds packageExtensions before the authoritative re-read
+ 'inject.js': [
+ "const fs = require('fs')",
+ "const p = JSON.parse(fs.readFileSync('package.json'))",
+ "p.packageExtensions = { 'foo@1': { dependencies: { bar: '^1.0.0' } } }",
+ "fs.writeFileSync('package.json', JSON.stringify(p))",
+ ].join('\n'),
+ },
+ authorization: token,
+ })
+ await t.rejects(
+ npm.exec('publish', []),
+ { code: 'EPACKAGEEXTENSIONS' },
+ 'the post-script manifest re-read catches the injected field'
+ )
+})
+
t.test('throws when invalid tag is semver', async t => {
const { npm } = await loadNpmWithRegistry(t, {
config: {
@@ -853,7 +912,7 @@ t.test('manifest', async t => {
}
delete manifest.gitHead
- manifest.man.sort()
+ manifest.man?.sort()
t.matchSnapshot(manifest, 'manifest')
})
@@ -1495,6 +1554,256 @@ t.test('oidc token exchange - provenance', (t) => {
},
}))
+ const provenanceFileSources = [
+ {
+ name: 'CLI config',
+ options: provenanceBundlePath => ({
+ config: {
+ 'provenance-file': provenanceBundlePath,
+ },
+ }),
+ },
+ {
+ // exercises Publish.#getManifest() and its flatten(filteredPublishConfig, opts)
+ // path: publishConfig must reach opts.provenanceFile before oidc() decides
+ // whether to enable automatic provenance
+ name: 'publishConfig',
+ options: provenanceBundlePath => ({
+ packageJson: {
+ publishConfig: {
+ 'provenance-file': provenanceBundlePath,
+ },
+ },
+ }),
+ },
+ ]
+
+ for (const { name, options } of provenanceFileSources) {
+ t.test(`${name} provenance-file takes precedence over OIDC auto-provenance`, async t => {
+ const bundleDir = t.testdir()
+ const provenanceBundlePath = path.join(
+ bundleDir,
+ 'provenance-bundle.json'
+ )
+ // holder so the libnpmpack mock can return the tarball computed below
+ const packMock = { tarballData: null }
+
+ const sourceOptions = options(provenanceBundlePath)
+
+ const { npm, registry, prefix, joinedOutput } = await mockOidc(t, {
+ oidcOptions: { github: true },
+ config: {
+ '//registry.npmjs.org/:_authToken': 'existing-fallback-token',
+ ...sourceOptions.config,
+ },
+ packageJson: sourceOptions.packageJson,
+ mockGithubOidcOptions: {
+ audience: 'npm:registry.npmjs.org',
+ idToken: githubPublicIdToken,
+ },
+ mockOidcTokenExchangeOptions: {
+ idToken: githubPublicIdToken,
+ body: {
+ token: 'exchange-token',
+ },
+ },
+ publishOptions: {
+ token: 'exchange-token',
+ noPut: true,
+ },
+ load: {
+ mocks: {
+ libnpmaccess: {
+ getVisibility: async () => ({ public: true }),
+ },
+ // publish a deterministic tarball so the bundle subject digest can match it
+ libnpmpack: async () => packMock.tarballData,
+ // libnpmpublish must be mocked as a module so its internal require of
+ // sigstore is intercepted: a user-supplied bundle is only verified,
+ // generation (attest) must never run
+ libnpmpublish: t.mock('libnpmpublish', {
+ 'libnpmpublish/lib/provenance': t.mock('libnpmpublish/lib/provenance', {
+ sigstore: {
+ verify: async () => {},
+ attest: async () => {
+ throw new Error('sigstore.attest must not be called when provenance-file is configured')
+ },
+ },
+ }),
+ }),
+ },
+ },
+ })
+
+ // compute the tarball integrity the same way libnpmpublish does so the
+ // provenance bundle subject matches the packed tarball
+ packMock.tarballData = await pacote.tarball(prefix, { Arborist })
+ const integrity = ssri.fromData(packMock.tarballData, { algorithms: ['sha512'] })
+ const spec = npa.resolve(pkg, '1.0.0')
+ const provenanceBundle = {
+ mediaType: 'application/vnd.dev.sigstore.bundle+json;version=0.2',
+ verificationMaterial: {
+ x509CertificateChain: {
+ certificates: [{ rawBytes: 'dGVzdA==' }],
+ },
+ tlogEntries: [],
+ },
+ dsseEnvelope: {
+ payload: Buffer.from(JSON.stringify({
+ _type: 'https://in-toto.io/Statement/v0.1',
+ subject: [
+ {
+ name: npa.toPurl(spec),
+ digest: { sha512: integrity.sha512[0].hexDigest() },
+ },
+ ],
+ predicateType: 'https://slsa.dev/provenance/v0.2',
+ predicate: {},
+ })).toString('base64'),
+ payloadType: 'application/vnd.in-toto+json',
+ signatures: [{
+ /* eslint-disable-next-line max-len */
+ sig: 'MEUCIQDqHtpkk1d0rMGLmf3qet9jLale3KVn8Pnywpwt7ln+9AIgG9CJvvUmyemhNYHz0DfJ4vMfKk1TMg+m3hR0mISXJos=',
+ keyid: '',
+ }],
+ },
+ }
+ fs.writeFileSync(provenanceBundlePath, JSON.stringify(provenanceBundle, null, 2))
+
+ let publishedBody
+ registry.nock
+ .put(`/${spec.escapedName}`, (body) => {
+ publishedBody = body
+ return true
+ })
+ .matchHeader('authorization', 'Bearer exchange-token')
+ // optional so a failed publish does not leave a pending mock behind
+ .optionally()
+ .reply(200, {})
+
+ // libnpmpublish checks package visibility itself before generating
+ // provenance; optional so it is only consumed if generation is attempted
+ registry.nock
+ .get(`/-/package/${spec.escapedName}/visibility`)
+ .optionally()
+ .reply(200, { public: true })
+
+ await npm.exec('publish', [])
+
+ t.match(joinedOutput(), '+ @npmcli/test-package@1.0.0')
+
+ const attachment =
+ publishedBody?._attachments[`${pkg}-1.0.0.sigstore`]
+
+ t.ok(attachment, 'published packument includes supplied provenance')
+ t.strictSame(
+ JSON.parse(attachment.data),
+ provenanceBundle,
+ 'published sigstore bundle is the user-supplied provenance file'
+ )
+ })
+ }
+
+ t.test('automatic provenance does not leak between workspace publishes', async t => {
+ const provenanceBundlePath = path.join(t.testdir(), 'provenance-bundle.json')
+ const autoPackage = 'workspace-auto-provenance'
+ const filePackage = 'workspace-file-provenance'
+ const publishCalls = []
+ const prefixDir = {
+ 'package.json': JSON.stringify({
+ name: 'workspace-root',
+ version: '1.0.0',
+ workspaces: [autoPackage, filePackage],
+ }),
+ [autoPackage]: {
+ 'package.json': JSON.stringify({
+ name: autoPackage,
+ version: '1.0.0',
+ }),
+ },
+ [filePackage]: {
+ 'package.json': JSON.stringify({
+ name: filePackage,
+ version: '1.0.0',
+ publishConfig: {
+ 'provenance-file': provenanceBundlePath,
+ },
+ }),
+ },
+ }
+
+ const { npm, registry } = await mockOidc(t, {
+ oidcOptions: { github: true },
+ packageName: autoPackage,
+ config: {
+ '//registry.npmjs.org/:_authToken': 'existing-fallback-token',
+ workspaces: true,
+ },
+ mockGithubOidcOptions: {
+ audience: 'npm:registry.npmjs.org',
+ idToken: githubPublicIdToken,
+ times: 2,
+ },
+ mockOidcTokenExchangeOptions: {
+ idToken: githubPublicIdToken,
+ body: {
+ token: 'exchange-token',
+ },
+ },
+ publishOptions: {
+ noPut: true,
+ },
+ load: {
+ prefixDir,
+ mocks: {
+ libnpmaccess: {
+ getVisibility: async () => ({ public: true }),
+ },
+ // mocked as a plain module so the publish options each workspace
+ // receives can be recorded verbatim
+ libnpmpublish: {
+ publish: async (manifest, _tarballData, opts) => {
+ publishCalls.push({
+ name: manifest.name,
+ provenance: opts.provenance,
+ provenanceFile: opts.provenanceFile,
+ })
+ },
+ },
+ },
+ },
+ })
+
+ registry.mockOidcTokenExchange({
+ packageName: filePackage,
+ idToken: githubPublicIdToken,
+ body: {
+ token: 'exchange-token',
+ },
+ })
+ registry.publish(filePackage, { noPut: true })
+
+ await npm.exec('publish', [])
+
+ t.strictSame(publishCalls, [
+ {
+ name: autoPackage,
+ provenance: true,
+ provenanceFile: null,
+ },
+ {
+ name: filePackage,
+ provenance: false,
+ provenanceFile: provenanceBundlePath,
+ },
+ ])
+ t.equal(
+ npm.config.isDefault('provenance'),
+ true,
+ 'automatic provenance does not mutate shared config'
+ )
+ })
+
const brokenJwts = [
'x.invalid-jwt.x',
'x.invalid-jwt.',
diff --git a/deps/npm/test/lib/commands/rebuild.js b/deps/npm/test/lib/commands/rebuild.js
index 1336fa1e7f2..cfd2d2511e1 100644
--- a/deps/npm/test/lib/commands/rebuild.js
+++ b/deps/npm/test/lib/commands/rebuild.js
@@ -222,7 +222,7 @@ t.test('completion', async t => {
t.type(res, Array)
})
-t.test('emits Phase 1 advisory warning for unreviewed install scripts', async t => {
+t.test('emits blocked warning for unreviewed install scripts', async t => {
const { npm, logs } = await setupMockNpm(t, {
prefixDir: {
'package.json': JSON.stringify({ name: 'host', version: '1.0.0' }),
@@ -240,7 +240,7 @@ t.test('emits Phase 1 advisory warning for unreviewed install scripts', async t
await npm.exec('rebuild', [])
t.match(
logs.warn.byTitle('rebuild'),
- [/install scripts not yet covered by allowScripts/]
+ [/install scripts blocked because they are not covered by allowScripts/]
)
})
@@ -264,7 +264,7 @@ t.test('global advisory warning points at npm config set, not approve-scripts',
})
await npm.exec('rebuild', [])
const warn = logs.warn.byTitle('rebuild').join('\n')
- t.match(warn, /install scripts not yet covered by allowScripts/)
+ t.match(warn, /install scripts blocked because they are not covered by allowScripts/)
t.match(warn, /npm config set allow-scripts=canvas/)
t.notMatch(warn, /approve-scripts/)
})
@@ -307,6 +307,54 @@ t.test('no advisory warning when allowScripts covers the package', async t => {
t.strictSame(logs.warn.byTitle('rebuild'), [])
})
+t.test('rebuild <pkg> honors the gate for an unreviewed package', async t => {
+ const { npm, logs, prefix: path } = await setupMockNpm(t, {
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: 'host',
+ version: '1.0.0',
+ dependencies: { canvas: '1.0.0' },
+ }),
+ 'package-lock.json': JSON.stringify({
+ name: 'host',
+ version: '1.0.0',
+ lockfileVersion: 3,
+ requires: true,
+ packages: {
+ '': { name: 'host', version: '1.0.0', dependencies: { canvas: '1.0.0' } },
+ 'node_modules/canvas': {
+ version: '1.0.0',
+ resolved: 'https://registry.npmjs.org/canvas/-/canvas-1.0.0.tgz',
+ hasInstallScript: true,
+ },
+ },
+ }),
+ node_modules: {
+ canvas: {
+ 'package.json': JSON.stringify({
+ name: 'canvas',
+ version: '1.0.0',
+ scripts: {
+ install: "node -e \"require('fs').writeFileSync('ran', '')\"",
+ },
+ }),
+ },
+ },
+ },
+ })
+
+ const ranFile = resolve(path, 'node_modules/canvas/ran')
+ t.throws(() => fs.statSync(ranFile))
+
+ await npm.exec('rebuild', ['canvas'])
+
+ t.throws(() => fs.statSync(ranFile), 'unreviewed install script must not run')
+ t.match(
+ logs.warn.byTitle('rebuild'),
+ [/install scripts blocked because they are not covered by allowScripts/]
+ )
+})
+
t.test('rebuild <name> never targets a bundled dependency', async t => {
const { npm, prefix: path } = await setupMockNpm(t, {
prefixDir: {
diff --git a/deps/npm/test/lib/commands/run.js b/deps/npm/test/lib/commands/run.js
index 2fd58b356dc..aeb93ae7dbd 100644
--- a/deps/npm/test/lib/commands/run.js
+++ b/deps/npm/test/lib/commands/run.js
@@ -85,17 +85,12 @@ t.test('default env, start, and restart scripts', async t => {
})
t.test('start', async t => {
- await runScript.exec(['start'])
- t.match(RUN_SCRIPTS(), [
- {
- path: npm.localPrefix,
- args: [],
- scriptShell: undefined,
- stdio: 'inherit',
- pkg: { name: 'x', version: '1.2.3', _id: 'x@1.2.3', scripts: {} },
- event: 'start',
- },
- ])
+ // run-script@11 removed the implicit `node server.js` behavior, so a
+ // package with a server.js file but no start script now errors.
+ await t.rejects(
+ runScript.exec(['start']),
+ /Missing script: "start"/
+ )
})
t.test('env', async t => {
diff --git a/deps/npm/test/lib/commands/sbom.js b/deps/npm/test/lib/commands/sbom.js
index b93011b5e28..a0cbca0ed4e 100644
--- a/deps/npm/test/lib/commands/sbom.js
+++ b/deps/npm/test/lib/commands/sbom.js
@@ -473,7 +473,7 @@ t.test('sbom', async t => {
})
await t.rejects(sbom.exec([]), {
code: 'EUSAGE',
- message: 'A package lock or shrinkwrap file is required in package-lock-only mode',
+ message: 'A package-lock.json file is required in package-lock-only mode',
},
'should throw error')
diff --git a/deps/npm/test/lib/commands/set.js b/deps/npm/test/lib/commands/set.js
index 8574b80345e..fbb46571ecd 100644
--- a/deps/npm/test/lib/commands/set.js
+++ b/deps/npm/test/lib/commands/set.js
@@ -18,13 +18,13 @@ t.test('no args', async t => {
t.test('test-config-item', async t => {
const { npm, home, joinedOutput } = await mockNpm(t, {
homeDir: {
- '.npmrc': 'original-config-test=original value',
+ '.npmrc': 'tag=beta',
},
})
t.equal(
- npm.config.get('original-config-test'),
- 'original value',
+ npm.config.get('tag'),
+ 'beta',
'original config is set from npmrc'
)
@@ -46,7 +46,7 @@ t.test('test-config-item', async t => {
t.equal(
cleanNewlines(await fs.readFile(join(home, '.npmrc'), 'utf-8')),
[
- 'original-config-test=original value',
+ 'tag=beta',
'fund=true',
'',
].join('\n'),
diff --git a/deps/npm/test/lib/commands/shrinkwrap.js b/deps/npm/test/lib/commands/shrinkwrap.js
deleted file mode 100644
index ec65ca604a8..00000000000
--- a/deps/npm/test/lib/commands/shrinkwrap.js
+++ /dev/null
@@ -1,232 +0,0 @@
-const t = require('tap')
-const fs = require('node:fs')
-const { resolve } = require('node:path')
-const { load: loadMockNpm } = require('../../fixtures/mock-npm')
-
-// Attempt to parse json values in snapshots before
-// stringifying to remove escaped values like \\"
-// This also doesn't reorder the keys of the object
-// like tap does by default which is nice in this case
-t.formatSnapshot = obj =>
- JSON.stringify(
- obj,
- (k, v) => {
- try {
- return JSON.parse(v)
- } catch {
- // leave invalid JSON as a string
- }
- return v
- },
- 2
- )
-
-// Run shrinkwrap against a specified prefixDir with config items
-// and make some assertions that should always be true. Sets
-// the results on t.context for use in child tests
-const shrinkwrap = async (t, prefixDir = {}, config = {}) => {
- const { npm, logs } = await loadMockNpm(t, {
- config,
- prefixDir,
- })
-
- await npm.exec('shrinkwrap', [])
-
- const newFile = resolve(npm.prefix, 'npm-shrinkwrap.json')
- const oldFile = resolve(npm.prefix, 'package-lock.json')
-
- t.notOk(fs.existsSync(oldFile), 'package-lock is always deleted')
- t.teardown(() => delete t.context)
- t.context = {
- localPrefix: prefixDir,
- config,
- shrinkwrap: JSON.parse(fs.readFileSync(newFile)),
- logs: logs.notice,
- warn: logs.warn,
- }
-}
-
-// Run shrinkwrap against all combinations of existing and config
-// lockfile versions
-const shrinkwrapMatrix = async (t, file, assertions) => {
- const ancient = JSON.stringify({ lockfileVersion: 1 })
- const existing = JSON.stringify({ lockfileVersion: 2 })
- const upgrade = { 'lockfile-version': 3 }
- const downgrade = { 'lockfile-version': 1 }
-
- let ancientDir = {}
- let existingDir = null
- if (file === 'package-lock') {
- ancientDir = { 'package-lock.json': ancient }
- existingDir = { 'package-lock.json': existing }
- } else if (file === 'npm-shrinkwrap') {
- ancientDir = { 'npm-shrinkwrap.json': ancient }
- existingDir = { 'npm-shrinkwrap.json': existing }
- } else if (file === 'hidden-lockfile') {
- ancientDir = { node_modules: { '.package-lock.json': ancient } }
- existingDir = { node_modules: { '.package-lock.json': existing } }
- }
-
- await t.test('ancient', async t => {
- await shrinkwrap(t, ancientDir)
- t.match(t.context, assertions.ancient)
- t.matchSnapshot(t.context)
- })
- await t.test('ancient upgrade', async t => {
- await shrinkwrap(t, ancientDir, upgrade)
- t.match(t.context, assertions.ancientUpgrade)
- t.matchSnapshot(t.context)
- })
-
- if (existingDir) {
- await t.test('existing', async t => {
- await shrinkwrap(t, existingDir)
- t.match(t.context, assertions.existing)
- t.matchSnapshot(t.context)
- })
- await t.test('existing upgrade', async t => {
- await shrinkwrap(t, existingDir, upgrade)
- t.match(t.context, assertions.existingUpgrade)
- t.matchSnapshot(t.context)
- })
- await t.test('existing downgrade', async t => {
- await shrinkwrap(t, existingDir, downgrade)
- t.match(t.context, assertions.existingDowngrade)
- t.matchSnapshot(t.context)
- })
- }
-}
-
-const NOTICES = {
- CREATED: (v = '') => [`created a lockfile as npm-shrinkwrap.json${v && ` with version ${v}`}`],
- RENAMED: (v = '') => [
- `package-lock.json has been renamed to npm-shrinkwrap.json${
- v && ` and updated to version ${v}`
- }`,
- ],
- UPDATED: (v = '') => [`npm-shrinkwrap.json updated to version ${v}`],
- SAME: () => [`npm-shrinkwrap.json up to date`],
- CONVERTING: (current, next) =>
- [`Converting lock file (npm-shrinkwrap.json) from v${current} -> v${next}`],
-}
-
-t.test('with nothing', t =>
- shrinkwrapMatrix(t, null, {
- ancient: {
- shrinkwrap: { lockfileVersion: 3 },
- logs: NOTICES.CREATED(3),
- warn: [],
- },
- ancientUpgrade: {
- shrinkwrap: { lockfileVersion: 3 },
- logs: NOTICES.CREATED(3),
- warn: [],
- },
- })
-)
-
-t.test('with package-lock.json', t =>
- shrinkwrapMatrix(t, 'package-lock', {
- ancient: {
- shrinkwrap: { lockfileVersion: 3 },
- logs: NOTICES.RENAMED(3),
- warn: NOTICES.CONVERTING(1, 3),
- },
- ancientUpgrade: {
- shrinkwrap: { lockfileVersion: 3 },
- logs: NOTICES.RENAMED(3),
- warn: NOTICES.CONVERTING(1, 3),
- },
- existing: {
- shrinkwrap: { lockfileVersion: 2 },
- logs: NOTICES.RENAMED(),
- warn: [],
- },
- existingUpgrade: {
- shrinkwrap: { lockfileVersion: 3 },
- logs: NOTICES.RENAMED(3),
- warn: NOTICES.CONVERTING(2, 3),
- },
- existingDowngrade: {
- shrinkwrap: { lockfileVersion: 1 },
- logs: NOTICES.RENAMED(1),
- warn: NOTICES.CONVERTING(2, 1),
- },
- })
-)
-
-t.test('with npm-shrinkwrap.json', t =>
- shrinkwrapMatrix(t, 'npm-shrinkwrap', {
- ancient: {
- shrinkwrap: { lockfileVersion: 3 },
- logs: NOTICES.UPDATED(3),
- warn: NOTICES.CONVERTING(1, 3),
- },
- ancientUpgrade: {
- shrinkwrap: { lockfileVersion: 3 },
- logs: NOTICES.UPDATED(3),
- warn: NOTICES.CONVERTING(1, 3),
- },
- existing: {
- shrinkwrap: { lockfileVersion: 2 },
- logs: NOTICES.SAME(),
- warn: [],
- },
- existingUpgrade: {
- shrinkwrap: { lockfileVersion: 3 },
- logs: NOTICES.UPDATED(3),
- warn: NOTICES.CONVERTING(2, 3),
- },
- existingDowngrade: {
- shrinkwrap: { lockfileVersion: 1 },
- logs: NOTICES.UPDATED(1),
- warn: NOTICES.CONVERTING(2, 1),
- },
- })
-)
-
-t.test('with hidden lockfile', t =>
- shrinkwrapMatrix(t, 'hidden-lockfile', {
- ancient: {
- shrinkwrap: { lockfileVersion: 1 },
- logs: NOTICES.CREATED(),
- warn: [],
- },
- ancientUpgrade: {
- shrinkwrap: { lockfileVersion: 3 },
- logs: NOTICES.CREATED(),
- warn: NOTICES.CONVERTING(1, 3),
- },
- existing: {
- shrinkwrap: { lockfileVersion: 2 },
- logs: NOTICES.CREATED(),
- warn: [],
- },
- existingUpgrade: {
- shrinkwrap: { lockfileVersion: 3 },
- logs: NOTICES.CREATED(3),
- warn: NOTICES.CONVERTING(2, 3),
- },
- existingDowngrade: {
- shrinkwrap: { lockfileVersion: 1 },
- logs: NOTICES.CREATED(1),
- warn: NOTICES.CONVERTING(2, 1),
- },
- })
-)
-
-t.test('throws in global mode', async t => {
- t.rejects(
- shrinkwrap(
- t,
- {},
- {
- global: true,
- }
- ),
- {
- message: '`npm shrinkwrap` does not work for global packages',
- code: 'ESHRINKWRAPGLOBAL',
- }
- )
-})
diff --git a/deps/npm/test/lib/commands/stage/list.js b/deps/npm/test/lib/commands/stage/list.js
index e66680db827..ded079a5ab7 100644
--- a/deps/npm/test/lib/commands/stage/list.js
+++ b/deps/npm/test/lib/commands/stage/list.js
@@ -15,6 +15,7 @@ const stageItems = [
actor: 'octocat',
actorType: 'user',
shasum: '4f7f5f1d5bcf2f72f6e4d6c4f3b2812d8a2f6c19',
+ status: 'validating',
},
{
id: 'f8e7a45b-7a5f-4f31-8e6d-9dd1c6ef38c0',
@@ -25,6 +26,7 @@ const stageItems = [
actor: 'npm-bot',
actorType: 'trusted automation',
shasum: '8eb3b4e9b6e3d0d2c86be1e6d4f43f4be62e80ad',
+ status: 'staged',
},
]
@@ -45,6 +47,9 @@ t.test('lists all staged packages', async t => {
t.match(out, 'package name: example-lib')
t.match(out, 'version: 1.2.3')
t.match(out, 'version: 0.4.0')
+ t.match(out, 'status: validating')
+ t.match(out, 'status: staged')
+ t.equal(out.match(/status:/g)?.length, 2, 'all server-provided statuses are shown')
})
t.test('lists with package filter', async t => {
@@ -80,6 +85,8 @@ t.test('lists with --json', async t => {
t.equal(out.length, 2)
t.equal(out[0].packageName, '@npmcli/example-package')
t.equal(out[0].id, '1de6f3db-2ed9-4d72-b3dd-8f0e2b474a2f', 'uuid id is not redacted')
+ t.equal(out[0].status, 'validating')
+ t.equal(out[1].status, 'staged')
})
t.test('shows message when no packages', async t => {
diff --git a/deps/npm/test/lib/commands/stage/view.js b/deps/npm/test/lib/commands/stage/view.js
index 604caf98fb2..36afc98b13d 100644
--- a/deps/npm/test/lib/commands/stage/view.js
+++ b/deps/npm/test/lib/commands/stage/view.js
@@ -14,6 +14,7 @@ const stageItem = {
actor: 'octocat',
actorType: 'user',
shasum: '4f7f5f1d5bcf2f72f6e4d6c4f3b2812d8a2f6c19',
+ status: 'awaiting_approval',
}
t.test('views a staged package', async t => {
@@ -31,6 +32,7 @@ t.test('views a staged package', async t => {
t.match(out, /id:/)
t.match(out, 'package name: @npmcli/example-package')
t.match(out, 'version: 1.2.3')
+ t.match(out, 'status: awaiting_approval')
})
t.test('views with --json', async t => {
@@ -47,6 +49,7 @@ t.test('views with --json', async t => {
const out = JSON.parse(joinedOutput())
t.ok(out.id)
t.equal(out.packageName, '@npmcli/example-package')
+ t.equal(out.status, 'awaiting_approval')
})
t.test('throws usageError without stage-id', async t => {
diff --git a/deps/npm/test/lib/commands/star.js b/deps/npm/test/lib/commands/star.js
deleted file mode 100644
index c5f233f01cc..00000000000
--- a/deps/npm/test/lib/commands/star.js
+++ /dev/null
@@ -1,61 +0,0 @@
-const t = require('tap')
-const { load: loadMockNpm } = require('../../fixtures/mock-npm.js')
-const MockRegistry = require('@npmcli/mock-registry')
-
-const pkgName = '@npmcli/test-package'
-const authToken = 'test-auth-token'
-const username = 'test-user'
-const auth = { '//registry.npmjs.org/:_authToken': authToken }
-
-t.test('no args', async t => {
- const { npm } = await loadMockNpm(t)
- await t.rejects(
- npm.exec('star', []),
- { code: 'EUSAGE' },
- 'should throw usage error'
- )
-})
-
-t.test('first person to star a package unicode:false', async t => {
- const { npm, joinedOutput } = await loadMockNpm(t, {
- config: { unicode: false, ...auth },
- })
- const registry = new MockRegistry({
- tap: t,
- registry: npm.config.get('registry'),
- authorization: authToken,
- })
- const manifest = registry.manifest({ name: pkgName })
- await registry.package({ manifest, query: { write: true } })
- registry.whoami({ username })
- registry.star(manifest, { [username]: true })
-
- await npm.exec('star', [pkgName])
- t.equal(
- joinedOutput(),
- '(*) @npmcli/test-package',
- 'should output starred package msg'
- )
-})
-
-t.test('second person to star a package unicode:true', async t => {
- const { npm, joinedOutput } = await loadMockNpm(t, {
- config: { unicode: true, ...auth },
- })
- const registry = new MockRegistry({
- tap: t,
- registry: npm.config.get('registry'),
- authorization: authToken,
- })
- const manifest = registry.manifest({ name: pkgName, users: { otheruser: true } })
- await registry.package({ manifest, query: { write: true } })
- registry.whoami({ username })
- registry.star(manifest, { otheruser: true, [username]: true })
-
- await npm.exec('star', [pkgName])
- t.equal(
- joinedOutput(),
- '★ @npmcli/test-package',
- 'should output starred package msg'
- )
-})
diff --git a/deps/npm/test/lib/commands/stars.js b/deps/npm/test/lib/commands/stars.js
deleted file mode 100644
index fc38ca77ac7..00000000000
--- a/deps/npm/test/lib/commands/stars.js
+++ /dev/null
@@ -1,127 +0,0 @@
-const t = require('tap')
-const realFetch = require('npm-registry-fetch')
-const mockNpm = require('../../fixtures/mock-npm')
-
-const noop = () => {}
-
-const mockStars = async (t, { npmFetch = noop, exec = true, ...opts }) => {
- const mock = await mockNpm(t, {
- command: 'stars',
- exec,
- mocks: {
- 'npm-registry-fetch': Object.assign(noop, realFetch, { json: npmFetch }),
- '{LIB}/utils/get-identity.js': async () => 'foo',
- },
- ...opts,
- })
-
- return {
- ...mock,
- result: mock.stars.output,
- logs: () => mock.logs.byTitle('stars'),
- }
-}
-
-t.test('no args', async t => {
- t.plan(3)
-
- const npmFetch = async (uri, opts) => {
- t.equal(uri, '/-/_view/starredByUser', 'should fetch from expected uri')
- t.equal(opts.query.key, '"foo"', 'should match logged in username')
-
- return {
- rows: [
- { value: '@npmcli/arborist' },
- { value: '@npmcli/map-workspaces' },
- { value: 'libnpmfund' },
- { value: 'libnpmpublish' },
- { value: 'ipt' },
- ],
- }
- }
-
- const { result } = await mockStars(t, { npmFetch })
-
- t.matchSnapshot(
- result,
- 'should output a list of starred packages'
- )
-})
-
-t.test('npm star <user>', async t => {
- t.plan(3)
-
- const npmFetch = async (uri, opts) => {
- t.equal(uri, '/-/_view/starredByUser', 'should fetch from expected uri')
- t.equal(opts.query.key, '"ruyadorno"', 'should match username')
-
- return {
- rows: [{ value: '@npmcli/arborist' }],
- }
- }
-
- const { result } = await mockStars(t, { npmFetch, exec: ['ruyadorno'] })
-
- t.match(
- result,
- '@npmcli/arborist',
- 'should output expected list of starred packages'
- )
-})
-
-t.test('unauthorized request', async t => {
- const npmFetch = async () => {
- throw Object.assign(
- new Error('Not logged in'),
- { code: 'ENEEDAUTH' }
- )
- }
-
- const { joinedOutput, stars, logs } = await mockStars(t, { npmFetch, exec: false })
-
- await t.rejects(
- stars.exec([]),
- /Not logged in/,
- 'should throw unauthorized request msg'
- )
-
- t.strictSame(
- logs(),
- ['stars auth is required to look up your username'],
- 'should warn auth required msg'
- )
-
- t.equal(
- joinedOutput(),
- '',
- 'should have empty output'
- )
-})
-
-t.test('unexpected error', async t => {
- const npmFetch = async () => {
- throw new Error('ERROR')
- }
-
- const { stars, logs } = await mockStars(t, { npmFetch, exec: false })
-
- await t.rejects(
- stars.exec([]),
- /ERROR/,
- 'should throw unexpected error message'
- )
-
- t.strictSame(logs(), [], 'no logs')
-})
-
-t.test('no pkg starred', async t => {
- const npmFetch = async () => ({ rows: [] })
-
- const { logs } = await mockStars(t, { npmFetch })
-
- t.strictSame(
- logs(),
- ['stars user has not starred any packages'],
- 'should warn no starred packages msg'
- )
-})
diff --git a/deps/npm/test/lib/commands/token.js b/deps/npm/test/lib/commands/token.js
index 34297a923c8..41ca9395375 100644
--- a/deps/npm/test/lib/commands/token.js
+++ b/deps/npm/test/lib/commands/token.js
@@ -475,3 +475,115 @@ t.test('token create invalid cidr', async t => {
message: 'CIDR whitelist contains invalid CIDR entry: apple/cider',
})
})
+
+t.test('token create stage-only produces stage-only policy and no warning', async t => {
+ const { npm, outputs, logs } = await loadMockNpm(t, {
+ config: {
+ ...auth,
+ name: 'stage-only-token',
+ password: 'test-password',
+ 'packages-and-scopes-permission': 'read-write-stage-only',
+ },
+ })
+
+ const registry = new MockRegistry({
+ tap: t,
+ registry: npm.config.get('registry'),
+ authorization: authToken,
+ })
+
+ registry.createToken({
+ name: 'stage-only-token',
+ password: 'test-password',
+ packages_and_scopes_permission: 'read-write-stage-only',
+ })
+
+ await npm.exec('token', ['create'])
+ t.match(outputs, ['Created token n3wt0k3n'])
+ t.strictSame(logs.warn, [], 'no deprecation warning for stage-only tokens')
+})
+
+t.test('token create read-write warns about direct-publish', async t => {
+ const { npm, outputs, logs } = await loadMockNpm(t, {
+ config: {
+ ...auth,
+ name: 'rw-token',
+ password: 'test-password',
+ 'packages-and-scopes-permission': 'read-write',
+ },
+ })
+
+ const registry = new MockRegistry({
+ tap: t,
+ registry: npm.config.get('registry'),
+ authorization: authToken,
+ })
+
+ registry.createToken({
+ name: 'rw-token',
+ password: 'test-password',
+ packages_and_scopes_permission: 'read-write',
+ })
+
+ await npm.exec('token', ['create'])
+ t.match(outputs, ['Created token n3wt0k3n'])
+ t.match(logs.warn, [/publish directly to the registry/], 'warns about direct-publish token')
+ t.match(logs.warn, [/read-write-stage-only/], 'warning points to stage-only tokens')
+ t.match(logs.warn, [/https:\/\/gh\.io\/bypass-2fa-tokens-no-longer-publish/], 'warning includes the docs link')
+})
+
+t.test('token create bypass-2fa alone does not warn', async t => {
+ const { npm, outputs, logs } = await loadMockNpm(t, {
+ config: {
+ ...auth,
+ name: 'bypass-token',
+ password: 'test-password',
+ 'bypass-2fa': true,
+ },
+ })
+
+ const registry = new MockRegistry({
+ tap: t,
+ registry: npm.config.get('registry'),
+ authorization: authToken,
+ })
+
+ registry.createToken({
+ name: 'bypass-token',
+ password: 'test-password',
+ bypass_2fa: true,
+ })
+
+ await npm.exec('token', ['create'])
+ t.match(outputs, ['Created token n3wt0k3n'])
+ t.strictSame(logs.warn, [], 'bypass-2fa alone grants no publish capability, so no warning')
+})
+
+t.test('token create read-write with bypass-2fa warns about direct-publish', async t => {
+ const { npm, outputs, logs } = await loadMockNpm(t, {
+ config: {
+ ...auth,
+ name: 'rw-bypass-token',
+ password: 'test-password',
+ 'packages-and-scopes-permission': 'read-write',
+ 'bypass-2fa': true,
+ },
+ })
+
+ const registry = new MockRegistry({
+ tap: t,
+ registry: npm.config.get('registry'),
+ authorization: authToken,
+ })
+
+ registry.createToken({
+ name: 'rw-bypass-token',
+ password: 'test-password',
+ packages_and_scopes_permission: 'read-write',
+ bypass_2fa: true,
+ })
+
+ await npm.exec('token', ['create'])
+ t.match(outputs, ['Created token n3wt0k3n'])
+ t.match(logs.warn, [/publish directly to the registry/], 'warns for read-write automation publish token')
+})
diff --git a/deps/npm/test/lib/commands/uninstall.js b/deps/npm/test/lib/commands/uninstall.js
index 049bf2da8b1..0302aa5bac3 100644
--- a/deps/npm/test/lib/commands/uninstall.js
+++ b/deps/npm/test/lib/commands/uninstall.js
@@ -143,6 +143,34 @@ t.test('remove multiple installed libs', async t => {
t.throws(() => fs.statSync(b), 'should have removed b package from nm')
})
+t.test('rejects an arg with a version spec', async t => {
+ const { uninstall } = await mockNpm(t, {
+ prefixDir: {
+ 'package.json': JSON.stringify({
+ name: 'test-rm-version-spec',
+ version: '1.0.0',
+ dependencies: {
+ foo: '*',
+ },
+ }),
+ node_modules: {
+ foo: {
+ 'package.json': JSON.stringify({
+ name: 'foo',
+ version: '1.0.0',
+ }),
+ },
+ },
+ },
+ })
+
+ await t.rejects(
+ uninstall(['foo@1']),
+ { code: 'ERMARGS', message: /npm rm foo/ },
+ 'should throw ERMARGS instead of silently no-oping'
+ )
+})
+
t.test('no args local', async t => {
const { uninstall } = await mockNpm(t)
diff --git a/deps/npm/test/lib/commands/unstar.js b/deps/npm/test/lib/commands/unstar.js
deleted file mode 100644
index ee31428546d..00000000000
--- a/deps/npm/test/lib/commands/unstar.js
+++ /dev/null
@@ -1,62 +0,0 @@
-const t = require('tap')
-const { load: loadMockNpm } = require('../../fixtures/mock-npm.js')
-const MockRegistry = require('@npmcli/mock-registry')
-
-const pkgName = '@npmcli/test-package'
-const authToken = 'test-auth-token'
-const username = 'test-user'
-const auth = { '//registry.npmjs.org/:_authToken': authToken }
-
-t.test('no args', async t => {
- const { npm } = await loadMockNpm(t)
- await t.rejects(
- npm.exec('unstar', []),
- { code: 'EUSAGE' },
- 'should throw usage error'
- )
-})
-
-t.test('unstar a package unicode:false', async t => {
- const { npm, joinedOutput } = await loadMockNpm(t, {
- config: { unicode: false, ...auth },
- })
- const registry = new MockRegistry({
- tap: t,
- registry: npm.config.get('registry'),
- authorization: authToken,
- })
- const manifest = registry.manifest({ name: pkgName, users: { [username]: true } })
- await registry.package({ manifest, query: { write: true } })
- registry.whoami({ username })
- registry.star(manifest, {})
-
- await npm.exec('unstar', [pkgName])
- t.equal(
- joinedOutput(),
- '( ) @npmcli/test-package',
- 'should output unstarred package msg'
- )
-})
-
-t.test('unstar a package unicode:true', async t => {
- const { npm, joinedOutput } = await loadMockNpm(t, {
- config: { unicode: true, ...auth },
- })
-
- const registry = new MockRegistry({
- tap: t,
- registry: npm.config.get('registry'),
- authorization: authToken,
- })
- const manifest = registry.manifest({ name: pkgName, users: { [username]: true } })
- await registry.package({ manifest, query: { write: true } })
- registry.whoami({ username })
- registry.star(manifest, {})
-
- await npm.exec('unstar', [pkgName])
- t.equal(
- joinedOutput(),
- '☆ @npmcli/test-package',
- 'should output unstarred package msg'
- )
-})
diff --git a/deps/npm/test/lib/commands/view.js b/deps/npm/test/lib/commands/view.js
index f1b7b589511..3b5a581f3a6 100644
--- a/deps/npm/test/lib/commands/view.js
+++ b/deps/npm/test/lib/commands/view.js
@@ -189,14 +189,37 @@ const packument = (nv, opts) => {
},
purple: {
name: 'purple',
+ 'dist-tags': {
+ latest: '1.0.0',
+ },
versions: {
'1.0.0': {
+ version: '1.0.0',
foo: 1,
+ metadata: {
+ channels: ['latest', 'next'],
+ empty: [],
+ release: {
+ stable: true,
+ },
+ },
+ items: [
+ { tags: ['one', 'two'] },
+ ],
maintainers: [
{ name: 'claudia' },
],
},
- '1.0.1': {},
+ '1.0.1': {
+ version: '1.0.1',
+ metadata: {
+ channels: ['next'],
+ empty: [],
+ release: {
+ stable: false,
+ },
+ },
+ },
},
},
green: {
@@ -394,7 +417,9 @@ const loadMockNpm = async function (t, opts = {}) {
}
t.test('package from git', async t => {
- const { view, joinedOutput } = await loadMockNpm(t, { config: { unicode: false } })
+ const { view, joinedOutput } = await loadMockNpm(t, {
+ config: { unicode: false, 'allow-git': 'all' },
+ })
await view.exec(['https://github.com/npm/green'])
t.matchSnapshot(joinedOutput())
})
@@ -465,6 +490,29 @@ t.test('package with --json and semver range', async t => {
t.matchSnapshot(joinedOutput())
})
+t.test('package with --json and single-match semver range preserves array output', async t => {
+ const { view, joinedOutput } = await loadMockNpm(t, { config: { json: true } })
+ await view.exec(['single-version@^1'])
+ const parsed = JSON.parse(joinedOutput())
+ t.ok(Array.isArray(parsed), 'preserves the top-level array for semver ranges')
+ t.equal(parsed.length, 1, 'returns the single matching version in an array')
+ t.match(parsed[0], {
+ name: 'single-version',
+ version: '1.0.0',
+ dist: {
+ shasum: '123',
+ tarball: 'http://hm.single-version.com/1.0.0.tgz',
+ fileCount: 1,
+ },
+ }, 'returns the expected package data')
+})
+
+t.test('package field with --json and single-match semver range preserves array output', async t => {
+ const { view, joinedOutput } = await loadMockNpm(t, { config: { json: true } })
+ await view.exec(['single-version@^1', 'version'])
+ t.strictSame(JSON.parse(joinedOutput()), ['1.0.0'], 'does not unwrap single field matches for semver ranges')
+})
+
t.test('package with _npmUser.trustedPublisher shows cleaned up property with --json', async t => {
const { view, joinedOutput } = await loadMockNpm(t, { config: { json: true } })
await view.exec(['cyan-oidc@^1.0.0'])
@@ -480,7 +528,119 @@ t.test('package with --json and no versions', async t => {
t.test('package with --json and single string arg', async t => {
const { view, joinedOutput } = await loadMockNpm(t, { config: { json: true } })
await view.exec(['blue', 'dist-tags.latest'])
- t.equal(JSON.parse(joinedOutput()), '1.0.0', 'no info to display')
+ t.strictSame(JSON.parse(joinedOutput()), ['1.0.0'], 'returns single string value as array')
+})
+
+t.test('package with --json and array-valued field', async t => {
+ const { view, joinedOutput } = await loadMockNpm(t, { config: { json: true } })
+ await view.exec(['blue', 'versions'])
+ t.strictSame(
+ JSON.parse(joinedOutput()),
+ ['1.0.0', '1.0.1'],
+ 'returns the field value without an additional result wrapper'
+ )
+})
+
+t.test('package with --json and array-valued field from multiple matches', async t => {
+ const { view, joinedOutput } = await loadMockNpm(t, { config: { json: true } })
+ await view.exec(['blue@^1', 'versions'])
+ t.strictSame(
+ JSON.parse(joinedOutput()),
+ [
+ ['1.0.0', '1.0.1'],
+ ['1.0.0', '1.0.1'],
+ ],
+ 'preserves the result boundary for each matching version'
+ )
+})
+
+t.test('package field access with --json preserves value shapes', async t => {
+ const cases = [
+ {
+ name: 'nested scalar field',
+ args: ['purple@1.0.0', 'metadata.release.stable'],
+ expected: [true],
+ },
+ {
+ name: 'nested object field',
+ args: ['purple@1.0.0', 'metadata.release'],
+ expected: [{ stable: true }],
+ },
+ {
+ name: 'nested empty array field',
+ args: ['purple@1.0.0', 'metadata.empty'],
+ expected: [],
+ },
+ {
+ name: 'nested single-item array field',
+ args: ['purple@1.0.1', 'metadata.channels'],
+ expected: ['next'],
+ },
+ {
+ name: 'nested multi-item array field',
+ args: ['purple@1.0.0', 'metadata.channels'],
+ expected: ['latest', 'next'],
+ },
+ {
+ name: 'array field with bracket notation',
+ args: ['purple@1.0.0', 'metadata[channels]'],
+ expected: ['latest', 'next'],
+ },
+ {
+ name: 'indexed array element',
+ args: ['purple@1.0.0', 'metadata.channels[0]'],
+ expected: ['latest'],
+ },
+ {
+ name: 'expanded array subfield',
+ args: ['pink@1.0.0', 'maintainers.url'],
+ expected: [{
+ 'maintainers[0].url': 'http://c.pink.com',
+ 'maintainers[1].url': 'http://i.pink.com',
+ }],
+ },
+ {
+ name: 'expanded array-valued subfield',
+ args: ['purple@1.0.0', 'items.tags'],
+ expected: ['one', 'two'],
+ },
+ {
+ name: 'multiple requested fields',
+ args: ['purple@1.0.0', 'metadata.channels', 'metadata.release'],
+ expected: [{
+ 'metadata.channels': ['latest', 'next'],
+ 'metadata.release': { stable: true },
+ }],
+ },
+ {
+ name: 'multiple requested fields with one missing',
+ args: ['purple@1.0.0', 'metadata.channels', 'missing'],
+ expected: ['latest', 'next'],
+ },
+ {
+ name: 'array field from multiple matching versions',
+ args: ['purple@^1', 'metadata.channels'],
+ expected: [
+ ['latest', 'next'],
+ ['next'],
+ ],
+ },
+ {
+ name: 'array field present in one of multiple matching versions',
+ args: ['purple@^1', 'items'],
+ expected: [
+ { tags: ['one', 'two'] },
+ ],
+ },
+ ]
+
+ for (const { name, args, expected } of cases) {
+ await t.test(name, async t => {
+ const { view, joinedOutput } = await loadMockNpm(t, { config: { json: true } })
+ await view.exec(args)
+ t.strictSame(JSON.parse(joinedOutput()), expected)
+ })
+ }
})
t.test('package with single version', async t => {
@@ -494,7 +654,7 @@ t.test('package with single version', async t => {
const { view, joinedOutput } = await loadMockNpm(t, { config: { json: true } })
await view.exec(['single-version', 'versions'])
const parsed = JSON.parse(joinedOutput())
- t.strictSame(parsed, ['1.0.0'], 'does not unwrap single item arrays in json')
+ t.strictSame(parsed, ['1.0.0'], 'preserves the array-valued field')
})
t.test('no json and versions arg', async t => {
@@ -741,6 +901,18 @@ t.test('workspaces', async t => {
t.matchSnapshot(joinedOutput())
})
+ t.test('all workspaces array field --json', async t => {
+ const { view, joinedOutput } = await loadMockNpm(t, {
+ prefixDir,
+ config: { unicode: false, workspaces: true, json: true },
+ })
+ await view.exec(['.', 'versions'])
+ t.strictSame(JSON.parse(joinedOutput()), {
+ green: ['1.0.0', '1.0.1'],
+ orange: ['1.0.0', '1.0.1'],
+ })
+ })
+
t.test('single workspace --json', async t => {
const { view, joinedOutput } = await loadMockNpm(t, {
prefixDir,
diff --git a/deps/npm/test/lib/npm.js b/deps/npm/test/lib/npm.js
index c4c0d720e86..0957baa499f 100644
--- a/deps/npm/test/lib/npm.js
+++ b/deps/npm/test/lib/npm.js
@@ -1,5 +1,5 @@
const t = require('tap')
-const { resolve, dirname, join } = require('node:path')
+const { resolve, join } = require('node:path')
const fs = require('node:fs/promises')
const { time } = require('proc-log')
const { load: loadMockNpm } = require('../fixtures/mock-npm.js')
@@ -35,6 +35,26 @@ t.test('npm.load', async t => {
)
})
+ await t.test('rejects extension-file from a disallowed config source', async t => {
+ const { npm } = await loadMockNpm(t, { load: false })
+ // a disallowed (env) source; mockGlobals restores process.env on teardown
+ mockGlobals(t, { 'process.env.npm_config_extension_file': 'tools/ext.mjs' })
+ await t.rejects(
+ () => npm.load(),
+ { code: 'ENPMEXTENSIONCONFIG' },
+ 'env config source is rejected with a surfaced error'
+ )
+ })
+
+ await t.test('accepts extension-file from project config', async t => {
+ // config.load() exports npm_config_* to the real env, so clean it up to avoid leaking into raw-env tests
+ t.teardown(() => delete process.env.npm_config_extension_file)
+ const { npm } = await loadMockNpm(t, {
+ prefixDir: { '.npmrc': 'extension-file=tools/ext.mjs' },
+ })
+ t.equal(npm.config.find('extension-file'), 'project', 'loaded from project config without error')
+ })
+
await t.test('basic loading', async t => {
const { npm, logs, cache } = await loadMockNpm(t, {
prefixDir: { node_modules: {} },
@@ -88,73 +108,6 @@ t.test('npm.load', async t => {
])
})
- await t.test('node is a symlink', async t => {
- const node = process.platform === 'win32' ? 'node.exe' : 'node'
- const { Npm, npm, logs, outputs, prefix } = await loadMockNpm(t, {
- prefixDir: {
- bin: t.fixture('symlink', dirname(process.execPath)),
- },
- config: {
- timing: true,
- usage: '',
- scope: 'foo',
- },
- argv: [
- 'token',
- 'revoke',
- 'blergggg',
- ],
- globals: (dirs) => ({
- 'process.env.PATH': resolve(dirs.prefix, 'bin'),
- 'process.argv': [
- node,
- process.argv[1],
- ],
- }),
- })
-
- t.equal(npm.config.get('scope'), '@foo', 'added the @ sign to scope')
-
- t.match([
- ...logs.timing.filter((p) => p.startsWith('npm:load:whichnode')),
- ...logs.verbose,
- ...logs.timing.filter((p) => p.startsWith('npm:load')),
- ], [
- /npm:load:whichnode Completed in [0-9.]+ms/,
- `node symlink ${resolve(prefix, 'bin', node)}`,
- /title npm token revoke blergggg/,
- /argv "token" "revoke" "blergggg".*"--usage" "--scope" "foo"/,
- /logfile logs-max:\d+ dir:.*/,
- /logfile .*-debug-0.log/,
- /npm:load:.* Completed in [0-9.]+ms/,
- ])
- t.equal(process.execPath, resolve(prefix, 'bin', node))
-
- outputs.length = 0
- logs.length = 0
- await npm.exec('ll', [])
-
- t.equal(npm.command, 'll', 'command set to first npm command')
- t.equal(npm.flatOptions.npmCommand, 'll', 'npmCommand flatOption set')
-
- const ll = Npm.cmd('ll')
- t.same(outputs, [ll.describeUsage], 'print usage')
- npm.config.set('usage', false)
-
- outputs.length = 0
- logs.length = 0
- await npm.exec('get', ['scope', 'usage'])
-
- t.strictSame([npm.command, npm.flatOptions.npmCommand], ['ll', 'll'],
- 'does not change npm.command when another command is called')
-
- t.match(logs, [
- /timing config:load:flatten Completed in [0-9.]+ms/,
- /timing command:config Completed in [0-9.]+ms/,
- ])
- t.same(outputs, ['scope=@foo\nusage=false'])
- })
-
await t.test('--no-workspaces with --workspace', async t => {
const { npm } = await loadMockNpm(t, {
prefixDir: {
diff --git a/deps/npm/test/lib/utils/allow-scripts-prune.js b/deps/npm/test/lib/utils/allow-scripts-prune.js
index 880b1dfe343..ea39bc6ecff 100644
--- a/deps/npm/test/lib/utils/allow-scripts-prune.js
+++ b/deps/npm/test/lib/utils/allow-scripts-prune.js
@@ -1,4 +1,5 @@
const t = require('tap')
+const path = require('node:path')
const { classifyUnusedEntries } = require('../../../lib/utils/allow-scripts-prune.js')
// Minimal registry node: `matches` derives name/version from the resolved URL.
@@ -29,6 +30,26 @@ t.test('keeps entries that match an installed package with scripts', t => {
t.end()
})
+t.test('keeps a local file key matching its absolute resolved source', t => {
+ const rootPath = path.resolve('project')
+ const key = `file:${path.resolve(rootPath, 'local.tgz')}`
+ const local = {
+ name: 'local',
+ version: '1.0.0',
+ resolved: key,
+ root: { path: rootPath },
+ isRegistryDependency: false,
+ }
+ const { remaining, removed } = classifyUnusedEntries(
+ { [key]: true },
+ [{ node: local, hasScripts: true }]
+ )
+
+ t.same(remaining, { [key]: true })
+ t.same(removed, [])
+ t.end()
+})
+
t.test('removes entries for packages no longer installed', t => {
const { remaining, removed } = classifyUnusedEntries(
{ canvas: true, gone: true },
diff --git a/deps/npm/test/lib/utils/allow-scripts-writer.js b/deps/npm/test/lib/utils/allow-scripts-writer.js
index 8edf25be307..f13389c8c25 100644
--- a/deps/npm/test/lib/utils/allow-scripts-writer.js
+++ b/deps/npm/test/lib/utils/allow-scripts-writer.js
@@ -1,8 +1,10 @@
const t = require('tap')
const path = require('node:path')
+const isScriptAllowed = require('../../../workspaces/arborist/lib/script-allowed.js')
const {
applyApprovalForPackage,
applyDenyForPackage,
+ keyTargetsNode,
nameKeyFor,
versionedKeyFor,
isSingleVersionPin,
@@ -379,6 +381,21 @@ t.test('applyApprovalForPackage — file dep uses resolved as both keys', async
t.strictSame(allowScripts, { 'file:../local': true })
})
+t.test('versionedKeyFor — local file key round-trips through policy matching', async t => {
+ const rootPath = path.resolve('project')
+ const local = {
+ name: 'local',
+ packageName: 'local',
+ version: '1.0.0',
+ resolved: `file:${path.resolve(rootPath, 'local.tgz')}`,
+ root: { path: rootPath },
+ isRegistryDependency: false,
+ }
+ const key = versionedKeyFor(local)
+
+ t.equal(isScriptAllowed(local, { [key]: true }), true)
+})
+
t.test('applyApprovalForPackage — empty nodes returns unchanged', async t => {
const { allowScripts, changes } = applyApprovalForPackage({ x: true }, [], { pin: true })
t.strictSame(allowScripts, { x: true })
@@ -493,6 +510,29 @@ t.test('applyApprovalForPackage — file dep with deny entry blocks approval', a
t.match(warning, /denied|versioned deny/)
})
+t.test('applyApprovalForPackage — relative file deny matches absolute resolved', async t => {
+ const rootPath = path.resolve('project')
+ const resolved = `file:${path.resolve(rootPath, 'local.tgz')}`
+ const local = {
+ name: 'local',
+ packageName: 'local',
+ version: '1.0.0',
+ resolved,
+ root: { path: rootPath },
+ isRegistryDependency: false,
+ }
+ const existing = { 'file:local.tgz': false }
+ const { allowScripts, changes, warning } = applyApprovalForPackage(
+ existing,
+ [local],
+ { pin: true }
+ )
+
+ t.strictSame(allowScripts, existing)
+ t.strictSame(changes, [])
+ t.match(warning, /denied|versioned deny/)
+})
+
t.test('applyApprovalForPackage — remote tarball deny blocks approval', async t => {
const remote = { name: 'pkg', packageName: 'pkg', version: '1.0.0', resolved: 'https://example.com/pkg.tgz' }
const { warning } = applyApprovalForPackage(
@@ -501,6 +541,7 @@ t.test('applyApprovalForPackage — remote tarball deny blocks approval', async
{ pin: true }
)
t.match(warning, /denied|versioned deny/)
+ t.equal(keyTargetsNode('https://example.com/other.tgz', remote), false)
})
t.test('applyApprovalForPackage — no-pin with no name produces no-op', async t => {
diff --git a/deps/npm/test/lib/utils/cli-only-flag.js b/deps/npm/test/lib/utils/cli-only-flag.js
new file mode 100644
index 00000000000..a30d97bc450
--- /dev/null
+++ b/deps/npm/test/lib/utils/cli-only-flag.js
@@ -0,0 +1,33 @@
+const t = require('tap')
+const cliOnlyFlag = require('../../../lib/utils/cli-only-flag.js')
+const { patchRelaxOpts } = require('../../../lib/utils/cli-only-flag.js')
+
+// minimal config stub: `where` is the layer find() would resolve the key from
+const mockConfig = (where, value) => ({
+ find: () => where,
+ get: () => value,
+})
+
+t.test('returns the value when set on the cli layer', t => {
+ t.equal(cliOnlyFlag(mockConfig('cli', true), 'x'), true)
+ t.end()
+})
+
+t.test('returns undefined when resolved from any non-cli layer', t => {
+ for (const where of ['env', 'project', 'user', 'global', 'default']) {
+ t.equal(cliOnlyFlag(mockConfig(where, true), 'x'), undefined, `${where} is ignored`)
+ }
+ t.end()
+})
+
+t.test('patchRelaxOpts maps the cli-only patch flags to arborist options', t => {
+ const config = {
+ find: key => (key === 'allow-unused-patches' ? 'cli' : 'project'),
+ get: () => true,
+ }
+ t.strictSame(patchRelaxOpts(config), {
+ allowUnusedPatches: true,
+ ignorePatchFailures: undefined,
+ })
+ t.end()
+})
diff --git a/deps/npm/test/lib/utils/explain-dep.js b/deps/npm/test/lib/utils/explain-dep.js
index 2a9a93f2b52..30f7167e706 100644
--- a/deps/npm/test/lib/utils/explain-dep.js
+++ b/deps/npm/test/lib/utils/explain-dep.js
@@ -140,6 +140,40 @@ const getCases = (testdir) => {
},
}],
},
+
+ packageExtensions: {
+ name: 'bar',
+ version: '1.2.3',
+ location: 'node_modules/bar',
+ dependents: [{
+ type: 'prod',
+ name: 'bar',
+ spec: '^1.0.0',
+ packageExtensions: { selector: 'foo@1', field: 'dependencies' },
+ from: {
+ name: 'foo',
+ version: '1.0.0',
+ location: 'node_modules/foo',
+ },
+ }],
+ },
+
+ npmExtension: {
+ name: 'bar',
+ version: '1.2.3',
+ location: 'node_modules/bar',
+ dependents: [{
+ type: 'prod',
+ name: 'bar',
+ spec: '^1.0.0',
+ npmExtension: { extensionPoint: 'transformManifest', field: 'dependencies' },
+ from: {
+ name: 'foo',
+ version: '1.0.0',
+ location: 'node_modules/foo',
+ },
+ }],
+ },
}
cases.manyDeps = {
diff --git a/deps/npm/test/lib/utils/key-values.js b/deps/npm/test/lib/utils/key-values.js
index 5e61f9e55fe..f162346eab4 100644
--- a/deps/npm/test/lib/utils/key-values.js
+++ b/deps/npm/test/lib/utils/key-values.js
@@ -76,6 +76,40 @@ t.test('logStageItem without actorType shows actor alone', async t => {
t.notMatch(out, /\(/)
})
+t.test('logStageItem shows status returned by the server', async t => {
+ const { joinedOutput } = await loadMockNpm(t)
+ const chalk = { cyan: v => v, green: v => v }
+ const item = {
+ id: 'abc',
+ packageName: 'pkg',
+ version: '1.0.0',
+ tag: 'latest',
+ createdAt: '2026-01-01',
+ actor: 'user',
+ shasum: 'sha1',
+ }
+
+ logStageItem({ ...item, status: 'awaiting_approval' }, { chalk })
+ t.match(joinedOutput(), /status: awaiting_approval/)
+})
+
+t.test('logStageItem omits missing status', async t => {
+ const { joinedOutput } = await loadMockNpm(t)
+ const chalk = { cyan: v => v, green: v => v }
+ const item = {
+ id: 'abc',
+ packageName: 'pkg',
+ version: '1.0.0',
+ tag: 'latest',
+ createdAt: '2026-01-01',
+ actor: 'user',
+ shasum: 'sha1',
+ }
+
+ logStageItem(item, { chalk })
+ t.notMatch(joinedOutput(), /status:/)
+})
+
t.test('logObject with all values skipped produces no output', async t => {
const { joinedOutput } = await loadMockNpm(t)
const chalk = { cyan: v => v, green: v => v }
diff --git a/deps/npm/test/lib/utils/patch-diff.js b/deps/npm/test/lib/utils/patch-diff.js
new file mode 100644
index 00000000000..dd571651be8
--- /dev/null
+++ b/deps/npm/test/lib/utils/patch-diff.js
@@ -0,0 +1,149 @@
+const t = require('tap')
+const { resolve } = require('node:path')
+const { readFileSync, existsSync, symlinkSync } = require('node:fs')
+const { diffDirs } = require('../../../lib/utils/patch-diff.js')
+const { applyPatchToDir } = require('@npmcli/arborist/lib/patch.js')
+
+// Helper to read a file from a dir as utf8.
+const read = (...p) => readFileSync(resolve(...p), 'utf8')
+
+t.test('modified file produces a unified diff', async t => {
+ const dir = t.testdir({
+ orig: { 'index.js': 'hello\n' },
+ edit: { 'index.js': 'world\n' },
+ })
+ const { diff } = await diffDirs(resolve(dir, 'orig'), resolve(dir, 'edit'))
+ t.match(diff, '--- a/index.js', 'has old header')
+ t.match(diff, '+++ b/index.js', 'has new header')
+ t.match(diff, '-hello', 'removes old line')
+ t.match(diff, '+world', 'adds new line')
+ t.notMatch(diff, '====', 'index separator is stripped')
+})
+
+t.test('added file uses --- /dev/null', async t => {
+ const dir = t.testdir({
+ orig: { 'keep.js': 'same\n' },
+ edit: { 'keep.js': 'same\n', 'added.js': 'brand new\n' },
+ })
+ const { diff } = await diffDirs(resolve(dir, 'orig'), resolve(dir, 'edit'))
+ t.match(diff, '--- /dev/null', 'old side is /dev/null')
+ t.match(diff, '+++ b/added.js', 'new side names the added file')
+ t.match(diff, '+brand new', 'includes added content')
+ t.notMatch(diff, 'keep.js', 'identical file is not in the diff')
+})
+
+t.test('deleted file uses +++ /dev/null', async t => {
+ const dir = t.testdir({
+ orig: { 'gone.js': 'remove me\n' },
+ edit: {},
+ })
+ const { diff } = await diffDirs(resolve(dir, 'orig'), resolve(dir, 'edit'))
+ t.match(diff, '--- a/gone.js', 'old side names the deleted file')
+ t.match(diff, '+++ /dev/null', 'new side is /dev/null')
+ t.match(diff, '-remove me', 'includes removed content')
+})
+
+t.test('nested file path is posix-separated in the diff', async t => {
+ const dir = t.testdir({
+ orig: { lib: { deep: { 'x.js': 'a\n' } } },
+ edit: { lib: { deep: { 'x.js': 'b\n' } } },
+ })
+ const { diff } = await diffDirs(resolve(dir, 'orig'), resolve(dir, 'edit'))
+ t.match(diff, '--- a/lib/deep/x.js', 'old header uses posix separators')
+ t.match(diff, '+++ b/lib/deep/x.js', 'new header uses posix separators')
+})
+
+t.test('identical files produce no diff', async t => {
+ const dir = t.testdir({
+ orig: { 'a.js': 'x\n', sub: { 'b.js': 'y\n' } },
+ edit: { 'a.js': 'x\n', sub: { 'b.js': 'y\n' } },
+ })
+ const { diff } = await diffDirs(resolve(dir, 'orig'), resolve(dir, 'edit'))
+ t.equal(diff, '', 'empty diff for identical trees')
+})
+
+t.test('node_modules and .git are ignored', async t => {
+ const dir = t.testdir({
+ orig: {
+ 'index.js': 'v1\n',
+ node_modules: { dep: { 'index.js': 'old\n' } },
+ '.git': { HEAD: 'ref: refs/heads/main\n' },
+ },
+ edit: {
+ 'index.js': 'v2\n',
+ node_modules: { dep: { 'index.js': 'changed\n' } },
+ '.git': { HEAD: 'ref: refs/heads/other\n' },
+ },
+ })
+ const { diff } = await diffDirs(resolve(dir, 'orig'), resolve(dir, 'edit'))
+ t.match(diff, 'index.js', 'top-level change is captured')
+ t.notMatch(diff, 'node_modules', 'node_modules contents are excluded')
+ t.notMatch(diff, 'HEAD', '.git contents are excluded')
+})
+
+t.test('root package.json is excluded and flagged, nested is kept', async t => {
+ const dir = t.testdir({
+ orig: {
+ 'package.json': '{ "version": "1.0.0" }\n',
+ 'index.js': 'a\n',
+ sub: { 'package.json': '{ "private": true }\n' },
+ },
+ edit: {
+ 'package.json': '{ "version": "2.0.0" }\n',
+ 'index.js': 'b\n',
+ sub: { 'package.json': '{ "private": false }\n' },
+ },
+ })
+ const { diff, packageJsonChanged } = await diffDirs(resolve(dir, 'orig'), resolve(dir, 'edit'))
+ t.equal(packageJsonChanged, true, 'root package.json change is flagged')
+ t.notMatch(diff, 'a/package.json\t', 'root package.json is not in the diff')
+ t.match(diff, 'a/sub/package.json', 'nested package.json is still diffed')
+ t.match(diff, 'a/index.js', 'other files are still diffed')
+})
+
+t.test('packageJsonChanged is false when only other files change', async t => {
+ const dir = t.testdir({
+ orig: { 'package.json': '{ "version": "1.0.0" }\n', 'index.js': 'a\n' },
+ edit: { 'package.json': '{ "version": "1.0.0" }\n', 'index.js': 'b\n' },
+ })
+ const { diff, packageJsonChanged } = await diffDirs(resolve(dir, 'orig'), resolve(dir, 'edit'))
+ t.equal(packageJsonChanged, false, 'unchanged package.json is not flagged')
+ t.match(diff, 'a/index.js', 'the real change is captured')
+})
+
+t.test('non-file entries like symlinks are skipped', async t => {
+ const dir = t.testdir({
+ orig: { 'real.js': 'a\n' },
+ edit: { 'real.js': 'b\n' },
+ })
+ // A symlink is neither a directory nor a regular file so it is ignored.
+ symlinkSync(resolve(dir, 'orig', 'real.js'), resolve(dir, 'edit', 'link.js'))
+ const { diff } = await diffDirs(resolve(dir, 'orig'), resolve(dir, 'edit'))
+ t.match(diff, 'real.js', 'regular file is diffed')
+ t.notMatch(diff, 'link.js', 'symlink entry is skipped')
+})
+
+t.test('round-trip: applying the diff reproduces the edited tree', async t => {
+ const dir = t.testdir({
+ orig: {
+ 'mod.js': 'original line\n',
+ 'del.js': 'doomed\n',
+ lib: { deep: { 'x.js': 'before\n' } },
+ },
+ edit: {
+ 'mod.js': 'patched line\n',
+ 'add.js': 'fresh content\n',
+ lib: { deep: { 'x.js': 'after\n' } },
+ },
+ })
+ const orig = resolve(dir, 'orig')
+ const { diff } = await diffDirs(orig, resolve(dir, 'edit'))
+
+ // Apply the diff back onto a copy of the original and check the result.
+ await applyPatchToDir({ patch: diff, cwd: orig })
+
+ t.equal(read(orig, 'mod.js'), 'patched line\n', 'modified file matches edit')
+ t.equal(read(orig, 'add.js'), 'fresh content\n', 'added file was created')
+ t.equal(read(orig, 'lib', 'deep', 'x.js'), 'after\n', 'nested file matches edit')
+ t.notOk(existsSync(resolve(orig, 'del.js')), 'deleted file was removed')
+})
diff --git a/deps/npm/test/lib/utils/reify-output.js b/deps/npm/test/lib/utils/reify-output.js
index ee9201482a7..48f2d03ed29 100644
--- a/deps/npm/test/lib/utils/reify-output.js
+++ b/deps/npm/test/lib/utils/reify-output.js
@@ -128,6 +128,35 @@ t.test('no message when funding config is false', async t => {
t.notMatch(out, 'looking for funding', 'should not print funding info')
})
+t.test('no message when installing globally', async t => {
+ const out = await mockReify(t, {
+ actualTree: {
+ name: 'foo',
+ package: {
+ name: 'foo',
+ version: '1.0.0',
+ },
+ edgesOut: new Map([
+ ['bar', {
+ to: {
+ name: 'bar',
+ package: {
+ name: 'bar',
+ version: '1.0.0',
+ funding: { type: 'foo', url: 'http://example.com' },
+ },
+ },
+ }],
+ ]),
+ },
+ diff: {
+ children: [],
+ },
+ }, { global: true })
+
+ t.notMatch(out, 'looking for funding', 'should not print funding info')
+})
+
t.test('print appropriate message for many packages', async t => {
const out = await mockReify(t, {
actualTree: {
@@ -440,6 +469,53 @@ t.test('prints dedupe difference on dry-run', async t => {
t.matchSnapshot(out, 'diff table')
})
+t.test('prints only json for dry-run and long', async t => {
+ for (const flag of ['dry-run', 'long']) {
+ await t.test(flag, async t => {
+ const out = await mockReify(t, {
+ actualTree: {
+ inventory: {
+ has: () => true,
+ },
+ children: [],
+ },
+ diff: {
+ children: [
+ {
+ action: 'ADD',
+ ideal: {
+ path: 'test/foo',
+ name: 'foo',
+ package: { version: '1.0.0' },
+ },
+ },
+ ],
+ },
+ }, {
+ [flag]: true,
+ json: true,
+ })
+
+ t.strictSame(JSON.parse(out), {
+ add: [
+ {
+ name: 'foo',
+ version: '1.0.0',
+ path: 'test/foo',
+ },
+ ],
+ added: 1,
+ audited: 0,
+ change: [],
+ changed: 0,
+ funding: 0,
+ remove: [],
+ removed: 0,
+ })
+ })
+ }
+})
+
t.test('prints dedupe difference on long', async t => {
const mock = {
actualTree: {
@@ -500,7 +576,7 @@ t.test('prints unreviewed install scripts summary', async t => {
const mock = await mockReifyWithExtras(t, baseReify, { unreviewedScripts })
const warn = mock.logs.warn.byTitle('install-scripts').join('\n')
- t.match(warn, /2 packages have install scripts not yet covered/)
+ t.match(warn, /2 packages had install scripts blocked because they are not covered by allowScripts/)
t.match(warn, /canvas@2\.11\.0 \(install: node-gyp rebuild\)/)
t.match(warn, /sharp@0\.33\.2 \(preinstall: pre; postinstall: post\)/)
t.match(warn, /npm install-scripts ls/)
@@ -532,7 +608,7 @@ t.test('global install suggests --allow-scripts, not approve-scripts', async t =
const mock = await mockReifyWithExtras(t, baseReify, { unreviewedScripts }, { global: true })
const warn = mock.logs.warn.byTitle('install-scripts').join('\n')
- t.match(warn, /2 packages have install scripts not yet covered/)
+ t.match(warn, /2 packages had install scripts blocked because they are not covered by allowScripts/)
t.match(warn, /canvas@2\.11\.0 \(install: node-gyp rebuild\)/)
t.match(warn, /npm install -g --allow-scripts=canvas,sharp/)
t.match(warn, /npm config set allow-scripts=canvas,sharp/)
@@ -557,7 +633,31 @@ t.test('single unreviewed script uses singular wording', async t => {
}],
}
)
- t.match(mock.logs.warn.byTitle('install-scripts').join('\n'), /1 package has install scripts/)
+ t.match(mock.logs.warn.byTitle('install-scripts').join('\n'), /1 package had install scripts blocked/)
+})
+
+t.test('optional dep with blocked scripts appears in the summary', async t => {
+ const mock = await mockNpm(t, {})
+ reifyOutput(mock.npm, {
+ actualTree: { inventory: { has: () => false } },
+ diff: { children: [] },
+ }, {
+ unreviewedScripts: [{
+ node: {
+ packageName: 'opt',
+ name: 'opt',
+ version: '1.0.0',
+ path: '/x/opt',
+ optional: true,
+ devOptional: true,
+ },
+ scripts: { install: 'cmd' },
+ }],
+ })
+ mock.npm.finish()
+ const warn = mock.logs.warn.byTitle('install-scripts').join('\n')
+ t.match(warn, /1 package had install scripts blocked/)
+ t.match(warn, /opt@1\.0\.0 \(install: cmd\)/)
})
t.test('json output includes unreviewedScripts', async t => {
diff --git a/deps/npm/test/lib/utils/resolve-allow-scripts.js b/deps/npm/test/lib/utils/resolve-allow-scripts.js
index a27d600d98f..650094ba170 100644
--- a/deps/npm/test/lib/utils/resolve-allow-scripts.js
+++ b/deps/npm/test/lib/utils/resolve-allow-scripts.js
@@ -86,6 +86,22 @@ t.test('--allow-scripts CLI flag is rejected in project-scoped installs', async
)
})
+t.test('allow-scripts environment policy is rejected in project-scoped installs', async t => {
+ const mock = await mockNpm(t, {
+ prefixDir: {
+ 'package.json': JSON.stringify({ name: 'p' }),
+ },
+ globals: {
+ 'process.env.npm_config_allow_scripts': 'canvas',
+ },
+ })
+ const resolveAllowScripts = loadResolver(t)
+ await t.rejects(
+ resolveAllowScripts(mock.npm),
+ { code: 'EALLOWSCRIPTS', message: /--allow-scripts is not allowed/ }
+ )
+})
+
t.test('--allow-scripts CLI flag is accepted in global installs (RFC layer 1 wins)', async t => {
const mock = await mockNpm(t, {
prefixDir: {
diff --git a/deps/npm/test/lib/utils/sbom-cyclonedx.js b/deps/npm/test/lib/utils/sbom-cyclonedx.js
index f3105e3cd48..b9d947be054 100644
--- a/deps/npm/test/lib/utils/sbom-cyclonedx.js
+++ b/deps/npm/test/lib/utils/sbom-cyclonedx.js
@@ -83,6 +83,19 @@ t.test('single node - package lock only', t => {
t.end()
})
+t.test('single node - uses package name for root component name', t => {
+ const node = {
+ ...root,
+ name: '',
+ packageName: '@scope/root-package',
+ pkgid: '@scope/root-package@1.0.0',
+ }
+ const res = cyclonedxOutput({ npm, nodes: [node] })
+ t.equal(res.metadata.component.name, '@scope/root-package')
+ t.equal(res.metadata.component['bom-ref'], '@scope/root-package@1.0.0')
+ t.end()
+})
+
t.test('single node - optional ', t => {
const node = { ...root, optional: true }
const res = cyclonedxOutput({ npm, nodes: [node] })
diff --git a/deps/npm/test/lib/utils/tar.js b/deps/npm/test/lib/utils/tar.js
index 3eff023ccec..85a95e57766 100644
--- a/deps/npm/test/lib/utils/tar.js
+++ b/deps/npm/test/lib/utils/tar.js
@@ -109,20 +109,6 @@ t.test('should log tarball contents with unicode', async (t) => {
t.end()
})
-t.test('logTar with json and no key emits bare tarball object', async (t) => {
- const buffered = []
- const logTar = tmock(t, '{LIB}/utils/tar.js', {
- 'proc-log': {
- log: { notice: () => {} },
- output: { buffer: (data) => buffered.push(data) },
- },
- }).logTar
-
- const tarball = { name: 'my-pkg', version: '1.0.0' }
- logTar(tarball, { json: true })
- t.strictSame(buffered, [tarball], 'buffers the bare tarball when key is omitted')
-})
-
t.test('should getContents of a tarball with only a package.json', async (t) => {
const testDir = t.testdir({
'package.json': JSON.stringify({
diff --git a/deps/npm/test/lib/utils/validate-lockfile.js b/deps/npm/test/lib/utils/validate-lockfile.js
index 25939c5f89c..cee1891f491 100644
--- a/deps/npm/test/lib/utils/validate-lockfile.js
+++ b/deps/npm/test/lib/utils/validate-lockfile.js
@@ -1,5 +1,102 @@
const t = require('tap')
const validateLockfile = require('../../../lib/utils/validate-lockfile.js')
+const { validatePackageExtensions } = require('../../../lib/utils/validate-lockfile.js')
+
+// build mock virtual/ideal trees for validatePackageExtensions
+const tree = ({ hash = null, packageExtensions, nodes = [] }) => ({
+ meta: { packageExtensionsHash: hash },
+ target: { package: packageExtensions === undefined ? {} : { packageExtensions } },
+ inventory: { values: () => nodes },
+})
+
+t.test('packageExtensions: matching hashes and clean tree', async t => {
+ const errors = validatePackageExtensions(
+ tree({ hash: 'sha512-abc' }),
+ tree({ hash: 'sha512-abc' })
+ )
+ t.strictSame(errors, [], 'no errors when hashes match and no provenance')
+})
+
+t.test('packageExtensions: both absent', async t => {
+ t.strictSame(validatePackageExtensions(tree({}), tree({})), [], 'no errors when neither has state')
+})
+
+t.test('packageExtensions: missing from lock file', async t => {
+ const errors = validatePackageExtensions(tree({ hash: null }), tree({ hash: 'sha512-abc' }))
+ t.match(errors[0], /Missing: packageExtensions state from lock file/, 'reports missing lock state')
+})
+
+t.test('packageExtensions: present in lock but not package.json', async t => {
+ const errors = validatePackageExtensions(tree({ hash: 'sha512-abc' }), tree({ hash: null }))
+ t.match(errors[0], /lock file records packageExtensions state but package.json has none/, 'reports stray lock state')
+})
+
+t.test('packageExtensions: hash mismatch', async t => {
+ const errors = validatePackageExtensions(tree({ hash: 'sha512-aaa' }), tree({ hash: 'sha512-bbb' }))
+ t.match(errors[0], /do not match the lock file/, 'reports a mismatch')
+})
+
+t.test('packageExtensions: stale provenance with matching hash', async t => {
+ // both hashes equal, but a locked node references a selector that no longer exists
+ const node = { name: 'foo', version: '1.0.0', packageExtensionsApplied: { selector: 'foo@1', dependencies: ['bar'] } }
+ const errors = validatePackageExtensions(
+ tree({ hash: 'h', nodes: [node] }),
+ tree({ hash: 'h', packageExtensions: {} })
+ )
+ t.match(errors[0], /stale packageExtensions provenance for foo@1.0.0/, 'reports stale provenance')
+})
+
+t.test('packageExtensions: valid provenance with matching hash', async t => {
+ const node = { name: 'foo', version: '1.0.0', packageExtensionsApplied: { selector: 'foo@1', dependencies: ['bar'] } }
+ // root and workspace nodes are skipped by the validation
+ const root = { name: 'root', version: '1.0.0', isProjectRoot: true }
+ const errors = validatePackageExtensions(
+ tree({ hash: 'h', nodes: [root, node] }),
+ tree({ hash: 'h', packageExtensions: { 'foo@1': { dependencies: { bar: '^1' } } } })
+ )
+ t.strictSame(errors, [], 'no errors when provenance still matches a selector')
+})
+
+t.test('packageExtensions: ideal tree without a target uses the tree itself', async t => {
+ const idealTree = {
+ meta: { packageExtensionsHash: 'h' },
+ package: { packageExtensions: { 'foo@1': { dependencies: { bar: '^1' } } } },
+ inventory: { values: () => [] },
+ }
+ t.strictSame(validatePackageExtensions(tree({ hash: 'h' }), idealTree), [], 'reads package off the tree directly')
+})
+
+t.test('packageExtensions: invalid rule set surfaces the engine error', async t => {
+ const errors = validatePackageExtensions(
+ tree({ hash: 'h' }),
+ tree({ hash: 'h', packageExtensions: { foo: { devDependencies: { a: '1' } } } })
+ )
+ t.match(errors[0], /Invalid: .*unsupported field/, 'reports the engine validation error')
+})
+
+t.test('packageExtensions: alias node matches the underlying package name', async t => {
+ // an aliased install: node.name is the alias, node.packageName is the real package
+ const node = {
+ name: 'my-alias',
+ packageName: 'real-pkg',
+ version: '1.0.0',
+ packageExtensionsApplied: { selector: 'real-pkg@1', dependencies: ['bar'] },
+ }
+ const errors = validatePackageExtensions(
+ tree({ hash: 'h', nodes: [node] }),
+ tree({ hash: 'h', packageExtensions: { 'real-pkg@1': { dependencies: { bar: '^1' } } } })
+ )
+ t.strictSame(errors, [], 'provenance validated against the underlying package name, not the alias')
+})
+
+t.test('packageExtensions: locked identity matching two selectors', async t => {
+ const node = { name: 'foo', version: '1.0.0' }
+ const errors = validatePackageExtensions(
+ tree({ hash: 'h', nodes: [node] }),
+ tree({ hash: 'h', packageExtensions: { foo: { dependencies: { a: '^1' } }, 'foo@1': { dependencies: { b: '^1' } } } })
+ )
+ t.match(errors[0], /Multiple packageExtensions selectors match foo@1.0.0/, 'reports a selector conflict')
+})
t.test('identical inventory for both idealTree and virtualTree', async t => {
t.matchSnapshot(
@@ -67,6 +164,38 @@ t.test('mismatching versions on inventory', async t => {
)
})
+t.test('mismatching patch integrity or path', async t => {
+ t.matchSnapshot(
+ validateLockfile(
+ new Map([
+ ['foo', { name: 'foo', version: '1.0.0', patched: { path: 'patches/foo.patch', integrity: 'sha512-aaa' } }],
+ ['bar', { name: 'bar', version: '2.0.0', patched: { path: 'patches/bar.patch', integrity: 'sha512-bbb' } }],
+ ['baz', { name: 'baz', version: '3.0.0' }],
+ ]),
+ new Map([
+ ['foo', { name: 'foo', version: '1.0.0', patched: { path: 'patches/foo.patch', integrity: 'sha512-CHANGED' } }],
+ ['bar', { name: 'bar', version: '2.0.0', patched: { path: 'patches/moved.patch', integrity: 'sha512-bbb' } }],
+ ['baz', { name: 'baz', version: '3.0.0', patched: { path: 'patches/baz.patch', integrity: 'sha512-ccc' } }],
+ ])
+ ),
+ 'should error on integrity drift, path drift, and a newly added patch'
+ )
+})
+
+t.test('lock file records a patch package.json no longer declares', async t => {
+ t.matchSnapshot(
+ validateLockfile(
+ new Map([
+ ['foo', { name: 'foo', version: '1.0.0', patched: { path: 'patches/foo.patch', integrity: 'sha512-aaa' } }],
+ ]),
+ new Map([
+ ['foo', { name: 'foo', version: '1.0.0' }],
+ ])
+ ),
+ 'should report a stray lock file patch'
+ )
+})
+
t.test('missing virtualTree inventory', async t => {
t.matchSnapshot(
validateLockfile(
@@ -80,3 +209,41 @@ t.test('missing virtualTree inventory', async t => {
'should have errors for each mismatching version'
)
})
+
+const { validateNpmExtension } = require('../../../lib/utils/validate-lockfile.js')
+
+// build a mock virtual tree with a root hash and optional provenance-bearing nodes
+const extVirtual = (hash, nodes = []) => ({
+ meta: { npmExtensionHash: hash },
+ inventory: { values: () => nodes },
+})
+
+t.test('npmExtension: matching hashes', async t => {
+ t.strictSame(validateNpmExtension(extVirtual('h'), 'h'), [], 'no errors when hashes match')
+})
+
+t.test('npmExtension: both absent', async t => {
+ t.strictSame(validateNpmExtension(extVirtual(null), null), [], 'no errors when both absent')
+})
+
+t.test('npmExtension: missing from lock file', async t => {
+ const errors = validateNpmExtension(extVirtual(null), 'h')
+ t.match(errors[0], /Missing: \.npm-extension state from lock file/, 'reports missing lock state')
+})
+
+t.test('npmExtension: present in lock but no file', async t => {
+ const errors = validateNpmExtension(extVirtual('h'), null)
+ t.match(errors[0], /records \.npm-extension state but no \.npm-extension file is present/, 'reports stray lock state')
+})
+
+t.test('npmExtension: hash mismatch', async t => {
+ const errors = validateNpmExtension(extVirtual('h1'), 'h2')
+ t.match(errors[0], /\.npm-extension file does not match the lock file/, 'reports a hash mismatch')
+})
+
+t.test('npmExtension: provenance without a root hash and no file fails', async t => {
+ const nodes = [{ name: 'foo', npmExtensionApplied: { extensionPoint: 'transformManifest', dependencies: ['bar'] } }]
+ const errors = validateNpmExtension(extVirtual(null, nodes), null)
+ t.match(errors[0], /records \.npm-extension state but no \.npm-extension file is present/,
+ 'per-node provenance counts as extension state even without a root hash')
+})