diff options
author | Darcy Clarke <darcy@darcyclarke.me> | 2020-11-13 15:30:43 -0500 |
---|---|---|
committer | Rich Trott <rtrott@gmail.com> | 2020-11-16 06:27:36 -0800 |
commit | b89d4090e7d3a87c4b8e1114541cfd925c68ca04 (patch) | |
tree | b34a9425bf873890f04ad00247c89d8d76c06ffa | |
parent | dc79f3f37caf6f25b8efee4623bec31e2c20f595 (diff) | |
download | node-new-b89d4090e7d3a87c4b8e1114541cfd925c68ca04.tar.gz |
deps: upgrade npm to 7.0.11
PR-URL: https://github.com/nodejs/node/pull/36112
Reviewed-By: Myles Borins <myles.borins@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
55 files changed, 993 insertions, 320 deletions
diff --git a/deps/npm/AUTHORS b/deps/npm/AUTHORS index 4209517f2a..c0986e8be2 100644 --- a/deps/npm/AUTHORS +++ b/deps/npm/AUTHORS @@ -730,3 +730,6 @@ Michele Azzolari <michele@azzolari.it> foxxyz <foxxyz@gmail.com> Dr <dr@dr.run> Jan Tojnar <jtojnar@gmail.com> +Jason Attwood <jason_attwood@hotmail.co.uk> +Vlad GURDIGA <gurdiga@gmail.com> +Sébastien Puech <s.puech@tricentis.com> diff --git a/deps/npm/CHANGELOG.md b/deps/npm/CHANGELOG.md index 49d44ab10a..8cafde1158 100644 --- a/deps/npm/CHANGELOG.md +++ b/deps/npm/CHANGELOG.md @@ -1,3 +1,115 @@ +## 7.0.11 (2020-11-13) + +### DEPENDENCIES + +* [`629a667a9`](https://github.com/npm/cli/commit/629a667a9b30b0b870075da965606979622a5e2e) + `eslint@7.13.0` +* [`de9891bd2`](https://github.com/npm/cli/commit/de9891bd2a16fe890ff5cfb140c7b1209aeac0de) + `eslint-plugin-standard@4.1.0` +* [`c3e7aa31c`](https://github.com/npm/cli/commit/c3e7aa31c565dfe21cd1f55a8433bfbcf58aa289) + [#2123](https://github.com/npm/cli/issues/2123) + [#1957](https://github.com/npm/cli/issues/1957) + `@npmcli/arborist@1.0.11` + +### BUG FIXES + +* [`a8aa38513`](https://github.com/npm/cli/commit/a8aa38513ad5c4ad44e6bb3e1499bfc40c31e213) + [#2134](https://github.com/npm/cli/issues/2134) + [#2156](https://github.com/npm/cli/issues/2156) + Fix `cannot read property length of undefined` in `ERESOLVE` explanation code + ([@isaacs](https://github.com/isaacs)) +* [`1dbf0f9bb`](https://github.com/npm/cli/commit/1dbf0f9bb26ba70f4c6d0a807701d7652c31d7d4) + [#2150](https://github.com/npm/cli/issues/2150) + [#2155](https://github.com/npm/cli/issues/2155) + send json errors to stderr, not stdout + ([@isaacs](https://github.com/isaacs)) +* [`fd1d7a21b`](https://github.com/npm/cli/commit/fd1d7a21b247bb35d112c51ff8d8a06fd83c8b44) + [#1927](https://github.com/npm/cli/issues/1927) + [#2154](https://github.com/npm/cli/issues/2154) + Set process.title a bit more usefully + ([@isaacs](https://github.com/isaacs)) +* [`2a80c67ef`](https://github.com/npm/cli/commit/2a80c67ef8c12c3d9d254f5be6293a6461067d99) + [#2008](https://github.com/npm/cli/issues/2008) + [#2153](https://github.com/npm/cli/issues/2153) + Support legacy auth tokens for registries that use them + ([@ruyadorno](https://github.com/ruyadorno)) +* [`786e36404`](https://github.com/npm/cli/commit/786e36404068fd51657ddac766e066a98754edbf) + [#2017](https://github.com/npm/cli/issues/2017) + [#2159](https://github.com/npm/cli/issues/2159) + pass all options to Arborist for `npm ci` + ([@darcyclarke](https://github.com/darcyclarke)) +* [`b47ada7d1`](https://github.com/npm/cli/commit/b47ada7d1623e9ee586ee0cf781ee3ac5ea3c223) + [#2161](https://github.com/npm/cli/issues/2161) + fixed typo + ([@scarabedore](https://github.com/scarabedore)) + +## 7.0.10 (2020-11-10) + +### DOCUMENTATION + +* [`e48badb03`](https://github.com/npm/cli/commit/e48badb03058286a557584d7319db4143049cc6b) + [#2148](https://github.com/npm/cli/issues/2148) + Fix link in documentation + ([@gurdiga](https://github.com/gurdiga)) + +### BUG FIXES + +* [`8edbbdc70`](https://github.com/npm/cli/commit/8edbbdc706694fa32f52d0991c76ae9f207b7bbc) + [#1972](https://github.com/npm/cli/issues/1972) + Support exec auto pick bin when all bin is alias + ([@dr-js](https://github.com/dr-js)) + +### DEPENDENCIES + +* [`04a3e8c10`](https://github.com/npm/cli/commit/04a3e8c10c3f38e1c7a35976d77c2929bdc39868) + [#1962](https://github.com/npm/cli/issues/1962) + `@npmcli/arborist@1.0.10`: + * prevent self-assignment of parent/fsParent + * Support update options in global package space + +## 7.0.9 (2020-11-06) + +### BUG FIXES + +* [`96a0d2802`](https://github.com/npm/cli/commit/96a0d2802d3e619c6ea47290f5c460edfe94070a) + default the 'start' script when server.js present + ([@isaacs](https://github.com/isaacs)) +* [`7716e423e`](https://github.com/npm/cli/commit/7716e423ee92a81730c0dfe5b9ecb4bb41a3f947) + [#2075](https://github.com/npm/cli/issues/2075) + [#2071](https://github.com/npm/cli/issues/2071) print the registry when + using 'npm login' ([@Wicked7000](https://github.com/Wicked7000)) +* [`7046fe10c`](https://github.com/npm/cli/commit/7046fe10c5035ac57246a31ca8a6b09e3f5562bf) + [#2122](https://github.com/npm/cli/issues/2122) tests for `npm cache` + command ([@nlf](https://github.com/nlf)) + +### DEPENDENCIES + +* [`74325f53b`](https://github.com/npm/cli/commit/74325f53b9d813b0e42203c037189418fad2f64a) + [#2124](https://github.com/npm/cli/issues/2124) + `@npmcli/run-script@1.7.5`: + * Export the `isServerPackage` method + * Proxy signals to and from foreground child processes +* [`0e58e6f6b`](https://github.com/npm/cli/commit/0e58e6f6b8f0cd62294642a502c17561aaf46553) + [#1984](https://github.com/npm/cli/issues/1984) + [#2079](https://github.com/npm/cli/issues/2079) + [#1923](https://github.com/npm/cli/issues/1923) + [#606](https://github.com/npm/cli/issues/606) + [#2031](https://github.com/npm/cli/issues/2031) `@npmcli/arborist@1.0.9`: + * Process deps for all link nodes + * Use junctions instead of symlinks + * Use @npmcli/move-file instead of fs.rename +* [`1dad328a1`](https://github.com/npm/cli/commit/1dad328a17d93def7799545596b4eba9833b35aa) + [#1865](https://github.com/npm/cli/issues/1865) + [#2106](https://github.com/npm/cli/issues/2106) + [#2084](https://github.com/npm/cli/issues/2084) `pacote@11.1.13`: + * Properly set the installation command for `prepare` scripts when + installing git/dir deps +* [`e090d706c`](https://github.com/npm/cli/commit/e090d706ca637d4df96d28bff1660590aa3f3b62) + [#2097](https://github.com/npm/cli/issues/2097) `libnpmversion@1.0.7`: + * Do not crash when the package.json file lacks a 'version' field +* [`8fa541a10`](https://github.com/npm/cli/commit/8fa541a10dbdc09376175db7a378cc9b33e8b17b) + `cmark-gfm@0.8.4` + ## 7.0.8 (2020-11-03) ### DOCUMENTATION diff --git a/deps/npm/docs/content/commands/npm-exec.md b/deps/npm/docs/content/commands/npm-exec.md index 38fb1bf25a..c9de9933be 100644 --- a/deps/npm/docs/content/commands/npm-exec.md +++ b/deps/npm/docs/content/commands/npm-exec.md @@ -54,7 +54,8 @@ the package specifier provided as the first positional argument according to the following heuristic: - If the package has a single entry in its `bin` field in `package.json`, - then that command will be used. + or if all entries are aliases of the same command, then that command + will be used. - If the package has multiple `bin` entries, and one of them matches the unscoped portion of the `name` field, then that command will be used. - If this does not result in exactly one option (either because there are diff --git a/deps/npm/docs/content/commands/npx.md b/deps/npm/docs/content/commands/npx.md index a5522c66e8..625ac3d8cd 100644 --- a/deps/npm/docs/content/commands/npx.md +++ b/deps/npm/docs/content/commands/npx.md @@ -8,9 +8,9 @@ description: Run a command from a local or remote npm package ```bash npm exec -- <pkg>[@<version>] [args...] -npm exec -p <pkg>[@<version>] -- <cmd> [args...] +npm exec --package=<pkg>[@<version>] -- <cmd> [args...] npm exec -c '<cmd> [args...]' -npm exec -p foo -c '<cmd> [args...]' +npm exec --package=foo -c '<cmd> [args...]' npx <pkg>[@<specifier>] [args...] npx -p <pkg>[@<specifier>] <cmd> [args...] @@ -19,7 +19,8 @@ npx -p <pkg>[@<specifier>] -c '<cmd> [args...]' alias: npm x, npx --p <pkg> --package=<pkg> (may be specified multiple times) +--package=<pkg> (may be specified multiple times) +-p is a shorthand for --package only when using npx executable -c <cmd> --call=<cmd> (may not be mixed with positional arguments) ``` @@ -29,9 +30,9 @@ This command allows you to run an arbitrary command from an npm package (either one installed locally, or fetched remotely), in a similar context as running it via `npm run`. -Whatever packages are specified by the `--package` or `-p` option will be +Whatever packages are specified by the `--package` option will be provided in the `PATH` of the executed command, along with any locally -installed package executables. The `--package` or `-p` option may be +installed package executables. The `--package` option may be specified multiple times, to execute the supplied command in an environment where all specified packages are available. @@ -47,13 +48,14 @@ only be considered a match if they have the exact same name and version as the local dependency. If no `-c` or `--call` option is provided, then the positional arguments -are used to generate the command string. If no `-p` or `--package` options +are used to generate the command string. If no `--package` options are provided, then npm will attempt to determine the executable name from the package specifier provided as the first positional argument according to the following heuristic: - If the package has a single entry in its `bin` field in `package.json`, - then that command will be used. + or if all entries are aliases of the same command, then that command + will be used. - If the package has multiple `bin` entries, and one of them matches the unscoped portion of the `name` field, then that command will be used. - If this does not result in exactly one option (either because there are diff --git a/deps/npm/docs/content/using-npm/developers.md b/deps/npm/docs/content/using-npm/developers.md index d42c759d42..7e47b76f65 100644 --- a/deps/npm/docs/content/using-npm/developers.md +++ b/deps/npm/docs/content/using-npm/developers.md @@ -109,7 +109,7 @@ create an empty `.npmignore` file to override it. Like `git`, `npm` looks for `.npmignore` and `.gitignore` files in all subdirectories of your package, not only the root directory. -`.npmignore` files follow the [same pattern rules](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository#Ignoring-Files) +`.npmignore` files follow the [same pattern rules](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository#_ignoring) as `.gitignore` files: * Blank lines or lines starting with `#` are ignored. diff --git a/deps/npm/docs/content/using-npm/scripts.md b/deps/npm/docs/content/using-npm/scripts.md index f86f9e88bc..c111aa3f3a 100644 --- a/deps/npm/docs/content/using-npm/scripts.md +++ b/deps/npm/docs/content/using-npm/scripts.md @@ -6,7 +6,7 @@ description: How npm handles the "scripts" field ### Description -The `"scripts"` property of of your `package.json` file supports a number of built-in scripts and their preset life cycle events as well as arbitrary scripts. These all can be executed by running `npm run-script <stage>` or `npm run <stage>` for short. *Pre* and *post* commands with matching names will be run for those as well (e.g. `premyscript`, `myscript`, `postmyscript`). Scripts from dependencies can be run with `npm explore <pkg> -- npm run <stage>`. +The `"scripts"` property of your `package.json` file supports a number of built-in scripts and their preset life cycle events as well as arbitrary scripts. These all can be executed by running `npm run-script <stage>` or `npm run <stage>` for short. *Pre* and *post* commands with matching names will be run for those as well (e.g. `premyscript`, `myscript`, `postmyscript`). Scripts from dependencies can be run with `npm explore <pkg> -- npm run <stage>`. ### Pre & Post Scripts diff --git a/deps/npm/docs/output/commands/npm-exec.html b/deps/npm/docs/output/commands/npm-exec.html index 6bd59f7a8e..6e50a1cb9a 100644 --- a/deps/npm/docs/output/commands/npm-exec.html +++ b/deps/npm/docs/output/commands/npm-exec.html @@ -186,7 +186,8 @@ the package specifier provided as the first positional argument according to the following heuristic:</p> <ul> <li>If the package has a single entry in its <code>bin</code> field in <code>package.json</code>, -then that command will be used.</li> +or if all entries are aliases of the same command, then that command +will be used.</li> <li>If the package has multiple <code>bin</code> entries, and one of them matches the unscoped portion of the <code>name</code> field, then that command will be used.</li> <li>If this does not result in exactly one option (either because there are diff --git a/deps/npm/docs/output/commands/npm-ls.html b/deps/npm/docs/output/commands/npm-ls.html index 55722b8f1c..437f062c29 100644 --- a/deps/npm/docs/output/commands/npm-ls.html +++ b/deps/npm/docs/output/commands/npm-ls.html @@ -156,7 +156,7 @@ installed, as well as their dependencies, in a tree-structure.</p> 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 lang="bash"><code> npm@7.0.8 /path/to/npm +<pre lang="bash"><code> npm@7.0.11 /path/to/npm └─┬ init-package-json@0.0.4 └── promzard@0.1.5 </code></pre> diff --git a/deps/npm/docs/output/commands/npm.html b/deps/npm/docs/output/commands/npm.html index e3f5ce28af..77cf24a8fb 100644 --- a/deps/npm/docs/output/commands/npm.html +++ b/deps/npm/docs/output/commands/npm.html @@ -148,7 +148,7 @@ npm command-line interface <pre lang="bash"><code>npm <command> [args] </code></pre> <h3 id="version">Version</h3> -<p>7.0.8</p> +<p>7.0.11</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 diff --git a/deps/npm/docs/output/commands/npx.html b/deps/npm/docs/output/commands/npx.html index 61194a0aa3..36aad9f701 100644 --- a/deps/npm/docs/output/commands/npx.html +++ b/deps/npm/docs/output/commands/npx.html @@ -146,9 +146,9 @@ npm command-line interface <div id="_content"><h3 id="synopsis">Synopsis</h3> <pre lang="bash"><code>npm exec -- <pkg>[@<version>] [args...] -npm exec -p <pkg>[@<version>] -- <cmd> [args...] +npm exec --package=<pkg>[@<version>] -- <cmd> [args...] npm exec -c '<cmd> [args...]' -npm exec -p foo -c '<cmd> [args...]' +npm exec --package=foo -c '<cmd> [args...]' npx <pkg>[@<specifier>] [args...] npx -p <pkg>[@<specifier>] <cmd> [args...] @@ -157,16 +157,17 @@ npx -p <pkg>[@<specifier>] -c '<cmd> [args...]' alias: npm x, npx --p <pkg> --package=<pkg> (may be specified multiple times) +--package=<pkg> (may be specified multiple times) +-p is a shorthand for --package only when using npx executable -c <cmd> --call=<cmd> (may not be mixed with positional arguments) </code></pre> <h3 id="description">Description</h3> <p>This command allows you to run an arbitrary command from an npm package (either one installed locally, or fetched remotely), in a similar context as running it via <code>npm run</code>.</p> -<p>Whatever packages are specified by the <code>--package</code> or <code>-p</code> option will be +<p>Whatever packages are specified by the <code>--package</code> option will be provided in the <code>PATH</code> of the executed command, along with any locally -installed package executables. The <code>--package</code> or <code>-p</code> option may be +installed package executables. The <code>--package</code> option may be specified multiple times, to execute the supplied command in an environment where all specified packages are available.</p> <p>If any requested packages are not present in the local project @@ -179,13 +180,14 @@ version exists in the local project. Package names with a specifier will only be considered a match if they have the exact same name and version as the local dependency.</p> <p>If no <code>-c</code> or <code>--call</code> option is provided, then the positional arguments -are used to generate the command string. If no <code>-p</code> or <code>--package</code> options +are used to generate the command string. If no <code>--package</code> options are provided, then npm will attempt to determine the executable name from the package specifier provided as the first positional argument according to the following heuristic:</p> <ul> <li>If the package has a single entry in its <code>bin</code> field in <code>package.json</code>, -then that command will be used.</li> +or if all entries are aliases of the same command, then that command +will be used.</li> <li>If the package has multiple <code>bin</code> entries, and one of them matches the unscoped portion of the <code>name</code> field, then that command will be used.</li> <li>If this does not result in exactly one option (either because there are diff --git a/deps/npm/docs/output/using-npm/developers.html b/deps/npm/docs/output/using-npm/developers.html index c0e7d4b95c..ae547d4f52 100644 --- a/deps/npm/docs/output/using-npm/developers.html +++ b/deps/npm/docs/output/using-npm/developers.html @@ -238,7 +238,7 @@ include something that is excluded by your <code>.gitignore</code> file, you can create an empty <code>.npmignore</code> file to override it. Like <code>git</code>, <code>npm</code> looks for <code>.npmignore</code> and <code>.gitignore</code> files in all subdirectories of your package, not only the root directory.</p> -<p><code>.npmignore</code> files follow the <a href="https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository#Ignoring-Files">same pattern rules</a> +<p><code>.npmignore</code> files follow the <a href="https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository#_ignoring">same pattern rules</a> as <code>.gitignore</code> files:</p> <ul> <li>Blank lines or lines starting with <code>#</code> are ignored.</li> diff --git a/deps/npm/docs/output/using-npm/scripts.html b/deps/npm/docs/output/using-npm/scripts.html index dc9d952142..8d0ad50907 100644 --- a/deps/npm/docs/output/using-npm/scripts.html +++ b/deps/npm/docs/output/using-npm/scripts.html @@ -145,7 +145,7 @@ npm command-line interface </section> <div id="_content"><h3 id="description">Description</h3> -<p>The <code>"scripts"</code> property of of your <code>package.json</code> file supports a number of built-in scripts and their preset life cycle events as well as arbitrary scripts. These all can be executed by running <code>npm run-script <stage></code> or <code>npm run <stage></code> for short. <em>Pre</em> and <em>post</em> commands with matching names will be run for those as well (e.g. <code>premyscript</code>, <code>myscript</code>, <code>postmyscript</code>). Scripts from dependencies can be run with <code>npm explore <pkg> -- npm run <stage></code>.</p> +<p>The <code>"scripts"</code> property of your <code>package.json</code> file supports a number of built-in scripts and their preset life cycle events as well as arbitrary scripts. These all can be executed by running <code>npm run-script <stage></code> or <code>npm run <stage></code> for short. <em>Pre</em> and <em>post</em> commands with matching names will be run for those as well (e.g. <code>premyscript</code>, <code>myscript</code>, <code>postmyscript</code>). Scripts from dependencies can be run with <code>npm explore <pkg> -- npm run <stage></code>.</p> <h3 id="pre--post-scripts">Pre & Post Scripts</h3> <p>To create “pre” or “post” scripts for any scripts defined in the <code>"scripts"</code> section of the <code>package.json</code>, simply create another script <em>with a matching name</em> and add “pre” or “post” to the beginning of them.</p> <pre lang="json"><code>{ diff --git a/deps/npm/lib/adduser.js b/deps/npm/lib/adduser.js index 895a677c01..5017f57a8a 100644 --- a/deps/npm/lib/adduser.js +++ b/deps/npm/lib/adduser.js @@ -4,6 +4,7 @@ const log = require('npmlog') const npm = require('./npm.js') const output = require('./utils/output.js') const usageUtil = require('./utils/usage.js') +const replaceInfo = require('./utils/replace-info.js') const authTypes = { legacy: require('./auth/legacy.js'), oauth: require('./auth/oauth.js'), @@ -57,6 +58,8 @@ const adduser = async (args) => { log.disableProgress() + log.notice('', `Log in on ${replaceInfo(registry)}`) + const { message, newCreds } = await auth({ creds, registry, diff --git a/deps/npm/lib/cache.js b/deps/npm/lib/cache.js index bf788043ab..30d6aef863 100644 --- a/deps/npm/lib/cache.js +++ b/deps/npm/lib/cache.js @@ -22,10 +22,11 @@ const usage = usageUtil('cache', const completion = (opts, cb) => { const argv = opts.conf.argv.remain if (argv.length === 2) - return cb(null, ['add', 'clean']) + return cb(null, ['add', 'clean', 'verify']) // TODO - eventually... switch (argv[2]) { + case 'verify': case 'clean': case 'add': return cb(null, []) @@ -40,11 +41,11 @@ const cache = async (args) => { case 'rm': case 'clear': case 'clean': return await clean(args) case 'add': - return await add(args, npm.prefix) + return await add(args) case 'verify': case 'check': return await verify() default: - throw usage + throw Object.assign(new Error(usage), { code: 'EUSAGE' }) } } @@ -77,22 +78,21 @@ with --force.`) // npm cache add <pkg> <ver> // npm cache add <tarball> // npm cache add <folder> -const add = async (args, where) => { +const add = async (args) => { const usage = 'Usage:\n' + ' npm cache add <tarball-url>\n' + ' npm cache add <pkg>@<ver>\n' + ' npm cache add <tarball>\n' + ' npm cache add <folder>\n' log.silly('cache add', 'args', args) - const spec = args[0] + + const spec = args[0] && args[0] + (args[1] === undefined || args[1] === null ? '' : `@${args[1]}`) - log.verbose('cache add', 'spec', spec) if (!spec) - throw new Error(usage) + throw Object.assign(new Error(usage), { code: 'EUSAGE' }) - log.silly('cache add', 'parsed spec', spec) - const opts = { ...npm.flatOptions, where } + log.silly('cache add', 'spec', spec) + const opts = { ...npm.flatOptions } // we ask pacote for the thing, and then just throw the data // away so that it tee-pipes it into the cache like it does @@ -109,7 +109,7 @@ const verify = async () => { ? `~${cache.substr(process.env.HOME.length)}` : cache const stats = await cacache.verify(cache) - output(`Cache verified and compressed (${prefix}):`) + output(`Cache verified and compressed (${prefix})`) output(`Content verified: ${stats.verifiedContent} (${stats.keptSize} bytes)`) stats.badContentCount && output(`Corrupted content removed: ${stats.badContentCount}`) stats.reclaimedCount && output(`Content garbage-collected: ${stats.reclaimedCount} (${stats.reclaimedSize} bytes)`) diff --git a/deps/npm/lib/ci.js b/deps/npm/lib/ci.js index a72e1c0cff..a1632e7e98 100644 --- a/deps/npm/lib/ci.js +++ b/deps/npm/lib/ci.js @@ -34,7 +34,7 @@ const ci = async () => { rimraf(`${where}/node_modules/*`, { glob: { dot: true, nosort: true, silent: true } }), ]) // npm ci should never modify the lockfile or package.json - await arb.reify({ save: false }) + await arb.reify({ ...npm.flatOptions, save: false }) reifyOutput(arb) } diff --git a/deps/npm/lib/cli.js b/deps/npm/lib/cli.js index f06abcd186..910b674eaa 100644 --- a/deps/npm/lib/cli.js +++ b/deps/npm/lib/cli.js @@ -1,5 +1,7 @@ // Separated out for easier unit testing module.exports = (process) => { + // set it here so that regardless of what happens later, we don't + // leak any private CLI configs to other programs process.title = 'npm' const { diff --git a/deps/npm/lib/exec.js b/deps/npm/lib/exec.js index 088a7c00eb..6bcaf838ed 100644 --- a/deps/npm/lib/exec.js +++ b/deps/npm/lib/exec.js @@ -226,15 +226,15 @@ const manifestMissing = (tree, mani) => { const getBinFromManifest = mani => { // if we have a bin matching (unscoped portion of) packagename, use that - // otherwise if there's 1 bin, use that, + // otherwise if there's 1 bin or all bin value is the same (alias), use that, // otherwise fail - const bins = Object.entries(mani.bin || {}) - if (bins.length === 1) - return bins[0][0] + const bin = mani.bin || {} + if (new Set(Object.values(bin)).size === 1) + return Object.keys(bin)[0] // XXX probably a util to parse this better? const name = mani.name.replace(/^@[^/]+\//, '') - if (mani.bin && mani.bin[name]) + if (bin[name]) return name // XXX need better error message diff --git a/deps/npm/lib/npm.js b/deps/npm/lib/npm.js index d6eab9674f..4430b80539 100644 --- a/deps/npm/lib/npm.js +++ b/deps/npm/lib/npm.js @@ -54,6 +54,7 @@ const _runCmd = Symbol('_runCmd') const _load = Symbol('_load') const _flatOptions = Symbol('_flatOptions') const _tmpFolder = Symbol('_tmpFolder') +const _title = Symbol('_title') const npm = module.exports = new class extends EventEmitter { constructor () { super() @@ -75,6 +76,7 @@ const npm = module.exports = new class extends EventEmitter { defaults, shorthands, }) + this[_title] = process.title this.updateNotification = null } @@ -156,6 +158,15 @@ const npm = module.exports = new class extends EventEmitter { return this.config.loaded } + get title () { + return this[_title] + } + + set title (t) { + process.title = t + this[_title] = t + } + async [_load] () { const node = await which(process.argv[0]).catch(er => null) if (node && node.toUpperCase() !== process.execPath.toUpperCase()) { @@ -166,6 +177,15 @@ const npm = module.exports = new class extends EventEmitter { await this.config.load() this.argv = this.config.parsedArgv.remain + // note: this MUST be shorter than the actual argv length, because it + // uses the same memory, so node will truncate it if it's too long. + // if it's a token revocation, then the argv contains a secret, so + // don't show that. (Regrettable historical choice to put it there.) + // Any other secrets are configs only, so showing only the positional + // args keeps those from being leaked. + const tokrev = deref(this.argv[0]) === 'token' && this.argv[1] === 'revoke' + this.title = tokrev ? 'npm token revoke' + (this.argv[2] ? ' ***' : '') + : ['npm', ...this.argv].join(' ') this.color = setupLog(this.config, this) process.env.COLOR = this.color ? '1' : '0' diff --git a/deps/npm/lib/run-script.js b/deps/npm/lib/run-script.js index 4d27e8eed9..568a5712f6 100644 --- a/deps/npm/lib/run-script.js +++ b/deps/npm/lib/run-script.js @@ -1,4 +1,5 @@ const run = require('@npmcli/run-script') +const { isServerPackage } = run const npm = require('./npm.js') const readJson = require('read-package-json-fast') const { resolve } = require('path') @@ -45,7 +46,7 @@ const runScript = async (args) => { pkg.scripts = scripts - if (!scripts[event]) { + if (!scripts[event] && !(event === 'start' && await isServerPackage(path))) { if (npm.config.get('if-present')) return diff --git a/deps/npm/lib/utils/config.js b/deps/npm/lib/utils/config.js index f9de6e9a79..6abb502e20 100644 --- a/deps/npm/lib/utils/config.js +++ b/deps/npm/lib/utils/config.js @@ -52,6 +52,7 @@ const defaults = { 'always-auth': false, audit: true, 'audit-level': null, + _auth: null, 'auth-type': 'legacy', before: null, 'bin-links': true, @@ -191,6 +192,7 @@ const types = { all: Boolean, 'allow-same-version': Boolean, also: [null, 'dev', 'development'], + _auth: [null, String], 'always-auth': Boolean, audit: Boolean, 'audit-level': ['low', 'moderate', 'high', 'critical', 'none', null], diff --git a/deps/npm/lib/utils/error-handler.js b/deps/npm/lib/utils/error-handler.js index dc9e2a26bc..476ca9e917 100644 --- a/deps/npm/lib/utils/error-handler.js +++ b/deps/npm/lib/utils/error-handler.js @@ -182,7 +182,7 @@ const errorHandler = (er) => { detail: messageText(msg.detail), }, } - console.log(JSON.stringify(error, null, 2)) + console.error(JSON.stringify(error, null, 2)) } exit(typeof er.errno === 'number' ? er.errno : typeof er.code === 'number' ? er.code : 1) diff --git a/deps/npm/lib/utils/explain-dep.js b/deps/npm/lib/utils/explain-dep.js index 096df97edf..ed69a02c14 100644 --- a/deps/npm/lib/utils/explain-dep.js +++ b/deps/npm/lib/utils/explain-dep.js @@ -64,7 +64,7 @@ const explainDependents = ({ name, dependents }, depth, color) => { const maxLen = 50 const showNames = [] for (let i = max; i < dependents.length; i++) { - const { from: { name } } = dependents[i] + const { from: { name = 'the root project' } } = dependents[i] len += name.length if (len >= maxLen && i < dependents.length - 1) { showNames.push('...') diff --git a/deps/npm/lib/utils/flat-options.js b/deps/npm/lib/utils/flat-options.js index be62c5a4cd..8b6864aa82 100644 --- a/deps/npm/lib/utils/flat-options.js +++ b/deps/npm/lib/utils/flat-options.js @@ -50,6 +50,7 @@ const flatten = obj => ({ alwaysAuth: obj['always-auth'], audit: obj.audit, auditLevel: obj['audit-level'], + _auth: obj._auth, authType: obj['auth-type'], ssoType: obj['sso-type'], ssoPollFrequency: obj['sso-poll-frequency'], diff --git a/deps/npm/man/man1/npm-exec.1 b/deps/npm/man/man1/npm-exec.1 index 6048388fd6..17d436812e 100644 --- a/deps/npm/man/man1/npm-exec.1 +++ b/deps/npm/man/man1/npm-exec.1 @@ -53,7 +53,8 @@ to the following heuristic: .RS 0 .IP \(bu 2 If the package has a single entry in its \fBbin\fP field in \fBpackage\.json\fP, -then that command will be used\. +or if all entries are aliases of the same command, then that command +will be used\. .IP \(bu 2 If the package has multiple \fBbin\fP entries, and one of them matches the unscoped portion of the \fBname\fP field, then that command will be used\. diff --git a/deps/npm/man/man1/npm-ls.1 b/deps/npm/man/man1/npm-ls.1 index afa7913b74..67c5234ef4 100644 --- a/deps/npm/man/man1/npm-ls.1 +++ b/deps/npm/man/man1/npm-ls.1 @@ -22,7 +22,7 @@ For example, running \fBnpm ls promzard\fP in npm's source tree will show: .P .RS 2 .nf - npm@7\.0\.8 /path/to/npm + npm@7\.0\.11 /path/to/npm └─┬ init\-package\-json@0\.0\.4 └── promzard@0\.1\.5 .fi diff --git a/deps/npm/man/man1/npm.1 b/deps/npm/man/man1/npm.1 index 9197f45f0a..32e4a5b425 100644 --- a/deps/npm/man/man1/npm.1 +++ b/deps/npm/man/man1/npm.1 @@ -10,7 +10,7 @@ npm <command> [args] .RE .SS Version .P -7\.0\.8 +7\.0\.11 .SS Description .P npm is the package manager for the Node JavaScript platform\. It puts diff --git a/deps/npm/man/man1/npx.1 b/deps/npm/man/man1/npx.1 index 88b597de52..d87c4a946d 100644 --- a/deps/npm/man/man1/npx.1 +++ b/deps/npm/man/man1/npx.1 @@ -6,9 +6,9 @@ .RS 2 .nf npm exec \-\- <pkg>[@<version>] [args\.\.\.] -npm exec \-p <pkg>[@<version>] \-\- <cmd> [args\.\.\.] +npm exec \-\-package=<pkg>[@<version>] \-\- <cmd> [args\.\.\.] npm exec \-c '<cmd> [args\.\.\.]' -npm exec \-p foo \-c '<cmd> [args\.\.\.]' +npm exec \-\-package=foo \-c '<cmd> [args\.\.\.]' npx <pkg>[@<specifier>] [args\.\.\.] npx \-p <pkg>[@<specifier>] <cmd> [args\.\.\.] @@ -17,7 +17,8 @@ npx \-p <pkg>[@<specifier>] \-c '<cmd> [args\.\.\.]' alias: npm x, npx -\-p <pkg> \-\-package=<pkg> (may be specified multiple times) +\-\-package=<pkg> (may be specified multiple times) +\-p is a shorthand for \-\-package only when using npx executable \-c <cmd> \-\-call=<cmd> (may not be mixed with positional arguments) .fi .RE @@ -27,9 +28,9 @@ This command allows you to run an arbitrary command from an npm package (either one installed locally, or fetched remotely), in a similar context as running it via \fBnpm run\fP\|\. .P -Whatever packages are specified by the \fB\-\-package\fP or \fB\-p\fP option will be +Whatever packages are specified by the \fB\-\-package\fP option will be provided in the \fBPATH\fP of the executed command, along with any locally -installed package executables\. The \fB\-\-package\fP or \fB\-p\fP option may be +installed package executables\. The \fB\-\-package\fP option may be specified multiple times, to execute the supplied command in an environment where all specified packages are available\. .P @@ -45,14 +46,15 @@ only be considered a match if they have the exact same name and version as the local dependency\. .P If no \fB\-c\fP or \fB\-\-call\fP option is provided, then the positional arguments -are used to generate the command string\. If no \fB\-p\fP or \fB\-\-package\fP options +are used to generate the command string\. If no \fB\-\-package\fP options are provided, then npm will attempt to determine the executable name from the package specifier provided as the first positional argument according to the following heuristic: .RS 0 .IP \(bu 2 If the package has a single entry in its \fBbin\fP field in \fBpackage\.json\fP, -then that command will be used\. +or if all entries are aliases of the same command, then that command +will be used\. .IP \(bu 2 If the package has multiple \fBbin\fP entries, and one of them matches the unscoped portion of the \fBname\fP field, then that command will be used\. diff --git a/deps/npm/man/man7/developers.7 b/deps/npm/man/man7/developers.7 index 9a34bf3edb..1af140b442 100644 --- a/deps/npm/man/man7/developers.7 +++ b/deps/npm/man/man7/developers.7 @@ -114,7 +114,7 @@ create an empty \fB\|\.npmignore\fP file to override it\. Like \fBgit\fP, \fBnpm for \fB\|\.npmignore\fP and \fB\|\.gitignore\fP files in all subdirectories of your package, not only the root directory\. .P -\fB\|\.npmignore\fP files follow the same pattern rules \fIhttps://git\-scm\.com/book/en/v2/Git\-Basics\-Recording\-Changes\-to\-the\-Repository#Ignoring\-Files\fR +\fB\|\.npmignore\fP files follow the same pattern rules \fIhttps://git\-scm\.com/book/en/v2/Git\-Basics\-Recording\-Changes\-to\-the\-Repository#_ignoring\fR as \fB\|\.gitignore\fP files: .RS 0 .IP \(bu 2 diff --git a/deps/npm/man/man7/scripts.7 b/deps/npm/man/man7/scripts.7 index 522e32cb80..2067fe45d9 100644 --- a/deps/npm/man/man7/scripts.7 +++ b/deps/npm/man/man7/scripts.7 @@ -3,7 +3,7 @@ \fBscripts\fR \- How npm handles the "scripts" field .SS Description .P -The \fB"scripts"\fP property of of your \fBpackage\.json\fP file supports a number of built\-in scripts and their preset life cycle events as well as arbitrary scripts\. These all can be executed by running \fBnpm run\-script <stage>\fP or \fBnpm run <stage>\fP for short\. \fIPre\fR and \fIpost\fR commands with matching names will be run for those as well (e\.g\. \fBpremyscript\fP, \fBmyscript\fP, \fBpostmyscript\fP)\. Scripts from dependencies can be run with \fBnpm explore <pkg> \-\- npm run <stage>\fP\|\. +The \fB"scripts"\fP property of your \fBpackage\.json\fP file supports a number of built\-in scripts and their preset life cycle events as well as arbitrary scripts\. These all can be executed by running \fBnpm run\-script <stage>\fP or \fBnpm run <stage>\fP for short\. \fIPre\fR and \fIpost\fR commands with matching names will be run for those as well (e\.g\. \fBpremyscript\fP, \fBmyscript\fP, \fBpostmyscript\fP)\. Scripts from dependencies can be run with \fBnpm explore <pkg> \-\- npm run <stage>\fP\|\. .SS Pre & Post Scripts .P To create "pre" or "post" scripts for any scripts defined in the \fB"scripts"\fP section of the \fBpackage\.json\fP, simply create another script \fIwith a matching name\fR and add "pre" or "post" to the beginning of them\. 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 54a6ff3375..579d5740da 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 @@ -7,6 +7,10 @@ const semver = require('semver') const promiseCallLimit = require('promise-call-limit') const getPeerSet = require('../peer-set.js') const realpath = require('../../lib/realpath.js') +const walkUpPath = require('walk-up-path') +const { dirname, resolve } = require('path') +const { promisify } = require('util') +const readdir = promisify(require('readdir-scoped-modules')) const debug = require('../debug.js') const fromPath = require('../from-path.js') @@ -182,8 +186,10 @@ module.exports = cls => class IdealTreeBuilder extends cls { process.emit('time', 'idealTree') - if (!options.add && !options.rm && this[_global]) - return Promise.reject(new Error('global requires an add or rm option')) + if (!options.add && !options.rm && !options.update && this[_global]) { + const er = new Error('global requires add, rm, or update option') + return Promise.reject(er) + } // first get the virtual tree, if possible. If there's a lockfile, then // that defines the ideal tree, unless the root package.json is not @@ -305,7 +311,6 @@ module.exports = cls => class IdealTreeBuilder extends cls { // cases we don't use a lockfile anyway. // Load on a new Arborist object, so the Nodes aren't the same, // or else it'll get super confusing when we change them! - // Only have to mapWorkspaces if we didn't get it from actual or virtual .then(async root => { if (!this[_updateAll] && !this[_global] && !root.meta.loadedFromDisk) await new this.constructor(this.options).loadActual({ root }) @@ -322,10 +327,10 @@ module.exports = cls => class IdealTreeBuilder extends cls { } [_globalRootNode] () { - const root = this[_rootNodeFromPackage]({}) + const root = this[_rootNodeFromPackage]({ dependencies: {} }) // this is a gross kludge to handle the fact that we don't save // metadata on the root node in global installs, because the "root" - // node is something like /usr/local/lib/node_modules. + // node is something like /usr/local/lib. const meta = new Shrinkwrap({ path: this.path }) meta.reset() root.meta = meta @@ -353,9 +358,19 @@ module.exports = cls => class IdealTreeBuilder extends cls { // If we have a list of package names to update, and we know it's // going to update them wherever they are, add any paths into those // named nodes to the buildIdealTree queue. - if (this[_updateNames].length) + if (!this[_global] && this[_updateNames].length) this[_queueNamedUpdates]() + // global updates only update the globalTop nodes, but we need to know + // that they're there, and not reinstall the world unnecessarily. + if (this[_global] && (this[_updateAll] || this[_updateNames].length)) { + const nm = resolve(this.path, 'node_modules') + for (const name of await readdir(nm)) { + if (this[_updateAll] || this[_updateNames].includes(name)) + this.idealTree.package.dependencies[name] = '*' + } + } + if (this.auditReport && this.auditReport.size > 0) this[_queueVulnDependents](options) @@ -563,7 +578,8 @@ module.exports = cls => class IdealTreeBuilder extends cls { const { meta, inventory } = this.idealTree const ancient = meta.ancientLockfile const old = meta.loadedFromDisk && !(meta.originalLockfileVersion >= 2) - if (inventory.size === 0 || !(ancient || old && this[_complete])) + + if (inventory.size === 0 || !ancient && !(old && this[_complete])) return // if the lockfile is from node v5 or earlier, then we'll have to reload @@ -604,6 +620,10 @@ This is a one-time fix-up, please be patient... }) } await promiseCallLimit(queue) + // yes, yes, this isn't the "original" version, but now that it's been + // upgraded, we need to make sure we don't do the work to upgrade it + // again, since it's now as new as can be. + meta.originalLockfileVersion = 2 this.finishTracker('idealTree:inflate') process.emit('timeEnd', 'idealTree:inflate') } @@ -790,6 +810,11 @@ This is a one-time fix-up, please be patient... } await Promise.all(promises) + for (const { to } of node.edgesOut.values()) { + if (to && to.isLink) + this[_linkNodes].add(to) + } + return this[_buildDepStep]() } @@ -1065,14 +1090,22 @@ This is a one-time fix-up, please be patient... let target let canPlace = null + let isSource = false + const source = this[_peerSetSource].get(dep) for (let check = start; check; check = check.resolveParent) { + // we always give the FIRST place we possibly *can* put this a little + // extra prioritization with peer dep overrides and deduping + if (check === source) + isSource = true + // if the current location has a peerDep on it, then we can't place here // this is pretty rare to hit, since we always prefer deduping peers. const checkEdge = check.edgesOut.get(edge.name) if (!check.isTop && checkEdge && checkEdge.peer) continue - const cp = this[_canPlaceDep](dep, check, edge, peerEntryEdge, peerPath) + const cp = this[_canPlaceDep](dep, check, edge, peerEntryEdge, peerPath, isSource) + isSource = false // anything other than a conflict is fine to proceed with if (cp !== CONFLICT) { @@ -1144,7 +1177,7 @@ This is a one-time fix-up, please be patient... const oldDeps = [] for (const [name, edge] of oldChild.edgesOut.entries()) { if (!newDep.edgesOut.has(name) && edge.to) - oldDeps.push(edge.to) + oldDeps.push(...gatherDepSet([edge.to], e => e.to !== edge.to)) } newDep.replace(oldChild) this[_pruneForReplacement](newDep, oldDeps) @@ -1245,14 +1278,17 @@ This is a one-time fix-up, please be patient... // deps that the new node doesn't depend on but the old one did. const invalidDeps = new Set([...node.edgesOut.values()] .filter(e => e.to && !e.valid).map(e => e.to)) - for (const dep of oldDeps) - invalidDeps.add(dep) + for (const dep of oldDeps) { + const set = gatherDepSet([dep], e => e.to !== dep && e.valid) + for (const dep of set) + invalidDeps.add(dep) + } // ignore dependency edges from the node being replaced, but // otherwise filter the set down to just the set with no // dependencies from outside the set, except the node in question. const deps = gatherDepSet(invalidDeps, edge => - edge.from !== node && edge.to !== node) + edge.from !== node && edge.to !== node && edge.valid) // now just delete whatever's left, because it's junk for (const dep of deps) @@ -1279,7 +1315,7 @@ This is a one-time fix-up, please be patient... // checking, because either we're leaving it alone, or it won't work anyway. // When we check peers, we pass along the peerEntryEdge to track the // original edge that caused us to load the family of peer dependencies. - [_canPlaceDep] (dep, target, edge, peerEntryEdge = null, peerPath = []) { + [_canPlaceDep] (dep, target, edge, peerEntryEdge = null, peerPath = [], isSource = false) { /* istanbul ignore next */ debug(() => { if (!dep) @@ -1287,8 +1323,16 @@ This is a one-time fix-up, please be patient... }) const entryEdge = peerEntryEdge || edge const source = this[_peerSetSource].get(dep) - const isSource = target === source - const { isRoot, isWorkspace } = source || {} + isSource = isSource || target === source + // if we're overriding the source, then we care if the *target* is + // ours, even if it wasn't actually the original source, since we + // are depending on something that has a dep that can't go in its own + // folder. for example, a -> b, b -> PEER(a). Even though a is the + // source, b has to be installed up a level, and if the root package + // depends on a, and it has a conflict, it's our problem. So, the root + // (or whatever is bringing in a) becomes the "effective source" for + // the purposes of this calculation. + const { isRoot, isWorkspace } = isSource ? target : source || {} const isMine = isRoot || isWorkspace // Useful testing thingie right here. @@ -1313,7 +1357,7 @@ This is a one-time fix-up, please be patient... const { version: newVer } = dep const tryReplace = curVer && newVer && semver.gte(newVer, curVer) if (tryReplace && dep.canReplace(current)) { - const res = this[_canPlacePeers](dep, target, edge, REPLACE, peerEntryEdge, peerPath) + const res = this[_canPlacePeers](dep, target, edge, REPLACE, peerEntryEdge, peerPath, isSource) /* istanbul ignore else - It's extremely rare that a replaceable * node would be a conflict, if the current one wasn't a conflict, * but it is theoretically possible if peer deps are pinned. In @@ -1333,7 +1377,7 @@ This is a one-time fix-up, please be patient... // a bit harder to be singletons. const preferDedupe = this[_preferDedupe] || edge.peer if (preferDedupe && !tryReplace && dep.canReplace(current)) { - const res = this[_canPlacePeers](dep, target, edge, REPLACE, peerEntryEdge, peerPath) + const res = this[_canPlacePeers](dep, target, edge, REPLACE, peerEntryEdge, peerPath, isSource) /* istanbul ignore else - It's extremely rare that a replaceable * node would be a conflict, if the current one wasn't a conflict, * but it is theoretically possible if peer deps are pinned. In @@ -1401,7 +1445,7 @@ This is a one-time fix-up, please be patient... } } if (canReplace) { - const ret = this[_canPlacePeers](dep, target, edge, REPLACE, peerEntryEdge, peerPath) + const ret = this[_canPlacePeers](dep, target, edge, REPLACE, peerEntryEdge, peerPath, isSource) /* istanbul ignore else - extremely rare that the peer set would * conflict if we can replace the node in question, but theoretically * possible, if peer deps are pinned aggressively. */ @@ -1462,14 +1506,14 @@ This is a one-time fix-up, please be patient... } // no objections! ok to place here - return this[_canPlacePeers](dep, target, edge, OK, peerEntryEdge, peerPath) + return this[_canPlacePeers](dep, target, edge, OK, peerEntryEdge, peerPath, isSource) } // make sure the family of peer deps can live here alongside it. // this doesn't guarantee that THIS solution will be the one we take, // but it does establish that SOME solution exists at this level in // the tree. - [_canPlacePeers] (dep, target, edge, ret, peerEntryEdge, peerPath) { + [_canPlacePeers] (dep, target, edge, ret, peerEntryEdge, peerPath, isSource) { // do not go in cycles when we're resolving a peer group if (!dep.parent || peerEntryEdge && peerPath.includes(dep)) return ret @@ -1481,7 +1525,7 @@ This is a one-time fix-up, please be patient... if (!peerEdge.peer || !peerEdge.to) continue const peer = peerEdge.to - const canPlacePeer = this[_canPlaceDep](peer, target, peerEdge, entryEdge, peerPath) + const canPlacePeer = this[_canPlaceDep](peer, target, peerEdge, entryEdge, peerPath, isSource) if (canPlacePeer !== CONFLICT) continue @@ -1514,34 +1558,35 @@ This is a one-time fix-up, please be patient... const external = /^\.\.(\/|$)/.test(loc) - if (external && !this[_follow]) { - // outside the root, somebody else's problem, ignore it - continue - } - if (!link.target.parent && !link.target.fsParent) { - // the fsParent MUST be some node in the tree, possibly the root. - // find it by walking up. Note that this is where its deps may - // end up being installed, if possible. - const parts = loc.split('/') - for (let p = parts.length - 1; p > -1; p--) { - const path = parts.slice(0, p).join('/') - if (!path && external) - break + // the fsParent likely some node in the tree, possibly the root, + // unless it is external. find it by walking up. Note that this + // is where its deps may end up being installed, if possible. + for (const p of walkUpPath(dirname(realpath))) { + const path = relpath(this.path, p) const node = !path ? this.idealTree : this.idealTree.inventory.get(path) if (node) { link.target.fsParent = node this.addTracker('idealTree', link.target.name, link.target.location) this[_depsQueue].push(link.target) - p = -1 + break } } } - // didn't find a parent for it, but we're filling in external - // link targets, so go ahead and process it. - if (this[_follow] && !link.target.parent && !link.target.fsParent) { + // outside the root, somebody else's problem, ignore it + if (external && !this[_follow]) + continue + + // didn't find a parent for it or it has not been seen yet + // so go ahead and process it. + const unseenLink = (link.target.parent || link.target.fsParent) + && !this[_depsSeen].has(link.target) + if (this[_follow] + && !link.target.parent + && !link.target.fsParent + || unseenLink) { this.addTracker('idealTree', link.target.name, link.target.location) this[_depsQueue].push(link.target) } 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 14c9609275..e335bdadd4 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 @@ -185,12 +185,6 @@ module.exports = cls => class VirtualLoader extends cls { // 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) async [resolveLinks] (links, nodes) { - // now we've loaded the root, and all real nodes - // link up the links - const {meta} = this.virtualTree - const {loadedFromDisk, originalLockfileVersion} = meta - const oldLockfile = loadedFromDisk && !(originalLockfileVersion >= 2) - for (const [location, meta] of links.entries()) { const targetPath = resolve(this.path, meta.resolved) const targetLoc = relpath(this.path, targetPath) @@ -198,27 +192,31 @@ module.exports = cls => class VirtualLoader extends cls { const link = this[loadLink](location, targetLoc, target, meta) nodes.set(location, link) nodes.set(targetLoc, link.target) - // legacy shrinkwraps do not store all the info we need for the target. - // if we're loading from disk, and have a link in place, we need to - // look in that actual folder (or at least try to) in order to get - // the dependencies of the link target and load it properly. - if (oldLockfile) { - const pj = link.realpath + '/package.json' - const pkg = await rpj(pj).catch(() => null) - if (pkg) - link.target.package = pkg - } + + // we always need to read the package.json for link targets + // because they can be changed by the local user + const pj = link.realpath + '/package.json' + const pkg = await rpj(pj).catch(() => null) + if (pkg) + link.target.package = pkg } } [assignParentage] (nodes) { for (const [location, node] of nodes) { + // Skip assignment of parentage for the root package + if (!location) + continue const { path, name } = node for (const p of walkUp(dirname(path))) { const ploc = relpath(this.path, p) const parent = nodes.get(ploc) if (!parent) continue + // Safety check: avoid self-assigning nodes as their own parents + /* istanbul ignore if - should be obviated by parentage skip check */ + if (parent === node) + continue const locTest = `${ploc}/node_modules/${name}`.replace(/^\//, '') const ptype = location === locTest 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 57ecf071fb..92943554b4 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js @@ -10,10 +10,10 @@ const {dirname, resolve, relative} = require('path') const {depth: dfwalk} = require('treeverse') const fs = require('fs') const {promisify} = require('util') -const rename = promisify(fs.rename) const symlink = promisify(fs.symlink) const writeFile = promisify(fs.writeFile) const mkdirp = require('mkdirp-infer-owner') +const moveFile = require('@npmcli/move-file') const rimraf = promisify(require('rimraf')) const packageContents = require('@npmcli/installed-package-contents') @@ -60,6 +60,7 @@ const _rollbackRetireShallowNodes = Symbol.for('rollbackRetireShallowNodes') const _rollbackCreateSparseTree = Symbol.for('rollbackCreateSparseTree') const _rollbackMoveBackRetiredUnchanged = Symbol.for('rollbackMoveBackRetiredUnchanged') const _saveIdealTree = Symbol.for('saveIdealTree') +const _saveLockFile = Symbol('saveLockFile') const _copyIdealToActual = Symbol('copyIdealToActual') const _addOmitsToTrashList = Symbol('addOmitsToTrashList') const _packageLockOnly = Symbol('packageLockOnly') @@ -172,7 +173,7 @@ module.exports = cls => class Reifier extends cls { ignoreMissing: true, global: true, filter: (node, kid) => !node.isRoot ? true - : this[_explicitRequests].has(kid), + : (node.edgesOut.has(kid) || this[_explicitRequests].has(kid)), } : { ignoreMissing: true } if (!this[_global]) { @@ -182,7 +183,9 @@ module.exports = cls => class Reifier extends cls { // the global install space tends to have a lot of stuff in it. don't // load all of it, just what we care about. we won't be saving a - // hidden lockfile in there anyway. + // hidden lockfile in there anyway. Note that we have to load ideal + // BEFORE loading actual, so that the actualOpt can use the + // explicitRequests which is set during buildIdealTree return this.buildIdealTree(bitOpt) .then(() => this.loadActual(actualOpt)) .then(() => process.emit('timeEnd', 'reify:loadTrees')) @@ -251,7 +254,7 @@ module.exports = cls => class Reifier extends cls { } [_renamePath] (from, to, didMkdirp = false) { - return rename(from, to) + return moveFile(from, to) .catch(er => { // Occasionally an expected bin file might not exist in the package, // or a shim/symlink might have been moved aside. If we've already @@ -261,7 +264,7 @@ module.exports = cls => class Reifier extends cls { return didMkdirp ? null : mkdirp(dirname(to)).then(() => this[_renamePath](from, to, true)) } else if (er.code === 'EEXIST') - return rimraf(to).then(() => rename(from, to)) + return rimraf(to).then(() => moveFile(from, to)) else throw er }) @@ -427,7 +430,7 @@ module.exports = cls => class Reifier extends cls { const dir = dirname(node.path) const target = node.realpath const rel = relative(dir, target) - return symlink(rel, node.path, 'dir') + return symlink(rel, node.path, 'junction') } [_warnDeprecated] (node) { @@ -436,23 +439,29 @@ module.exports = cls => class Reifier extends cls { this.log.warn('deprecated', `${_id}: ${deprecated}`) } - [_loadAncientPackageDetails] (node) { + async [_loadAncientPackageDetails] (node, forceReload = false) { // If we're loading from a v1 lockfile, load details from the package.json // that weren't recorded in the old format. const {meta} = this.idealTree const ancient = meta.ancientLockfile const old = meta.loadedFromDisk && !(meta.originalLockfileVersion >= 2) + // already replaced with the manifest if it's truly ancient - if (old && !ancient) { + if (node.path && (forceReload || (old && !ancient))) { // XXX should have a shared location where package.json is read, // so we don't ever read the same pj more than necessary. - return rpj(node.path + '/package.json').then(pkg => { + let pkg + try { + pkg = await rpj(node.path + '/package.json') + } catch (err) {} + + if (pkg) { node.package.bin = pkg.bin node.package.os = pkg.os node.package.cpu = pkg.cpu node.package.engines = pkg.engines meta.add(node) - }) + } } } @@ -839,12 +848,28 @@ module.exports = cls => class Reifier extends cls { format: (this[_formatPackageLock] && format) ? format : this[_formatPackageLock], } + return Promise.all([ - this[_usePackageLock] && this.idealTree.meta.save(saveOpt), + this[_saveLockFile](saveOpt), writeFile(pj, json), ]).then(() => process.emit('timeEnd', 'reify:save')) } + async [_saveLockFile] (saveOpt) { + if (!this[_usePackageLock]) + return + + const { meta } = this.idealTree + + // might have to update metadata for bins and stuff that gets lost + if (meta.loadedFromDisk && !(meta.originalLockfileVersion >= 2)) { + for (const node of this.idealTree.inventory.values()) + await this[_loadAncientPackageDetails](node, true) + } + + return meta.save(saveOpt) + } + [_copyIdealToActual] () { // save the ideal's meta as a hidden lockfile after we actualize it this.idealTree.meta.filename = diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/node.js b/deps/npm/node_modules/@npmcli/arborist/lib/node.js index a783ce9c97..e4ba3ac42b 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/node.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/node.js @@ -35,6 +35,7 @@ const {normalize} = require('read-package-json-fast') const {getPaths: getBinPaths} = require('bin-links') const npa = require('npm-package-arg') const debug = require('./debug.js') +const gatherDepSet = require('./gather-dep-set.js') const {resolve, relative, dirname, basename} = require('path') const _package = Symbol('_package') @@ -566,13 +567,32 @@ class Node { } debug(() => { - if (!this.fsParent && this.realpath.indexOf(fsParent.realpath) !== 0) - throw new Error('attempting to set fsParent improperly') + if (fsParent === this) + throw new Error('setting node to its own fsParent') + + if (fsParent.realpath === this.realpath) + throw new Error('setting fsParent to same path') + + // the initial set MUST be an actual walk-up from the realpath + // subsequent sets will re-root on the new fsParent's path. + if (!this[_fsParent] && this.realpath.indexOf(fsParent.realpath) !== 0) { + throw Object.assign(new Error('setting fsParent improperly'), { + path: this.path, + realpath: this.realpath, + fsParent: { + path: fsParent.path, + realpath: fsParent.realpath, + }, + }) + } if (fsParent.isLink) - throw new Error('attempting to set fsParent to link node') + throw new Error('setting fsParent to link node') }) + if (this === fsParent || fsParent.realpath === this.realpath) + return + // prune off the original location, so we don't leave edges lying around if (current) this.fsParent = null @@ -621,8 +641,14 @@ class Node { if (node.name !== this.name) return false + // gather up all the deps of this node and that are only depended + // upon by deps of this node. those ones don't count, since + // they'll be replaced if this node is replaced anyway. + const depSet = gatherDepSet([this], e => e.to !== this && e.valid) + for (const edge of this.edgesIn) { - if (!edge.satisfiedBy(node)) + // only care about edges that don't originate from this node + if (!depSet.has(edge.from) && !edge.satisfiedBy(node)) return false } @@ -731,6 +757,9 @@ class Node { set parent (parent) { const oldParent = this[_parent] + if (this === parent) + return + // link nodes can't contain children directly. // children go under the link target. if (parent) { diff --git a/deps/npm/node_modules/@npmcli/arborist/package.json b/deps/npm/node_modules/@npmcli/arborist/package.json index fe72f409c4..6dca9abe50 100644 --- a/deps/npm/node_modules/@npmcli/arborist/package.json +++ b/deps/npm/node_modules/@npmcli/arborist/package.json @@ -1,11 +1,12 @@ { "name": "@npmcli/arborist", - "version": "1.0.8", + "version": "1.0.11", "description": "Manage node_modules trees", "dependencies": { "@npmcli/installed-package-contents": "^1.0.5", "@npmcli/map-workspaces": "^1.0.1", "@npmcli/metavuln-calculator": "^1.0.0", + "@npmcli/move-file": "^1.0.1", "@npmcli/name-from-folder": "^1.0.1", "@npmcli/node-gyp": "^1.0.0", "@npmcli/run-script": "^1.7.2", @@ -68,6 +69,7 @@ "node-arg": [ "--unhandled-rejections=strict" ], + "after": "test/fixtures/cleanup.js", "coverage-map": "map.js", "esm": false, "timeout": "120" 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 5980376f55..47f386304e 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 @@ -20,6 +20,9 @@ const runScriptPkg = async options => { stdioString = false, // note: only used when stdio:inherit banner = true, + // how long to wait for a process.kill signal + // only exposed here so that we can make the test go a bit faster. + signalTimeout = 500, } = options const {scripts = {}, gypfile} = pkg @@ -68,7 +71,17 @@ const runScriptPkg = async options => { if (p.stdin) p.stdin.end() - return p + return p.catch(er => { + const { signal } = er + if (stdio === 'inherit' && signal) { + process.kill(process.pid, signal) + // just in case we don't die, reject after 500ms + // this also keeps the node process open long enough to actually + // get the signal, rather than terminating gracefully. + return new Promise((res, rej) => setTimeout(() => rej(er), signalTimeout)) + } else + throw er + }) } module.exports = runScriptPkg 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 3be39b0ba8..af33d2113f 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,6 +1,7 @@ const rpj = require('read-package-json-fast') const runScriptPkg = require('./run-script-pkg.js') const validateOptions = require('./validate-options.js') +const isServerPackage = require('./is-server-package.js') const runScript = options => { validateOptions(options) @@ -9,4 +10,4 @@ const runScript = options => { : rpj(path + '/package.json').then(pkg => runScriptPkg({...options, pkg})) } -module.exports = runScript +module.exports = Object.assign(runScript, { isServerPackage }) diff --git a/deps/npm/node_modules/@npmcli/run-script/package.json b/deps/npm/node_modules/@npmcli/run-script/package.json index 5ec3bb5b66..c8a052f036 100644 --- a/deps/npm/node_modules/@npmcli/run-script/package.json +++ b/deps/npm/node_modules/@npmcli/run-script/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/run-script", - "version": "1.7.4", + "version": "1.7.5", "description": "Run a lifecycle script for a package (descendant of npm-lifecycle)", "author": "Isaac Z. Schlueter <i@izs.me> (https://izs.me)", "license": "ISC", diff --git a/deps/npm/node_modules/libnpmversion/lib/version.js b/deps/npm/node_modules/libnpmversion/lib/version.js index ee02fb7ffb..309b9c2b95 100644 --- a/deps/npm/node_modules/libnpmversion/lib/version.js +++ b/deps/npm/node_modules/libnpmversion/lib/version.js @@ -34,7 +34,7 @@ module.exports = async (newversion, opts) => { } = opts const { valid, clean, inc } = semver - const current = pkg.version + const current = pkg.version || '0.0.0' const currentClean = clean(current) const newV = valid(newversion, { loose: true }) ? clean(newversion, { loose: true }) diff --git a/deps/npm/node_modules/libnpmversion/package.json b/deps/npm/node_modules/libnpmversion/package.json index 856e36da6d..d7e8d5fa58 100644 --- a/deps/npm/node_modules/libnpmversion/package.json +++ b/deps/npm/node_modules/libnpmversion/package.json @@ -1,6 +1,6 @@ { "name": "libnpmversion", - "version": "1.0.6", + "version": "1.0.7", "main": "lib/index.js", "files": [ "lib/*.js" diff --git a/deps/npm/node_modules/pacote/lib/fetcher.js b/deps/npm/node_modules/pacote/lib/fetcher.js index 01058acb2b..5142bb280a 100644 --- a/deps/npm/node_modules/pacote/lib/fetcher.js +++ b/deps/npm/node_modules/pacote/lib/fetcher.js @@ -91,18 +91,11 @@ class FetcherBase { // command to run 'prepare' scripts on directories and git dirs // To use pacote with yarn, for example, set npmBin to 'yarn' - // and npmInstallCmd to ['add'], and npmCliConfig with yarn's equivalents. + // and npmCliConfig with yarn's equivalents. this.npmBin = opts.npmBin || 'npm' // command to install deps for preparing - this.npmInstallCmd = opts.npmInstallCmd || [ - 'install', - '--only=dev', - '--prod', - '--ignore-prepublish', - '--no-progress', - '--no-save', - ] + this.npmInstallCmd = opts.npmInstallCmd || [ 'install' ] // XXX fill more of this in based on what we know from this.opts // we explicitly DO NOT fill in --tag, though, since we are often @@ -113,7 +106,10 @@ class FetcherBase { `--prefer-offline=${!!this.preferOffline}`, `--prefer-online=${!!this.preferOnline}`, `--offline=${!!this.offline}`, - `--before=${this.before ? this.before.toISOString() : ''}`, + ...(this.before ? [`--before=${this.before.toISOString()}`] : []), + '--no-progress', + '--no-save', + '--no-audit', ] } diff --git a/deps/npm/node_modules/pacote/package.json b/deps/npm/node_modules/pacote/package.json index 7f38a193f7..bef19b6622 100644 --- a/deps/npm/node_modules/pacote/package.json +++ b/deps/npm/node_modules/pacote/package.json @@ -1,6 +1,6 @@ { "name": "pacote", - "version": "11.1.12", + "version": "11.1.13", "description": "JavaScript package downloader", "author": "Isaac Z. Schlueter <i@izs.me> (https://izs.me)", "bin": { @@ -47,7 +47,7 @@ "minipass": "^3.1.3", "mkdirp": "^1.0.3", "npm-package-arg": "^8.0.1", - "npm-packlist": "^2.1.0", + "npm-packlist": "^2.1.4", "npm-pick-manifest": "^6.0.0", "npm-registry-fetch": "^9.0.0", "promise-retry": "^1.1.1", diff --git a/deps/npm/package.json b/deps/npm/package.json index d0ca0bf91a..5dfcd6807f 100644 --- a/deps/npm/package.json +++ b/deps/npm/package.json @@ -1,5 +1,5 @@ { - "version": "7.0.8", + "version": "7.0.11", "name": "npm", "description": "a package manager for JavaScript", "keywords": [ @@ -42,10 +42,10 @@ "./package.json": "./package.json" }, "dependencies": { - "@npmcli/arborist": "^1.0.8", + "@npmcli/arborist": "^1.0.11", "@npmcli/ci-detect": "^1.2.0", "@npmcli/config": "^1.2.1", - "@npmcli/run-script": "^1.7.4", + "@npmcli/run-script": "^1.7.5", "abbrev": "~1.1.1", "ansicolors": "~0.3.2", "ansistyles": "~0.1.3", @@ -76,7 +76,7 @@ "libnpmpublish": "^4.0.0", "libnpmsearch": "^3.0.1", "libnpmteam": "^2.0.2", - "libnpmversion": "^1.0.6", + "libnpmversion": "^1.0.7", "make-fetch-happen": "^8.0.9", "mkdirp": "^1.0.4", "mkdirp-infer-owner": "^2.0.0", @@ -92,7 +92,7 @@ "npm-user-validate": "^1.0.1", "npmlog": "~4.1.2", "opener": "^1.5.2", - "pacote": "^11.1.12", + "pacote": "^11.1.13", "parse-conflict-json": "^1.1.1", "qrcode-terminal": "^0.12.0", "read": "~1.0.7", @@ -180,12 +180,12 @@ "write-file-atomic" ], "devDependencies": { - "cmark-gfm": "^0.8.3", - "eslint": "^7.12.1", + "cmark-gfm": "^0.8.4", + "eslint": "^7.13.0", "eslint-plugin-import": "^2.22.1", "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^4.2.1", - "eslint-plugin-standard": "^4.0.2", + "eslint-plugin-standard": "^4.1.0", "jsdom": "^16.4.0", "marked-man": "^0.7.0", "require-inject": "^1.4.4", diff --git a/deps/npm/scripts/install.sh b/deps/npm/scripts/install.sh index 7f66151dae..4458de87fa 100755 --- a/deps/npm/scripts/install.sh +++ b/deps/npm/scripts/install.sh @@ -8,7 +8,7 @@ # shell living at /bin/sh. # # See this helpful document on writing portable shell scripts: -# https://www.gnu.org/s/hello/manual/autoconf/Portable-Shell.html +# http://www.gnu.org/s/hello/manual/autoconf/Portable-Shell.html # # The only shell it won't ever work on is cmd.exe. @@ -23,32 +23,27 @@ if [ "x$0" = "xsh" ]; then if [ $ret -eq 0 ]; then (exit 0) else - echo "Uninstalling npm-install-$$.sh" >&2 rm npm-install-$$.sh - echo "Failed to download script" >&2 + echo "failed to download script" >&2 exit $ret fi sh npm-install-$$.sh ret=$? - echo "Uninstalling npm-install-$$.sh" >&2 rm npm-install-$$.sh exit $ret fi -# See what "npm_config_*" things there are in the env, -# and make them permanent. -# If this fails, it's not such a big deal. -configures="`env | grep 'npm_config_' | sed -e 's|^npm_config_||g'`" - +debug=0 npm_config_loglevel="error" if [ "x$npm_debug" = "x" ]; then (exit 0) else - echo "Running in debug mode." - echo "Note that this requires bash or zsh." + echo "running in debug mode." + echo "note that this requires bash or zsh." set -o xtrace set -o pipefail npm_config_loglevel="verbose" + debug=1 fi export npm_config_loglevel @@ -61,33 +56,20 @@ if [ $ret -ne 0 ]; then ret=$? fi if [ $ret -eq 0 ] && [ -x "$node" ]; then + if [ $debug -eq 1 ]; then + echo "found 'node' at: $node" + echo -n "version: " + $node --version + echo "" + fi (exit 0) else echo "npm cannot be installed without node.js." >&2 - echo "Install node first, and then try again." >&2 + echo "install node first, and then try again." >&2 echo "" >&2 - echo "Maybe node is installed, but not in the PATH?" >&2 - echo "Note that running as sudo can change envs." >&2 - echo "" - echo "PATH=$PATH" >&2 exit $ret fi -# set the temp dir -TMP="${TMPDIR}" -if [ "x$TMP" = "x" ]; then - TMP="/tmp" -fi -TMP="${TMP}/npm.$$" -rm -rf "$TMP" || true -mkdir "$TMP" -if [ $? -ne 0 ]; then - echo "failed to mkdir $TMP" >&2 - exit 1 -fi - -BACK="$PWD" - ret=0 tar="${TAR}" if [ -z "$tar" ]; then @@ -99,10 +81,11 @@ if [ -z "$tar" ]; then fi if [ $ret -eq 0 ] && [ -x "$tar" ]; then - echo "tar=$tar" - if [ $tar --version > /dev/null 2>&1 ]; then - echo "version:" + if [ $debug -eq 1 ]; then + echo "found 'tar' at: $tar" + echo -n "version: " $tar --version + echo "" fi ret=$? fi @@ -110,76 +93,43 @@ fi if [ $ret -eq 0 ]; then (exit 0) else - echo "No suitable tar program found." + echo "this script requires 'tar', please install it and try again." exit 1 fi - - -# Try to find a suitable make -# If the MAKE environment var is set, use that. -# otherwise, try to find gmake, and then make. -# If no make is found, then just execute the necessary commands. - -# XXX For some reason, make is building all the docs every time. This -# is an annoying source of bugs. Figure out why this happens. -MAKE=NOMAKE - -if [ "x$MAKE" = "x" ]; then - make=`which gmake 2>&1` - if [ $? -eq 0 ] && [ -x "$make" ]; then - (exit 0) - else - make=`which make 2>&1` - if [ $? -eq 0 ] && [ -x "$make" ]; then - (exit 0) - else - make=NOMAKE - fi +curl=`which curl 2>&1` +ret=$? +if [ $ret -eq 0 ]; then + if [ $debug -eq 1 ]; then + echo "found 'curl' at: $curl" + echo -n "version: " + $curl --version | head -n 1 + echo "" fi -else - make="$MAKE" -fi - -if [ -x "$make" ]; then (exit 0) else - # echo "Installing without make. This may fail." >&2 - make=NOMAKE + echo "this script requires 'curl', please install it and try again." + exit 1 fi -# If there's no bash, then don't even try to clean -if [ -x "/bin/bash" ]; then - (exit 0) -else - clean="no" +# set the temp dir +TMP="${TMPDIR}" +if [ "x$TMP" = "x" ]; then + TMP="/tmp" fi - -node_version=`"$node" --version 2>&1` -ret=$? -if [ $ret -ne 0 ]; then - echo "You need node to run this program." >&2 - echo "node --version reports: $node_version" >&2 - echo "with exit code = $ret" >&2 - echo "Please install node before continuing." >&2 - exit $ret +TMP="${TMP}/npm.$$" +rm -rf "$TMP" || true +mkdir "$TMP" +if [ $? -ne 0 ]; then + echo "failed to mkdir $TMP" >&2 + exit 1 fi +BACK="$PWD" + t="${npm_install}" if [ -z "$t" ]; then - # switch based on node version. - # note that we can only use strict sh-compatible patterns here. - case $node_version in - 0.[01234567].* | v0.[01234567].*) - echo "You are using an outdated and unsupported version of" >&2 - echo "node ($node_version). Please update node and try again." >&2 - exit 99 - ;; - *) - echo "install npm@latest" - t="latest" - ;; - esac + t="latest" fi # need to echo "" after, because Posix sed doesn't treat EOF @@ -201,7 +151,7 @@ if [ "x$url" = "x" ]; then fi fi if [ $ret -ne 0 ]; then - echo "Failed to get tarball url for npm/$t" >&2 + echo "failed to get tarball url for npm/$t" >&2 exit $ret fi @@ -209,37 +159,19 @@ fi echo "fetching: $url" >&2 cd "$TMP" \ - && curl -SsL "$url" \ - | $tar -xzf - \ - && cd "$TMP"/* \ - && (ret=0 - if [ $ret -ne 0 ]; then - echo "Aborted 0.x cleanup. Exiting." >&2 - exit $ret - fi) \ - && (if [ "x$configures" = "x" ]; then - (exit 0) - else - echo "./configure $configures" - echo "$configures" > npmrc - fi) \ - && (if [ "$make" = "NOMAKE" ]; then - (exit 0) - elif "$make" uninstall install; then - (exit 0) - else - make="NOMAKE" - fi - if [ "$make" = "NOMAKE" ]; then - "$node" bin/npm-cli.js rm npm -gf - "$node" bin/npm-cli.js install -gf $("$node" bin/npm-cli.js pack | tail -1) - fi) \ + && curl -SsL -o npm.tgz "$url" \ + && $tar -xzf npm.tgz \ + && cd "$TMP"/package \ + && echo "removing existing npm" \ + && "$node" bin/npm-cli.js rm npm -gf --loglevel=silent \ + && echo "installing npm@$t" \ + && "$node" bin/npm-cli.js install -gf ../npm.tgz \ && cd "$BACK" \ && rm -rf "$TMP" \ - && echo "It worked" + && echo "successfully installed npm@$t" ret=$? if [ $ret -ne 0 ]; then - echo "It failed" >&2 + echo "failed!" >&2 fi exit $ret diff --git a/deps/npm/tap-snapshots/test-lib-utils-config.js-TAP.test.js b/deps/npm/tap-snapshots/test-lib-utils-config.js-TAP.test.js index 5190a5604a..3bdf905d86 100644 --- a/deps/npm/tap-snapshots/test-lib-utils-config.js-TAP.test.js +++ b/deps/npm/tap-snapshots/test-lib-utils-config.js-TAP.test.js @@ -8,6 +8,7 @@ exports[`test/lib/utils/config.js TAP no process.umask() method > must match snapshot 1`] = ` Object { "defaults": Object { + "_auth": null, "access": null, "all": false, "allow-same-version": false, @@ -267,6 +268,10 @@ Object { ], }, "types": Object { + "_auth": Array [ + null, + "{String TYPE}", + ], "access": Array [ null, "restricted", @@ -537,6 +542,7 @@ Object { exports[`test/lib/utils/config.js TAP no working network interfaces, on windows > must match snapshot 1`] = ` Object { "defaults": Object { + "_auth": null, "access": null, "all": false, "allow-same-version": false, @@ -796,6 +802,10 @@ Object { ], }, "types": Object { + "_auth": Array [ + null, + "{String TYPE}", + ], "access": Array [ null, "restricted", @@ -1066,6 +1076,7 @@ Object { exports[`test/lib/utils/config.js TAP working network interfaces, not windows > must match snapshot 1`] = ` Object { "defaults": Object { + "_auth": null, "access": null, "all": false, "allow-same-version": false, @@ -1325,6 +1336,10 @@ Object { ], }, "types": Object { + "_auth": Array [ + null, + "{String TYPE}", + ], "access": Array [ null, "restricted", diff --git a/deps/npm/tap-snapshots/test-lib-utils-explain-dep.js-TAP.test.js b/deps/npm/tap-snapshots/test-lib-utils-explain-dep.js-TAP.test.js index 48f84e5111..54a77bc122 100644 --- a/deps/npm/tap-snapshots/test-lib-utils-explain-dep.js-TAP.test.js +++ b/deps/npm/tap-snapshots/test-lib-utils-explain-dep.js-TAP.test.js @@ -10,7 +10,7 @@ manydep@1.0.0 manydep@"1.0.0" from prod-dep@1.2.3 node_modules/prod-dep prod-dep@"1.x" from the root project - 6 more (optdep, extra-neos, deep-dev, peer, ...) + 7 more (optdep, extra-neos, deep-dev, peer, the root project, ...) ` exports[`test/lib/utils/explain-dep.js TAP > ellipses test two 1`] = ` @@ -18,7 +18,7 @@ manydep@1.0.0 manydep@"1.0.0" from prod-dep@1.2.3 node_modules/prod-dep prod-dep@"1.x" from the root project - 5 more (optdep, extra-neos, deep-dev, peer, a package with a pretty long name) + 6 more (optdep, extra-neos, deep-dev, peer, the root project, a package with a pretty long name) ` exports[`test/lib/utils/explain-dep.js TAP deepDev > explain color deep 1`] = ` @@ -90,6 +90,7 @@ exports[`test/lib/utils/explain-dep.js TAP manyDeps > explain color deep 1`] = ` [35mpeer[39m [1mmanydep[22m@"[1m>1.0.0-beta <1.0.1[22m" from [1mpeer[22m@[1m1.0.0[22m [1m[35mpeer[39m[22m[2m[22m [2mnode_modules/peer[22m [35mpeer[39m [1mpeer[22m@"[1m1.0.0[22m" from the root project + [1mmanydep[22m@"[1m>1.0.0-beta <1.0.1[22m" from the root project [1mmanydep[22m@"[1m1[22m" from [1ma package with a pretty long name[22m@[1m1.2.3[22m [1mmanydep[22m@"[1m1[22m" from [1manother package with a pretty long name[22m@[1m1.2.3[22m [1mmanydep[22m@"[1m1[22m" from [1myet another a package with a pretty long name[22m@[1m1.2.3[22m @@ -100,7 +101,7 @@ manydep@1.0.0 manydep@"1.0.0" from prod-dep@1.2.3 node_modules/prod-dep prod-dep@"1.x" from the root project - 7 more (optdep, extra-neos, deep-dev, peer, ...) + 8 more (optdep, extra-neos, deep-dev, peer, the root project, ...) ` exports[`test/lib/utils/explain-dep.js TAP manyDeps > print color 1`] = ` diff --git a/deps/npm/tap-snapshots/test-lib-utils-flat-options.js-TAP.test.js b/deps/npm/tap-snapshots/test-lib-utils-flat-options.js-TAP.test.js index 0e6c053b2f..6890338a13 100644 --- a/deps/npm/tap-snapshots/test-lib-utils-flat-options.js-TAP.test.js +++ b/deps/npm/tap-snapshots/test-lib-utils-flat-options.js-TAP.test.js @@ -7,6 +7,7 @@ 'use strict' exports[`test/lib/utils/flat-options.js TAP basic > flat options 1`] = ` Object { + "_auth": undefined, "@scope:registry": "@scope:registry", "//nerf.dart:_authToken": "//nerf.dart:_authToken", "access": "access", diff --git a/deps/npm/test/lib/adduser.js b/deps/npm/test/lib/adduser.js index 4d2233b18c..22c7c49cfa 100644 --- a/deps/npm/test/lib/adduser.js +++ b/deps/npm/test/lib/adduser.js @@ -13,6 +13,7 @@ const _flatOptions = { let failSave = false let deletedConfig = {} +let registryOutput = '' let setConfig = {} const authDummy = () => Promise.resolve({ message: 'success', @@ -32,7 +33,10 @@ const deleteMock = (key, where) => { } const adduser = requireInject('../../lib/adduser.js', { npmlog: { - disableProgress: () => null + disableProgress: () => null, + notice: (_, msg) => { + registryOutput = msg + }, }, '../../lib/npm.js': { flatOptions: _flatOptions, @@ -69,6 +73,12 @@ test('simple login', (t) => { adduser([], (err) => { t.ifError(err, 'npm adduser') + t.equal( + registryOutput, + 'Log in on https://registry.npmjs.org/', + 'should have correct message result' + ) + t.deepEqual( deletedConfig, { @@ -102,6 +112,7 @@ test('simple login', (t) => { 'should output auth success msg' ) + registryOutput = '' deletedConfig = {} setConfig = {} result = '' diff --git a/deps/npm/test/lib/cache.js b/deps/npm/test/lib/cache.js new file mode 100644 index 0000000000..9c27386ed8 --- /dev/null +++ b/deps/npm/test/lib/cache.js @@ -0,0 +1,232 @@ +const t = require('tap') +const requireInject = require('require-inject') +const path = require('path') + +const usageUtil = () => 'usage instructions' + +const flatOptions = { + force: false +} + +const npm = { + flatOptions, + cache: '/fake/path' +} + +let rimrafPath = '' +const rimraf = (path, cb) => { + rimrafPath = path + return cb() +} + +let logOutput = [] +const npmlog = { + silly: (...args) => { + logOutput.push(['silly', ...args]) + } +} + +let tarballStreamSpec = '' +let tarballStreamOpts = {} +const pacote = { + tarball: { + stream: (spec, cb, opts) => { + tarballStreamSpec = spec + tarballStreamOpts = opts + return cb({ + resume: () => {}, + promise: () => Promise.resolve() + }) + } + } +} + +let outputOutput = [] +const output = (msg) => { + outputOutput.push(msg) +} + +let cacacheVerifyPath = '' +const cacacheVerifyStats = { + keptSize: 100, + verifiedContent: 1, + totalEntries: 1, + runTime: { total: 2000 } +} +const cacache = { + verify: (path) => { + cacacheVerifyPath = path + return cacacheVerifyStats + } +} + +const mocks = { + cacache, + npmlog, + pacote, + rimraf, + '../../lib/npm.js': npm, + '../../lib/utils/output.js': output, + '../../lib/utils/usage.js': usageUtil +} + +const cache = requireInject('../../lib/cache.js', mocks) + +t.test('cache no args', t => { + cache([], err => { + t.equal(err.message, 'usage instructions', 'should throw usage instructions') + t.end() + }) +}) + +t.test('cache clean', t => { + cache(['clean'], err => { + t.match(err.message, 'the npm cache self-heals', 'should throw warning') + t.end() + }) +}) + +t.test('cache clean (force)', t => { + flatOptions.force = true + t.teardown(() => { + rimrafPath = '' + flatOptions.force = false + }) + + cache(['clear'], err => { + t.ifError(err) + t.equal(rimrafPath, path.join(npm.cache, '_cacache')) + t.end() + }) +}) + +t.test('cache clean with arg', t => { + cache(['rm', 'pkg'], err => { + t.match(err.message, 'does not accept arguments', 'should throw error') + t.end() + }) +}) + +t.test('cache add no arg', t => { + t.teardown(() => { + logOutput = [] + }) + + cache(['add'], err => { + t.strictSame(logOutput, [ + ['silly', 'cache add', 'args', []], + ], 'logs correctly') + t.equal(err.code, 'EUSAGE', 'throws usage error') + t.end() + }) +}) + +t.test('cache add pkg only', t => { + t.teardown(() => { + logOutput = [] + tarballStreamSpec = '' + tarballStreamOpts = {} + }) + + cache(['add', 'mypkg'], err => { + t.ifError(err) + t.strictSame(logOutput, [ + ['silly', 'cache add', 'args', ['mypkg']], + ['silly', 'cache add', 'spec', 'mypkg'] + ], 'logs correctly') + t.equal(tarballStreamSpec, 'mypkg', 'passes the correct spec to pacote') + t.same(tarballStreamOpts, flatOptions, 'passes the correct options to pacote') + t.end() + }) +}) + +t.test('cache add pkg w/ spec modifier', t => { + t.teardown(() => { + logOutput = [] + tarballStreamSpec = '' + tarballStreamOpts = {} + }) + + cache(['add', 'mypkg', 'latest'], err => { + t.ifError(err) + t.strictSame(logOutput, [ + ['silly', 'cache add', 'args', ['mypkg', 'latest']], + ['silly', 'cache add', 'spec', 'mypkg@latest'] + ], 'logs correctly') + t.equal(tarballStreamSpec, 'mypkg@latest', 'passes the correct spec to pacote') + t.same(tarballStreamOpts, flatOptions, 'passes the correct options to pacote') + t.end() + }) +}) + +t.test('cache verify', t => { + t.teardown(() => { + outputOutput = [] + cacacheVerifyPath = '' + }) + + cache(['verify'], err => { + t.ifError(err) + t.match(outputOutput, [ + `Cache verified and compressed (${path.join(npm.cache, '_cacache')})`, + 'Content verified: 1 (100 bytes)', + 'Index entries: 1', + 'Finished in 2s' + ], 'prints correct output') + t.end() + }) +}) + +t.test('cache verify w/ extra output', t => { + npm.cache = `${process.env.HOME}/fake/path` + cacacheVerifyStats.badContentCount = 1 + cacacheVerifyStats.reclaimedCount = 2 + cacacheVerifyStats.reclaimedSize = 200 + cacacheVerifyStats.missingContent = 3 + t.teardown(() => { + npm.cache = '/fake/path' + outputOutput = [] + cacacheVerifyPath = '' + delete cacacheVerifyStats.badContentCount + delete cacacheVerifyStats.reclaimedCount + delete cacacheVerifyStats.reclaimedSize + delete cacacheVerifyStats.missingContent + }) + + cache(['check'], err => { + t.ifError(err) + t.match(outputOutput, [ + `Cache verified and compressed (~${path.join('/fake/path', '_cacache')})`, + 'Content verified: 1 (100 bytes)', + 'Corrupted content removed: 1', + 'Content garbage-collected: 2 (200 bytes)', + 'Missing content: 3', + 'Index entries: 1', + 'Finished in 2s' + ], 'prints correct output') + t.end() + }) +}) + +t.test('cache completion', t => { + const { completion } = cache + + const testComp = (argv, expect) => { + completion({ conf: { argv: { remain: argv } } }, (err, res) => { + t.ifError(err) + t.strictSame(res, expect, argv.join(' ')) + }) + } + + testComp(['npm', 'cache'], [ + 'add', + 'clean', + 'verify' + ]) + + testComp(['npm', 'cache', 'add'], []) + testComp(['npm', 'cache', 'clean'], []) + testComp(['npm', 'cache', 'verify'], []) + + t.end() +}) diff --git a/deps/npm/test/lib/ci.js b/deps/npm/test/lib/ci.js index 645fc6aed9..43ad2783b0 100644 --- a/deps/npm/test/lib/ci.js +++ b/deps/npm/test/lib/ci.js @@ -42,6 +42,25 @@ test('should use Arborist', (t) => { }) }) +test('should pass flatOptions to Arborist.reify', (t) => { + const ci = requireInject('../../lib/ci.js', { + '../../lib/npm.js': { + prefix: 'foo', + flatOptions: { + production: true + } + }, + '@npmcli/arborist': function () { + this.loadVirtual = () => Promise.resolve(true) + this.reify = async (options) => { + t.equal(options.production, true, 'should pass flatOptions to Arborist.reify') + t.end() + } + } + }) + ci(null, () => {}) +}) + test('should throw if package-lock.json or npm-shrinkwrap missing', (t) => { const testDir = t.testdir({ 'index.js': 'some contents', diff --git a/deps/npm/test/lib/exec.js b/deps/npm/test/lib/exec.js index fb89776b55..08592353ce 100644 --- a/deps/npm/test/lib/exec.js +++ b/deps/npm/test/lib/exec.js @@ -386,6 +386,75 @@ t.test('npm exec @foo/bar -- --some=arg, locally installed', async t => { }]) }) +t.test('npm exec @foo/bar, with same bin alias and no unscoped named bin, locally installed', async t => { + const foobarManifest = { + name: '@foo/bar', + version: '1.2.3', + bin: { + baz: 'corge', // pick the first one + qux: 'corge', + quux: 'corge', + } + } + const path = t.testdir({ + node_modules: { + '@foo/bar': { + 'package.json': JSON.stringify(foobarManifest) + } + } + }) + npm.localPrefix = path + ARB_ACTUAL_TREE[path] = { + children: new Map([['@foo/bar', { name: '@foo/bar', version: '1.2.3' }]]) + } + MANIFESTS['@foo/bar'] = foobarManifest + await exec(['@foo/bar'], er => { + if (er) { + throw er + } + }) + t.strictSame(MKDIRPS, [], 'no need to make any dirs') + t.match(ARB_CTOR, [ { package: ['@foo/bar'], path } ]) + t.strictSame(ARB_REIFY, [], 'no need to reify anything') + t.equal(PROGRESS_ENABLED, true, 'progress re-enabled') + t.match(RUN_SCRIPTS, [{ + pkg: { scripts: { npx: 'baz' } }, + banner: false, + path: process.cwd(), + stdioString: true, + event: 'npx', + env: { PATH: process.env.PATH }, + stdio: 'inherit' + }]) +}) + +t.test('npm exec @foo/bar, with different bin alias and no unscoped named bin, locally installed', t => { + const path = t.testdir() + npm.localPrefix = path + ARB_ACTUAL_TREE[path] = { + children: new Map([['@foo/bar', { name: '@foo/bar', version: '1.2.3' }]]) + } + MANIFESTS['@foo/bar'] = { + name: '@foo/bar', + version: '1.2.3', + bin: { + foo: 'qux', + corge: 'qux', + baz: 'quux', + }, + _from: 'foo@', + _id: '@foo/bar@1.2.3' + } + return t.rejects(exec(['@foo/bar'], er => { + if (er) { + throw er + } + }), { + message: 'could not determine executable to run', + pkgid: '@foo/bar@1.2.3' + }) +}) + t.test('run command with 2 packages, need install, verify sort', t => { // test both directions, should use same install dir both times // also test the read() call here, verify that the prompts match diff --git a/deps/npm/test/lib/npm.js b/deps/npm/test/lib/npm.js index b2be5543fa..f6a13b90fa 100644 --- a/deps/npm/test/lib/npm.js +++ b/deps/npm/test/lib/npm.js @@ -256,7 +256,10 @@ t.test('npm.load', t => { '--prefix', dir, '--userconfig', `${dir}/.npmrc`, '--usage', - '--scope=foo' + '--scope=foo', + 'token', + 'revoke', + 'blergggg', ] freshConfig() @@ -353,3 +356,91 @@ t.test('loading as main will load the cli', t => { t.end() }) }) + +t.test('set process.title', t => { + const { execPath, argv: processArgv } = process + const { log } = console + const titleDesc = Object.getOwnPropertyDescriptor(process, 'title') + Object.defineProperty(process, 'title', { + value: '', + settable: true, + enumerable: true, + configurable: true, + }) + const consoleLogs = [] + console.log = (...msg) => consoleLogs.push(msg) + + t.teardown(() => { + console.log = log + process.argv = processArgv + Object.defineProperty(process, 'title', titleDesc) + freshConfig() + }) + + t.afterEach(cb => { + consoleLogs.length = 0 + cb() + }) + + t.test('basic title setting', async t => { + freshConfig({ + argv: [ + process.execPath, + process.argv[1], + '--metrics-registry', 'http://example.com', + '--usage', + '--scope=foo', + 'ls', + ], + }) + await npm.load(er => { + if (er) + throw er + t.equal(npm.title, 'npm ls') + t.equal(process.title, 'npm ls') + }) + }) + + t.test('do not expose token being revoked', async t => { + freshConfig({ + argv: [ + process.execPath, + process.argv[1], + '--metrics-registry', 'http://example.com', + '--usage', + '--scope=foo', + 'token', + 'revoke', + 'deadbeefcafebad', + ], + }) + await npm.load(er => { + if (er) + throw er + t.equal(npm.title, 'npm token revoke ***') + t.equal(process.title, 'npm token revoke ***') + }) + }) + + t.test('do show *** unless a token is actually being revoked', async t => { + freshConfig({ + argv: [ + process.execPath, + process.argv[1], + '--metrics-registry', 'http://example.com', + '--usage', + '--scope=foo', + 'token', + 'revoke', + ], + }) + await npm.load(er => { + if (er) + throw er + t.equal(npm.title, 'npm token revoke') + t.equal(process.title, 'npm token revoke') + }) + }) + + t.end() +}) diff --git a/deps/npm/test/lib/run-script.js b/deps/npm/test/lib/run-script.js index 7a034aff01..7ddb6ff6f6 100644 --- a/deps/npm/test/lib/run-script.js +++ b/deps/npm/test/lib/run-script.js @@ -25,9 +25,11 @@ const output = [] const npmlog = { level: 'warn' } const getRS = windows => requireInject('../../lib/run-script.js', { - '@npmcli/run-script': async opts => { + '@npmcli/run-script': Object.assign(async opts => { RUN_SCRIPTS.push(opts) - }, + }, { + isServerPackage: require('@npmcli/run-script').isServerPackage, + }), npmlog, '../../lib/npm.js': npm, '../../lib/utils/is-windows-shell.js': windows, @@ -90,10 +92,29 @@ t.test('fail if no package.json', async t => { await runScript(['test'], er => t.match(er, { code: 'ENOENT' })) }) -t.test('default env and restart scripts', async t => { +t.test('default env, start, and restart scripts', async t => { npm.localPrefix = t.testdir({ - 'package.json': JSON.stringify({ name: 'x', version: '1.2.3' }) + 'package.json': JSON.stringify({ name: 'x', version: '1.2.3' }), + 'server.js': 'console.log("hello, world")', + }) + + await runScript(['start'], er => { + if (er) { + throw er + } + t.match(RUN_SCRIPTS, [ + { + path: npm.localPrefix, + args: [], + scriptShell: undefined, + stdio: 'inherit', + stdioString: true, + pkg: { name: 'x', version: '1.2.3', _id: 'x@1.2.3', scripts: {}}, + event: 'start' + } + ]) }) + RUN_SCRIPTS.length = 0 await runScript(['env'], er => { if (er) { diff --git a/deps/npm/test/lib/utils/error-handler.js b/deps/npm/test/lib/utils/error-handler.js index 840b3a3565..9e32dfc5ff 100644 --- a/deps/npm/test/lib/utils/error-handler.js +++ b/deps/npm/test/lib/utils/error-handler.js @@ -218,8 +218,8 @@ t.test('console.log output using --json', (t) => { config.values.json = true - const _log = console.log - console.log = (jsonOutput) => { + const _error = console.error + console.error = (jsonOutput) => { t.deepEqual( JSON.parse(jsonOutput), { @@ -236,7 +236,7 @@ t.test('console.log output using --json', (t) => { errorHandler(new Error('Error: EBADTHING Something happened')) t.teardown(() => { - console.log = _log + console.error = _error delete config.values.json }) }) diff --git a/deps/npm/test/lib/utils/explain-dep.js b/deps/npm/test/lib/utils/explain-dep.js index e030534865..9a205e3c39 100644 --- a/deps/npm/test/lib/utils/explain-dep.js +++ b/deps/npm/test/lib/utils/explain-dep.js @@ -2,7 +2,7 @@ const t = require('tap') const requireInject = require('require-inject') const npm = {} const { explainNode, printNode } = requireInject('../../../lib/utils/explain-dep.js', { - '../../../lib/npm.js': npm + '../../../lib/npm.js': npm, }) const cases = { @@ -16,10 +16,10 @@ const cases = { name: 'prod-dep', spec: '1.x', from: { - location: '/path/to/project' - } - } - ] + location: '/path/to/project', + }, + }, + ], }, deepDev: { @@ -51,16 +51,16 @@ const cases = { name: 'topdev', spec: '4.x', from: { - location: '/path/to/project' - } - } - ] - } - } - ] - } - } - ] + location: '/path/to/project', + }, + }, + ], + }, + }, + ], + }, + }, + ], }, optional: { @@ -74,10 +74,10 @@ const cases = { name: 'optdep', spec: '1.0.0', from: { - location: '/path/to/project' - } - } - ] + location: '/path/to/project', + }, + }, + ], }, peer: { @@ -91,10 +91,10 @@ const cases = { name: 'peer', spec: '1.0.0', from: { - location: '/path/to/project' - } - } - ] + location: '/path/to/project', + }, + }, + ], }, extraneous: { @@ -102,8 +102,8 @@ const cases = { version: '1337.420.69-lol', location: 'node_modules/extra-neos', dependents: [], - extraneous: true - } + extraneous: true, + }, } cases.manyDeps = { @@ -114,31 +114,39 @@ cases.manyDeps = { type: 'prod', name: 'manydep', spec: '1.0.0', - from: cases.prodDep + from: cases.prodDep, }, { type: 'optional', name: 'manydep', spec: '1.x', - from: cases.optional + from: cases.optional, }, { type: 'prod', name: 'manydep', spec: '1.0.x', - from: cases.extraneous + from: cases.extraneous, }, { type: 'dev', name: 'manydep', spec: '*', - from: cases.deepDev + from: cases.deepDev, }, { type: 'peer', name: 'manydep', spec: '>1.0.0-beta <1.0.1', - from: cases.peer + from: cases.peer, + }, + { + type: 'prod', + name: 'manydep', + spec:'>1.0.0-beta <1.0.1', + from: { + location: '/path/to/project', + }, }, { type: 'prod', @@ -148,9 +156,9 @@ cases.manyDeps = { name: 'a package with a pretty long name', version: '1.2.3', dependents: { - location: '/path/to/project' - } - } + location: '/path/to/project', + }, + }, }, { type: 'prod', @@ -160,9 +168,9 @@ cases.manyDeps = { name: 'another package with a pretty long name', version: '1.2.3', dependents: { - location: '/path/to/project' - } - } + location: '/path/to/project', + }, + }, }, { type: 'prod', @@ -172,14 +180,13 @@ cases.manyDeps = { name: 'yet another a package with a pretty long name', version: '1.2.3', dependents: { - location: '/path/to/project' - } - } + location: '/path/to/project', + }, + }, }, - ] + ], } - for (const [name, expl] of Object.entries(cases)) { t.test(name, t => { npm.color = true diff --git a/deps/npm/test/lib/utils/flat-options.js b/deps/npm/test/lib/utils/flat-options.js index d3b8b89bc8..7601c78d27 100644 --- a/deps/npm/test/lib/utils/flat-options.js +++ b/deps/npm/test/lib/utils/flat-options.js @@ -291,6 +291,18 @@ t.test('various default values and falsey fallbacks', t => { t.end() }) +t.test('legacy _auth token', t => { + const npm = new Mocknpm({ + _auth: 'asdfasdf', + }) + t.strictSame( + flatOptions(npm)._auth, + 'asdfasdf', + 'should set legacy _auth token', + ) + t.end() +}) + t.test('save-type', t => { const base = { 'save-optional': false, |