diff options
author | Ruy Adorno <ruyadorno@hotmail.com> | 2021-03-23 14:58:11 -0400 |
---|---|---|
committer | Ruy Adorno <ruyadorno@hotmail.com> | 2021-03-23 22:10:30 -0400 |
commit | 73b3e06c910549a7fd3c8f49324ab14e0adf2c8d (patch) | |
tree | e7f0ab70d8bb09a6212f8a22da25dc07410e6967 /deps | |
parent | f2090877f1f727020099ef9e30cc70e10b10f900 (diff) | |
download | node-new-73b3e06c910549a7fd3c8f49324ab14e0adf2c8d.tar.gz |
deps: upgrade npm to 7.7.0
PR-URL: https://github.com/nodejs/node/pull/37879
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Diffstat (limited to 'deps')
305 files changed, 14585 insertions, 7996 deletions
diff --git a/deps/npm/AUTHORS b/deps/npm/AUTHORS index 9e5ac7fcaf..9c67cf88ef 100644 --- a/deps/npm/AUTHORS +++ b/deps/npm/AUTHORS @@ -759,3 +759,9 @@ Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Bjørn Johansen <bjjohans@microsoft.com> Fraqe <f@fraqe.ca> Edward Grech <dwardu@gmail.com> +Kenrick <kenrick95@gmail.com> +Karthik Sundari <karthik_sundari@comcast.com> +Jan Sepke <625043+jansepke@users.noreply.github.com> +Augusto Moura <augusto.borgesm@gmail.com> +Eric Chow <eric.zjp.chow@gmail.com> +kbayrhammer <klaus.bayrhammer@redbull.com> diff --git a/deps/npm/CHANGELOG.md b/deps/npm/CHANGELOG.md index 0b20696a89..c11a44734a 100644 --- a/deps/npm/CHANGELOG.md +++ b/deps/npm/CHANGELOG.md @@ -1,3 +1,79 @@ +## v7.7.0 (2021-03-23) + +### FEATURES + +* [`33c4189f9`](https://github.com/npm/cli/commit/33c4189f939aebdfaf85ea419e6ea01d0977b79d) + [#2864](https://github.com/npm/cli/issues/2864) + add `npm run-script` workspaces support + ([@ruyadorno](https://github.com/ruyadorno)) +* [`e1b3b318f`](https://github.com/npm/cli/commit/e1b3b318f095a7e1a7cc4b131907de4955275d9d) + [#2886](https://github.com/npm/cli/issues/2886) + add `npm exec` workspaces support + ([@ruyadorno](https://github.com/ruyadorno)) +* [`41facf643`](https://github.com/npm/cli/commit/41facf6435ced4e416d74111d9c3ff00ee19ab7d) + [#2859](https://github.com/npm/cli/issues/2859) + expanded "Did you mean?" suggestions for missing cmds and scripts + ([@wraithgar](https://github.com/wraithgar)) + +### BUG FIXES + +* [`8cce4282f`](https://github.com/npm/cli/commit/8cce4282f7bef11aeeb73cffd532b477b241985e) + [#2865](https://github.com/npm/cli/issues/2865) + `npm publish`: handle case where multiple config list is present + ([@kenrick95](https://github.com/kenrick95)) +* [`6598bfe86`](https://github.com/npm/cli/commit/6598bfe8697439e827d84981f8504febca64a55a) + mark deprecated configs + ([@isaacs](https://github.com/isaacs)) +* [`8a38afe77`](https://github.com/npm/cli/commit/8a38afe779ce71a10178ed62b13709d06adf7a66) + [#2881](https://github.com/npm/cli/issues/2881) + docs(package-json): document default main behavior + ([@klausbayrhammer](https://github.com/klausbayrhammer)) +* [`93a061d73`](https://github.com/npm/cli/commit/93a061d737dc769663652368e8586e4202267b9e) + [#2917](https://github.com/npm/cli/issues/2917) + add action items to `npm run` error output + ([@wraithgar](https://github.com/wraithgar)) + +### DOCUMENTATION + +* [`ad65bd910`](https://github.com/npm/cli/commit/ad65bd9101aa8e8b94bc1e48df3ef93deca6d30c) + [#2860](https://github.com/npm/cli/issues/2860) + fix link in configuring-npm + ([@varmakarthik12](https://github.com/varmakarthik12)) +* [`b419bfb02`](https://github.com/npm/cli/commit/b419bfb0259596fb338d45b2eaeab25a7a0d1f1e) + [#2876](https://github.com/npm/cli/issues/2876) + fix test-coverage command in contributing guide + ([@chowkapow](https://github.com/chowkapow)) + +### DEPENDENCIES + +* [`7b5606b93`](https://github.com/npm/cli/commit/7b5606b931083e8a70f5ea094c2b46f0b7a38a18) + `@npmcli/arborist@2.2.9` + * [#254](https://github.com/npm/arborist/pull/254) Honor explicit + prefix when saving dependencies + ([@jameschensmith](https://github.com/jameschensmith)) + * [#255](https://github.com/npm/arborist/pull/255) Never save to + `bundleDependencies` when saving a `peer` or `peerOptional` + dependency. ([@isaacs](https://github.com/isaacs)) +* [`f76e7c21f`](https://github.com/npm/cli/commit/f76e7c21ffd87b08593d8c396a78ab9c5fa790bd) + `pacote@11.3.1` + * increases tarball compression level +* [`4928512bc`](https://github.com/npm/cli/commit/4928512bcefd8448ff5852978cfc7f903e3ae996) + `semver@7.3.5` + * fix handling prereleases/ANY ranges in subset +* [`1924eb457`](https://github.com/npm/cli/commit/1924eb457aea7c93dfaf4a911355a63d84d66eee) + `libnpmversion@1.0.12` + * fix removing undescored-prefixed package.json properties in `npm version` +* [`916623056`](https://github.com/npm/cli/commit/91662305643509eebd2f79ed7e3ff01562aa4968) + `@npmcli/run-script@1.8.4` + * fix expanding windows-style environment variables +* [`a8d0751e4`](https://github.com/npm/cli/commit/a8d0751e4b7c7d8b808c8a49f288fc7272f729b0) + `npm-pick-manifest@6.1.1` + * fix running packages with a single executable binary with `npm exec` +* [`af7eaac50`](https://github.com/npm/cli/commit/af7eaac5018ed821d72d43d08f1d7e49e7491453) + `hosted-git-info@4.0.1` +* [`f52c51db1`](https://github.com/npm/cli/commit/f52c51db13c39cfbaed18dbd13ba7302a4b6a0d9) + `@npmcli/config@2.0.0` + ## v7.6.3 (2021-03-11) ### DOCUMENTATION diff --git a/deps/npm/CONTRIBUTING.md b/deps/npm/CONTRIBUTING.md index 5198918f01..4116f4e71d 100644 --- a/deps/npm/CONTRIBUTING.md +++ b/deps/npm/CONTRIBUTING.md @@ -38,7 +38,7 @@ We expect that every new feature or bug fix comes with corresponding tests that **You can find out what the current test coverage percentage is by running...** ```bash -$ npm run test-coverage +$ npm run check-coverage ``` ## Performance & Benchmarks diff --git a/deps/npm/README.md b/deps/npm/README.md index 8a649847ec..01de9e8f69 100644 --- a/deps/npm/README.md +++ b/deps/npm/README.md @@ -28,6 +28,7 @@ If you're looking to manage multiple versions of **`node`** &/or **`npm`**, cons * [**`n`**](https://github.com/tj/n) * [**`volta`**](https://github.com/volta-cli/volta) * [**`nodenv`**](https://github.com/nodenv/nodenv) +* [**`asdf-nodejs`**](https://github.com/asdf-vm/asdf-nodejs) ### Usage diff --git a/deps/npm/bin/npx-cli.js b/deps/npm/bin/npx-cli.js index f4a419972f..a495090c64 100755 --- a/deps/npm/bin/npx-cli.js +++ b/deps/npm/bin/npx-cli.js @@ -24,11 +24,11 @@ const removed = new Set([ ...removedOpts ]) -const { types, shorthands } = require('../lib/utils/config.js') -const npmSwitches = Object.entries(types) - .filter(([key, type]) => type === Boolean || +const { definitions, shorthands } = require('../lib/utils/config/index.js') +const npmSwitches = Object.entries(definitions) + .filter(([key, {type}]) => type === Boolean || (Array.isArray(type) && type.includes(Boolean))) - .map(([key, type]) => key) + .map(([key]) => key) // things that don't take a value const switches = new Set([ diff --git a/deps/npm/docs/content/commands/npm-adduser.md b/deps/npm/docs/content/commands/npm-adduser.md index 7960869ad3..d0ddd68c25 100644 --- a/deps/npm/docs/content/commands/npm-adduser.md +++ b/deps/npm/docs/content/commands/npm-adduser.md @@ -12,6 +12,8 @@ npm adduser [--registry=url] [--scope=@orgname] [--always-auth] [--auth-type=leg aliases: login, add-user ``` +Note: This command is unaware of workspaces. + ### Description Create or verify a user named `<username>` in the specified registry, and diff --git a/deps/npm/docs/content/commands/npm-bin.md b/deps/npm/docs/content/commands/npm-bin.md index 4303040e78..c835784f67 100644 --- a/deps/npm/docs/content/commands/npm-bin.md +++ b/deps/npm/docs/content/commands/npm-bin.md @@ -10,6 +10,8 @@ description: Display npm bin folder npm bin [-g|--global] ``` +Note: This command is unaware of workspaces. + ### Description Print the folder where npm will install executables. diff --git a/deps/npm/docs/content/commands/npm-cache.md b/deps/npm/docs/content/commands/npm-cache.md index 13386f2c4a..bcc2989b7d 100644 --- a/deps/npm/docs/content/commands/npm-cache.md +++ b/deps/npm/docs/content/commands/npm-cache.md @@ -18,6 +18,8 @@ aliases: npm cache clear, npm cache rm npm cache verify ``` +Note: This command is unaware of workspaces. + ### Description Used to add, list, or clean the npm cache folder. diff --git a/deps/npm/docs/content/commands/npm-completion.md b/deps/npm/docs/content/commands/npm-completion.md index 53737c8033..9dbd960913 100644 --- a/deps/npm/docs/content/commands/npm-completion.md +++ b/deps/npm/docs/content/commands/npm-completion.md @@ -10,6 +10,8 @@ description: Tab Completion for npm source <(npm completion) ``` +Note: This command is unaware of workspaces. + ### Description Enables tab-completion in all npm commands. diff --git a/deps/npm/docs/content/commands/npm-config.md b/deps/npm/docs/content/commands/npm-config.md index 51caa5a61b..31629a6b7d 100644 --- a/deps/npm/docs/content/commands/npm-config.md +++ b/deps/npm/docs/content/commands/npm-config.md @@ -18,6 +18,8 @@ npm get [<key> [<key> ...]] alias: c ``` +Note: This command is unaware of workspaces. + ### Description npm gets its config settings from the command line, environment diff --git a/deps/npm/docs/content/commands/npm-dedupe.md b/deps/npm/docs/content/commands/npm-dedupe.md index 9b14e99dd1..c6d26126d3 100644 --- a/deps/npm/docs/content/commands/npm-dedupe.md +++ b/deps/npm/docs/content/commands/npm-dedupe.md @@ -1,7 +1,7 @@ --- title: npm-dedupe section: 1 -description: Reduce duplication +description: Reduce duplication in the package tree --- ### Synopsis @@ -10,7 +10,7 @@ description: Reduce duplication npm dedupe npm ddp -aliases: find-dupes, ddp +aliases: ddp ``` ### Description @@ -74,6 +74,7 @@ Using `npm find-dupes` will run the command in `--dry-run` mode. ### See Also +* [npm find-dupes](/cli-commands/find-dupes) * [npm ls](/cli-commands/ls) * [npm update](/cli-commands/update) * [npm install](/cli-commands/install) diff --git a/deps/npm/docs/content/commands/npm-deprecate.md b/deps/npm/docs/content/commands/npm-deprecate.md index 139441856b..0603797661 100644 --- a/deps/npm/docs/content/commands/npm-deprecate.md +++ b/deps/npm/docs/content/commands/npm-deprecate.md @@ -10,6 +10,8 @@ description: Deprecate a version of a package npm deprecate <pkg>[@<version range>] <message> ``` +Note: This command is unaware of workspaces. + ### Description This command will update the npm registry entry for a package, providing a diff --git a/deps/npm/docs/content/commands/npm-doctor.md b/deps/npm/docs/content/commands/npm-doctor.md index 2aceee2390..9416818a40 100644 --- a/deps/npm/docs/content/commands/npm-doctor.md +++ b/deps/npm/docs/content/commands/npm-doctor.md @@ -10,6 +10,8 @@ description: Check your npm environment npm doctor ``` +Note: This command is unaware of workspaces. + ### Description `npm doctor` runs a set of checks to ensure that your npm installation has diff --git a/deps/npm/docs/content/commands/npm-edit.md b/deps/npm/docs/content/commands/npm-edit.md index 40fac04085..20788aafb6 100644 --- a/deps/npm/docs/content/commands/npm-edit.md +++ b/deps/npm/docs/content/commands/npm-edit.md @@ -10,6 +10,8 @@ description: Edit an installed package npm edit <pkg> ``` +Note: This command is unaware of workspaces. + ### Description Selects a dependency in the current project and opens the package folder in diff --git a/deps/npm/docs/content/commands/npm-exec.md b/deps/npm/docs/content/commands/npm-exec.md index cb3e51c825..88b98e3bce 100644 --- a/deps/npm/docs/content/commands/npm-exec.md +++ b/deps/npm/docs/content/commands/npm-exec.md @@ -11,6 +11,7 @@ npm exec -- <pkg>[@<version>] [args...] npm exec --package=<pkg>[@<version>] -- <cmd> [args...] npm exec -c '<cmd> [args...]' npm exec --package=foo -c '<cmd> [args...]' +npm exec [-ws] [-w <workspace-name] [args...] npx <pkg>[@<specifier>] [args...] npx -p <pkg>[@<specifier>] <cmd> [args...] @@ -145,6 +146,68 @@ $ npm x -c 'eslint && say "hooray, lint passed"' $ npx -c 'eslint && say "hooray, lint passed"' ``` +### Workspaces support + +You may use the `workspace` or `workspaces` configs in order to run an +arbitrary command from an npm package (either one installed locally, or fetched +remotely) in the context of the specified workspaces. +If no positional argument or `--call` option is provided, it will open an +interactive subshell in the context of each of these configured workspaces one +at a time. + +Given a project with configured workspaces, e.g: + +``` +. ++-- package.json +`-- packages + +-- a + | `-- package.json + +-- b + | `-- package.json + `-- c + `-- package.json +``` + +Assuming the workspace configuration is properly set up at the root level +`package.json` file. e.g: + +``` +{ + "workspaces": [ "./packages/*" ] +} +``` + +You can execute an arbitrary command from a package in the context of each of +the configured workspaces when using the `workspaces` configuration options, +in this example we're using **eslint** to lint any js file found within each +workspace folder: + +``` +npm exec -ws -- eslint ./*.js +``` + +#### Filtering workspaces + +It's also possible to execute a command in a single workspace using the +`workspace` config along with a name or directory path: + +``` +npm exec --workspace=a -- eslint ./*.js +``` + +The `workspace` config can also be specified multiple times in order to run a +specific script in the context of multiple workspaces. When defining values for +the `workspace` config in the command line, it also possible to use `-w` as a +shorthand, e.g: + +``` +npm exec -w a -w b -- eslint ./*.js +``` + +This last command will run the `eslint` command in both `./packages/a` and +`./packages/b` folders. + ### Compatibility with Older npx Versions The `npx` binary was rewritten in npm v7.0.0, and the standalone `npx` @@ -195,6 +258,30 @@ requested from the server. To force full offline mode, use `offline`. Forces full offline mode. Any packages not locally cached will result in an error. +#### workspace + +* Alias: `-w` +* Type: Array +* Default: `[]` + +Enable running scripts in the context of workspaces while also filtering by +the provided names or paths provided. + +Valid values for the `workspace` config are either: +- Workspace names +- Path to a workspace directory +- Path to a parent workspace directory (will result to selecting all of the +children workspaces) + +#### workspaces + +* Alias: `-ws` +* Type: Boolean +* Default: `false` + +Run scripts in the context of all configured workspaces for the current +project. + ### See Also * [npm run-script](/commands/npm-run-script) diff --git a/deps/npm/docs/content/commands/npm-explore.md b/deps/npm/docs/content/commands/npm-explore.md index e467a75575..7e2004b84c 100644 --- a/deps/npm/docs/content/commands/npm-explore.md +++ b/deps/npm/docs/content/commands/npm-explore.md @@ -10,6 +10,8 @@ description: Browse an installed package npm explore <pkg> [ -- <command>] ``` +Note: This command is unaware of workspaces. + ### Description Spawn a subshell in the directory of the installed package specified. diff --git a/deps/npm/docs/content/commands/npm-find-dupes.md b/deps/npm/docs/content/commands/npm-find-dupes.md new file mode 100644 index 0000000000..e098cf47f4 --- /dev/null +++ b/deps/npm/docs/content/commands/npm-find-dupes.md @@ -0,0 +1,23 @@ +--- +title: npm-find-dupes +section: 1 +description: Find duplication in the package tree +--- + +### Synopsis + +```bash +npm find-dupes +``` + +### Description + +Runs `npm dedupe` in `--dry-run` mode, making npm only output the +duplications, without actually changing the package tree. + +### See Also + +* [npm dedupe](/cli-commands/dedupe) +* [npm ls](/cli-commands/ls) +* [npm update](/cli-commands/update) +* [npm install](/cli-commands/install) diff --git a/deps/npm/docs/content/commands/npm-help-search.md b/deps/npm/docs/content/commands/npm-help-search.md index e10638efa0..51c7b43fb5 100644 --- a/deps/npm/docs/content/commands/npm-help-search.md +++ b/deps/npm/docs/content/commands/npm-help-search.md @@ -10,6 +10,8 @@ description: Search npm help documentation npm help-search <text> ``` +Note: This command is unaware of workspaces. + ### Description This command will search the npm markdown documentation files for the terms diff --git a/deps/npm/docs/content/commands/npm-help.md b/deps/npm/docs/content/commands/npm-help.md index 56e4664552..57c5efc8ed 100644 --- a/deps/npm/docs/content/commands/npm-help.md +++ b/deps/npm/docs/content/commands/npm-help.md @@ -10,6 +10,8 @@ description: Get help on npm npm help <term> [<terms..>] ``` +Note: This command is unaware of workspaces. + ### Description If supplied a topic, then show the appropriate documentation page. diff --git a/deps/npm/docs/content/commands/npm-hook.md b/deps/npm/docs/content/commands/npm-hook.md index 2ac548ada0..6effc9b7d2 100644 --- a/deps/npm/docs/content/commands/npm-hook.md +++ b/deps/npm/docs/content/commands/npm-hook.md @@ -13,6 +13,8 @@ npm hook update <id> <url> [secret] npm hook rm <id> ``` +Note: This command is unaware of workspaces. + ### Description Allows you to manage [npm diff --git a/deps/npm/docs/content/commands/npm-init.md b/deps/npm/docs/content/commands/npm-init.md index 8a40d90e83..4b0b8c4c43 100644 --- a/deps/npm/docs/content/commands/npm-init.md +++ b/deps/npm/docs/content/commands/npm-init.md @@ -1,7 +1,7 @@ --- title: npm-init section: 1 -description: create a package.json file +description: Create a package.json file --- ### Synopsis diff --git a/deps/npm/docs/content/commands/npm-logout.md b/deps/npm/docs/content/commands/npm-logout.md index 7fa858a999..1172a3f0f5 100644 --- a/deps/npm/docs/content/commands/npm-logout.md +++ b/deps/npm/docs/content/commands/npm-logout.md @@ -10,6 +10,8 @@ description: Log out of the registry npm logout [--registry=<url>] [--scope=<@scope>] ``` +Note: This command is unaware of workspaces. + ### Description When logged into a registry that supports token-based authentication, tell diff --git a/deps/npm/docs/content/commands/npm-org.md b/deps/npm/docs/content/commands/npm-org.md index 18047d109c..384f5b99fd 100644 --- a/deps/npm/docs/content/commands/npm-org.md +++ b/deps/npm/docs/content/commands/npm-org.md @@ -12,6 +12,8 @@ npm org rm <orgname> <username> npm org ls <orgname> [<username>] ``` +Note: This command is unaware of workspaces. + ### Example Add a new developer to an org: diff --git a/deps/npm/docs/content/commands/npm-owner.md b/deps/npm/docs/content/commands/npm-owner.md index 69eba56afd..b30bbc8dc6 100644 --- a/deps/npm/docs/content/commands/npm-owner.md +++ b/deps/npm/docs/content/commands/npm-owner.md @@ -14,6 +14,8 @@ npm owner ls [<@scope>/]<pkg> aliases: author ``` +Note: This command is unaware of workspaces. + ### Description Manage ownership of published packages. diff --git a/deps/npm/docs/content/commands/npm-ping.md b/deps/npm/docs/content/commands/npm-ping.md index 8de06aa184..f640bf060c 100644 --- a/deps/npm/docs/content/commands/npm-ping.md +++ b/deps/npm/docs/content/commands/npm-ping.md @@ -10,6 +10,8 @@ description: Ping npm registry npm ping [--registry <registry>] ``` +Note: This command is unaware of workspaces. + ### Description Ping the configured or given npm registry and verify authentication. diff --git a/deps/npm/docs/content/commands/npm-prefix.md b/deps/npm/docs/content/commands/npm-prefix.md index 9c33bb1890..4e3edf1902 100644 --- a/deps/npm/docs/content/commands/npm-prefix.md +++ b/deps/npm/docs/content/commands/npm-prefix.md @@ -10,6 +10,8 @@ description: Display prefix npm prefix [-g] ``` +Note: This command is unaware of workspaces. + ### Description Print the local prefix to standard output. This is the closest parent directory diff --git a/deps/npm/docs/content/commands/npm-profile.md b/deps/npm/docs/content/commands/npm-profile.md index 88edf26d87..b4e2fdaee6 100644 --- a/deps/npm/docs/content/commands/npm-profile.md +++ b/deps/npm/docs/content/commands/npm-profile.md @@ -14,6 +14,8 @@ npm profile enable-2fa [auth-and-writes|auth-only] npm profile disable-2fa ``` +Note: This command is unaware of workspaces. + ### Description Change your profile information on the registry. Note that this command diff --git a/deps/npm/docs/content/commands/npm-run-script.md b/deps/npm/docs/content/commands/npm-run-script.md index 8b89435e1a..076dfd7add 100644 --- a/deps/npm/docs/content/commands/npm-run-script.md +++ b/deps/npm/docs/content/commands/npm-run-script.md @@ -8,6 +8,8 @@ description: Run arbitrary package scripts ```bash npm run-script <command> [--if-present] [--silent] [-- <args>] +npm run-script <command> [--workspace=<workspace-name>] +npm run-script <command> [--workspaces] aliases: run, rum, urn ``` @@ -78,6 +80,65 @@ If you try to run a script without having a `node_modules` directory and it fails, you will be given a warning to run `npm install`, just in case you've forgotten. +### Workspaces support + +You may use the `workspace` or `workspaces` configs in order to run an +arbitrary command from a package's `"scripts"` object in the context of the +specified workspaces. If no `"command"` is provided, it will list the available +scripts for each of these configured workspaces. + +Given a project with configured workspaces, e.g: + +``` +. ++-- package.json +`-- packages + +-- a + | `-- package.json + +-- b + | `-- package.json + `-- c + `-- package.json +``` + +Assuming the workspace configuration is properly set up at the root level +`package.json` file. e.g: + +``` +{ + "workspaces": [ "./packages/*" ] +} +``` + +And that each of the configured workspaces has a configured `test` script, +we can run tests in all of them using the `workspaces` config: + +``` +npm test --workspaces +``` + +#### Filtering workspaces + +It's also possible to run a script in a single workspace using the `workspace` +config along with a name or directory path: + +``` +npm test --workspace=a +``` + +The `workspace` config can also be specified multiple times in order to run a +specific script in the context of multiple workspaces. When defining values for +the `workspace` config in the command line, it also possible to use `-w` as a +shorthand, e.g: + +``` +npm test -w a -w b +``` + +This last command will run `test` in both `./packages/a` and `./packages/b` +packages. + + ### Configuration #### if-present @@ -111,6 +172,30 @@ to `/bin/sh` on Unix, defaults to `env.comspec` or `cmd.exe` on Windows. You can use the `--silent` flag to prevent showing `npm ERR!` output on error. +#### workspace + +* Alias: `-w` +* Type: Array +* Default: `[]` + +Enable running scripts in the context of workspaces while also filtering by +the provided names or paths provided. + +Valid values for the `workspace` config are either: +- Workspace names +- Path to a workspace directory +- Path to a parent workspace directory (will result to selecting all of the +children workspaces) + +#### workspaces + +* Alias: `-ws` +* Type: Boolean +* Default: `false` + +Run scripts in the context of all configured workspaces for the current +project. + ### See Also * [npm scripts](/using-npm/scripts) diff --git a/deps/npm/docs/content/commands/npm-search.md b/deps/npm/docs/content/commands/npm-search.md index 35178bcb0a..046c9334ff 100644 --- a/deps/npm/docs/content/commands/npm-search.md +++ b/deps/npm/docs/content/commands/npm-search.md @@ -12,6 +12,8 @@ npm search [-l|--long] [--json] [--parseable] [--no-description] [search terms . aliases: s, se, find ``` +Note: This command is unaware of workspaces. + ### Description Search the registry for packages matching the search terms. `npm search` diff --git a/deps/npm/docs/content/commands/npm-shrinkwrap.md b/deps/npm/docs/content/commands/npm-shrinkwrap.md index dce50b7843..6786229469 100644 --- a/deps/npm/docs/content/commands/npm-shrinkwrap.md +++ b/deps/npm/docs/content/commands/npm-shrinkwrap.md @@ -10,6 +10,8 @@ description: Lock down dependency versions for publication npm shrinkwrap ``` +Note: This command is unaware of workspaces. + ### Description This command repurposes `package-lock.json` into a publishable diff --git a/deps/npm/docs/content/commands/npm-star.md b/deps/npm/docs/content/commands/npm-star.md index aab6e10774..e624b92480 100644 --- a/deps/npm/docs/content/commands/npm-star.md +++ b/deps/npm/docs/content/commands/npm-star.md @@ -10,6 +10,8 @@ description: Mark your favorite packages npm star [<pkg>...] ``` +Note: This command is unaware of workspaces. + ### Description "Starring" a package means that you have some interest in it. It's diff --git a/deps/npm/docs/content/commands/npm-stars.md b/deps/npm/docs/content/commands/npm-stars.md index dab11bc669..80217ee044 100644 --- a/deps/npm/docs/content/commands/npm-stars.md +++ b/deps/npm/docs/content/commands/npm-stars.md @@ -9,6 +9,8 @@ description: View packages marked as favorites npm stars [<user>] ``` +Note: This command is unaware of workspaces. + ### Description If you have starred a lot of neat things and want to find them again diff --git a/deps/npm/docs/content/commands/npm-team.md b/deps/npm/docs/content/commands/npm-team.md index 96aacd8ae9..04e1d7f9eb 100644 --- a/deps/npm/docs/content/commands/npm-team.md +++ b/deps/npm/docs/content/commands/npm-team.md @@ -16,6 +16,8 @@ npm team rm <scope:team> <user> npm team ls <scope>|<scope:team> ``` +Note: This command is unaware of workspaces. + ### Description Used to manage teams in organizations, and change team memberships. Does not diff --git a/deps/npm/docs/content/commands/npm-token.md b/deps/npm/docs/content/commands/npm-token.md index 6520794537..bafc7fc45c 100644 --- a/deps/npm/docs/content/commands/npm-token.md +++ b/deps/npm/docs/content/commands/npm-token.md @@ -9,7 +9,9 @@ description: Manage your authentication tokens npm token list [--json|--parseable] npm token create [--read-only] [--cidr=1.1.1.1/24,2.2.2.2/16] npm token revoke <id|token> - ``` +``` + +Note: This command is unaware of workspaces. ### Description diff --git a/deps/npm/docs/content/commands/npm-unstar.md b/deps/npm/docs/content/commands/npm-unstar.md index 5471d90800..bad1917593 100644 --- a/deps/npm/docs/content/commands/npm-unstar.md +++ b/deps/npm/docs/content/commands/npm-unstar.md @@ -10,6 +10,8 @@ description: Remove an item from your favorite packages npm unstar [<pkg>...] ``` +Note: This command is unaware of workspaces. + ### Description "Unstarring" a package is the opposite of [`npm star`](/commands/npm-star), diff --git a/deps/npm/docs/content/commands/npm-whoami.md b/deps/npm/docs/content/commands/npm-whoami.md index 43b301c517..892adeea3d 100644 --- a/deps/npm/docs/content/commands/npm-whoami.md +++ b/deps/npm/docs/content/commands/npm-whoami.md @@ -10,6 +10,8 @@ description: Display npm username npm whoami [--registry <registry>] ``` +Note: This command is unaware of workspaces. + ### Description Print the `username` config to standard output. diff --git a/deps/npm/docs/content/configuring-npm/package-json.md b/deps/npm/docs/content/configuring-npm/package-json.md index 4b3fd2ba93..f3a186f436 100644 --- a/deps/npm/docs/content/configuring-npm/package-json.md +++ b/deps/npm/docs/content/configuring-npm/package-json.md @@ -325,6 +325,8 @@ This should be a module relative to the root of your package folder. For most modules, it makes the most sense to have a main script and often not much else. +If `main` is not set it defaults to `index.js` in the packages root folder. + ### browser If your module is meant to be used client-side the browser field should be @@ -562,8 +564,7 @@ tarball or git URL. **Please do not put test harnesses or transpilers or other "development" time tools in your `dependencies` object.** See `devDependencies`, below. -See [semver]([/using-npm/semver](https://github.com/npm/node-semver#versions)) -for more details about specifying version ranges. +See [semver](/using-npm/semver#versions) for more details about specifying version ranges. * `version` Must match `version` exactly * `>version` Must be greater than `version` diff --git a/deps/npm/docs/content/using-npm/config.md b/deps/npm/docs/content/using-npm/config.md index 1032adafbe..da69ad4632 100644 --- a/deps/npm/docs/content/using-npm/config.md +++ b/deps/npm/docs/content/using-npm/config.md @@ -59,30 +59,48 @@ internal to npm, and are defaults if nothing else is specified. The following shorthands are parsed on the command-line: -* `-v`: `--version` -* `-h`, `-?`, `--help`, `-H`: `--usage` -* `-s`, `--silent`: `--loglevel silent` -* `-q`, `--quiet`: `--loglevel warn` -* `-d`: `--loglevel info` -* `-dd`, `--verbose`: `--loglevel verbose` -* `-ddd`: `--loglevel silly` +<!-- AUTOGENERATED CONFIG SHORTHANDS START --> +<!-- automatically generated, do not edit manually --> +* `-a`: `--all` +* `--enjoy-by`: `--before` +* `-c`: `--call` +* `--desc`: `--description` +* `-f`: `--force` * `-g`: `--global` -* `-C`: `--prefix` +* `-d`: `--loglevel info` +* `-s`: `--loglevel silent` +* `--silent`: `--loglevel silent` +* `--ddd`: `--loglevel silly` +* `--dd`: `--loglevel verbose` +* `--verbose`: `--loglevel verbose` +* `-q`: `--loglevel warn` +* `--quiet`: `--loglevel warn` * `-l`: `--long` * `-m`: `--message` -* `-p`, `--porcelain`: `--parseable` -* `-reg`: `--registry` -* `-f`: `--force` -* `-desc`: `--description` +* `--local`: `--no-global` +* `-n`: `--no-yes` +* `--no`: `--no-yes` +* `-p`: `--parseable` +* `--porcelain`: `--parseable` +* `-C`: `--prefix` +* `--readonly`: `--read-only` +* `--reg`: `--registry` * `-S`: `--save` -* `-P`: `--save-prod` -* `-D`: `--save-dev` -* `-O`: `--save-optional` * `-B`: `--save-bundle` +* `-D`: `--save-dev` * `-E`: `--save-exact` +* `-O`: `--save-optional` +* `-P`: `--save-prod` +* `-?`: `--usage` +* `-h`: `--usage` +* `-H`: `--usage` +* `--help`: `--usage` +* `-v`: `--version` +* `-w`: `--workspace` +* `--ws`: `--workspaces` * `-y`: `--yes` -* `-n`: `--yes false` -* `ll` and `la` commands: `ls --long` + +<!-- AUTOGENERATED CONFIG SHORTHANDS END --> If the specified configuration param resolves unambiguously to a known configuration parameter, then it is expanded to that configuration @@ -107,26 +125,39 @@ npm ls --global --parseable --long --loglevel info ### Config Settings -#### access +<!-- AUTOGENERATED CONFIG DESCRIPTIONS START --> +<!-- automatically generated, do not edit manually --> +#### `_auth` + +* Default: null +* Type: null or String + +A basic-auth string to use when authenticating against the npm registry. + +Warning: This should generally not be set via a command-line option. It is +safer to use a registry-provided authentication bearer token stored in the +~/.npmrc file by running `npm login`. -* Default: `restricted` -* Type: Access +#### `access` -When publishing scoped packages, the access level defaults to `restricted`. If -you want your scoped package to be publicly viewable (and installable) set -`--access=public`. The only valid values for `access` are `public` and +* Default: 'restricted' for scoped packages, 'public' for unscoped packages +* Type: null, "restricted", or "public" + +When publishing scoped packages, the access level defaults to `restricted`. +If you want your scoped package to be publicly viewable (and installable) +set `--access=public`. The only valid values for `access` are `public` and `restricted`. Unscoped packages _always_ have an access level of `public`. -#### all +#### `all` -* Default: `false` +* Default: false * Type: Boolean When running `npm outdated` and `npm ls`, setting `--all` will show all outdated or installed packages, rather than only those directly depended upon by the current project. -#### allow-same-version +#### `allow-same-version` * Default: false * Type: Boolean @@ -134,78 +165,62 @@ upon by the current project. Prevents throwing an error when `npm version` is used to set the new version to the same value as the current version. -#### always-auth +#### `always-auth` * Default: false * Type: Boolean -Force npm to always require authentication when accessing the registry, -even for `GET` requests. - -#### also - -* Default: null -* Type: String - -When "dev" or "development" and running local `npm shrinkwrap`, -`npm outdated`, or `npm update`, is an alias for `--dev`. +Force npm to always require authentication when accessing the registry, even +for `GET` requests. -#### audit +#### `audit` * Default: true * Type: Boolean When "true" submit audit reports alongside `npm install` runs to the default -registry and all registries configured for scopes. See the documentation -for [`npm audit`](/commands/npm-audit) for details on what is submitted. - -#### audit-level - -* Default: `"low"` -* Type: `'low'`, `'moderate'`, `'high'`, `'critical'` - -The minimum level of vulnerability for `npm audit` to exit with -a non-zero exit code. +registry and all registries configured for scopes. See the documentation for +[`npm audit`](/commands/npm-audit) for details on what is submitted. -#### auth-type +#### `audit-level` -* Default: `'legacy'` -* Type: `'legacy'`, `'sso'`, `'saml'`, `'oauth'` +* Default: null +* Type: "low", "moderate", "high", "critical", "none", or null -What authentication strategy to use with `adduser`/`login`. +The minimum level of vulnerability for `npm audit` to exit with a non-zero +exit code. -#### before +#### `before` -* Alias: enjoy-by * Default: null -* Type: Date +* Type: null or Date -If passed to `npm install`, will rebuild the npm tree such that only versions -that were available **on or before** the `--before` time get installed. -If there's no versions available for the current set of direct dependencies, the -command will error. +If passed to `npm install`, will rebuild the npm tree such that only +versions that were available **on or before** the `--before` time get +installed. If there's no versions available for the current set of direct +dependencies, the command will error. If the requested version is a `dist-tag` and the given tag does not pass the -`--before` filter, the most recent version less than or equal to that tag will -be used. For example, `foo@latest` might install `foo@1.2` even though `latest` -is `2.0`. +`--before` filter, the most recent version less than or equal to that tag +will be used. For example, `foo@latest` might install `foo@1.2` even though +`latest` is `2.0`. -#### bin-links +#### `bin-links` -* Default: `true` +* Default: true * Type: Boolean Tells npm to create symlinks (or `.cmd` shims on Windows) for package executables. -Set to false to have it not do this. This can be used to work around -the fact that some file systems don't support symlinks, even on -ostensibly Unix systems. +Set to false to have it not do this. This can be used to work around the +fact that some file systems don't support symlinks, even on ostensibly Unix +systems. -#### browser +#### `browser` * Default: OS X: `"open"`, Windows: `"start"`, Others: `"xdg-open"` -* Type: String or Boolean +* Type: null, Boolean, or String The browser that is called by npm commands to open websites. @@ -214,87 +229,50 @@ terminal. Set to `true` to use default system URL opener. -#### ca +#### `ca` -* Default: The npm CA certificate -* Type: String, Array or null +* Default: null +* Type: null or String (can be set multiple times) The Certificate Authority signing certificate that is trusted for SSL -connections to the registry. Values should be in PEM format (Windows calls it "Base-64 encoded X.509 (.CER)") with newlines -replaced by the string "\n". For example: +connections to the registry. Values should be in PEM format (Windows calls +it "Base-64 encoded X.509 (.CER)") with newlines replaced by the string +"\n". For example: -```bash +```ini ca="-----BEGIN CERTIFICATE-----\nXXXX\nXXXX\n-----END CERTIFICATE-----" ``` -Set to `null` to only allow "known" registrars, or to a specific CA cert -to trust only that specific signing authority. +Set to `null` to only allow "known" registrars, or to a specific CA cert to +trust only that specific signing authority. Multiple CAs can be trusted by specifying an array of certificates: -```bash +```ini ca[]="..." ca[]="..." ``` See also the `strict-ssl` config. -#### cafile - -* Default: `null` -* Type: path - -A path to a file containing one or multiple Certificate Authority signing -certificates. Similar to the `ca` setting, but allows for multiple CA's, as -well as for the CA information to be stored in a file on disk. - -#### cache - -* Default: Windows: `%AppData%\npm-cache`, Posix: `~/.npm` -* Type: path - -The location of npm's cache directory. See [`npm cache`](/commands/npm-cache) - -#### cache-lock-stale - -* Default: 60000 (1 minute) -* Type: Number - -The number of ms before cache folder lockfiles are considered stale. - -#### cache-lock-retries - -* Default: 10 -* Type: Number +#### `cache` -Number of times to retry to acquire a lock on cache folder lockfiles. +* Default: Windows: `%LocalAppData%\npm-cache`, Posix: `~/.npm` +* Type: Path -#### cache-lock-wait +The location of npm's cache directory. See [`npm +cache`](/commands/npm-cache) -* Default: 10000 (10 seconds) -* Type: Number +#### `cafile` -Number of ms to wait for cache lock files to expire. - -#### cache-max - -* Default: Infinity -* Type: Number - -**DEPRECATED**: This option has been deprecated in favor of `--prefer-online`. - -`--cache-max=0` is an alias for `--prefer-online`. - -#### cache-min - -* Default: 10 -* Type: Number - -**DEPRECATED**: This option has been deprecated in favor of `--prefer-offline`. +* Default: null +* Type: Path -`--cache-min=9999 (or bigger)` is an alias for `--prefer-offline`. +A path to a file containing one or multiple Certificate Authority signing +certificates. Similar to the `ca` setting, but allows for multiple CA's, as +well as for the CA information to be stored in a file on disk. -#### call +#### `call` * Default: "" * Type: String @@ -306,154 +284,206 @@ custom command to be run along with the installed packages. npm exec --package yo --package generator-node --call "yo node" ``` -#### cert -* Default: `null` -* Type: String +#### `cert` + +* Default: null +* Type: null or String -A client certificate to pass when accessing the registry. Values should be in -PEM format (Windows calls it "Base-64 encoded X.509 (.CER)") with newlines replaced by the string "\n". For example: +A client certificate to pass when accessing the registry. Values should be +in PEM format (Windows calls it "Base-64 encoded X.509 (.CER)") with +newlines replaced by the string "\n". For example: -```bash +```ini cert="-----BEGIN CERTIFICATE-----\nXXXX\nXXXX\n-----END CERTIFICATE-----" ``` -It is _not_ the path to a certificate file (and there is no "certfile" option). +It is _not_ the path to a certificate file (and there is no "certfile" +option). -#### cidr +#### `ci-name` -* Default: `null` -* Type: String, Array, null +* Default: The name of the current CI system, or `null` when not on a known CI + platform. +* Type: null or String -This is a list of CIDR address to be used when configuring limited access tokens with the `npm token create` command. +The name of a continuous integration system. If not set explicitly, npm will +detect the current CI environment using the +[`@npmcli/ci-detect`](http://npm.im/@npmcli/ci-detect) module. -#### commit-hooks +#### `cidr` -* Default: `true` -* Type: Boolean +* Default: null +* Type: null or String (can be set multiple times) -Run git commit hooks when using the `npm version` command. +This is a list of CIDR address to be used when configuring limited access +tokens with the `npm token create` command. -#### color +#### `color` -* Default: true -* Type: Boolean or `"always"` +* Default: true unless the NO_COLOR environ is set to something other than '0' +* Type: "always" or Boolean -If false, never shows colors. If `"always"` then always shows colors. -If true, then only prints color codes for tty file descriptors. +If false, never shows colors. If `"always"` then always shows colors. If +true, then only prints color codes for tty file descriptors. -This option can also be changed using the environment: colors are -disabled when the environment variable `NO_COLOR` is set to any value. +#### `commit-hooks` -#### depth +* Default: true +* Type: Boolean -* Default: null +Run git commit hooks when using the `npm version` command. + +#### `depth` + +* Default: `Infinity` if `--all` is set, otherwise `1` * Type: null or Number The depth to go when recursing packages for `npm ls`. -To make this default to `Infinity` instead of `null`, set `--all`. +If not set, `npm ls` will show only the immediate dependencies of the root +project. If `--all` is set, then npm will show all dependencies by default. -#### description +#### `description` * Default: true * Type: Boolean Show the description in `npm search` -#### dev +#### `diff` + +* Default: +* Type: String (can be set multiple times) + +Define arguments to compare in `npm diff`. + +#### `diff-dst-prefix` + +* Default: "b/" +* Type: String + +Destination prefix to be used in `npm diff` output. + +#### `diff-ignore-all-space` * Default: false * Type: Boolean -\[Deprecated\] Install `dev-dependencies` along with packages. +Ignore whitespace when comparing lines in `npm diff`. -#### dry-run +#### `diff-name-only` * Default: false * Type: Boolean -Indicates that you don't want npm to make any changes and that it should -only report what it would have done. This can be passed into any of the -commands that modify your local installation, eg, `install`, `update`, -`dedupe`, `uninstall`. This is NOT currently honored by some network related -commands, eg `dist-tags`, `owner`, etc. +Prints only filenames when using `npm diff`. -#### diff +#### `diff-no-prefix` -* Default: null -* Type: String, Array, null +* Default: false +* Type: Boolean -Define arguments to compare in `npm diff`. +Do not show any source or destination prefix in `npm diff` output. + +Note: this causes `npm diff` to ignore the `--diff-src-prefix` and +`--diff-dst-prefix` configs. + +#### `diff-src-prefix` + +* Default: "a/" +* Type: String + +Source prefix to be used in `npm diff` output. -#### diff-name-only +#### `diff-text` * Default: false * Type: Boolean -Prints only filenames when using `npm diff`. +Treat all files as text in `npm diff`. -#### diff-unified +#### `diff-unified` -* Type: number -* Default: `3` +* Default: 3 +* Type: Number The number of lines of context to print in `npm diff`. -#### diff-ignore-all-space +#### `dry-run` -* Type: Boolean * Default: false +* Type: Boolean -Ignore whitespace when comparing lines in `npm diff. +Indicates that you don't want npm to make any changes and that it should +only report what it would have done. This can be passed into any of the +commands that modify your local installation, eg, `install`, `update`, +`dedupe`, `uninstall`, as well as `pack` and `publish`. -#### diff-no-prefix +Note: This is NOT honored by other network related commands, eg `dist-tags`, +`owner`, etc. + +#### `editor` + +* Default: The EDITOR or VISUAL environment variables, or 'notepad.exe' on + Windows, or 'vim' on Unix systems +* Type: String + +The command to run for `npm edit` and `npm config edit`. + +#### `engine-strict` -* Type: Boolean * Default: false +* Type: Boolean -Do not show any source or destination prefix in `npm diff` output. +If set to true, then npm will stubbornly refuse to install (or even consider +installing) any package that claims to not be compatible with the current +Node.js version. -#### diff-src-prefix +This can be overridden by setting the `--force` flag. -* Type: String -* Default: `"a/"` +#### `fetch-retries` -Source prefix to be used in `npm diff` output. +* Default: 2 +* Type: Number -#### diff-dst-prefix +The "retries" config for the `retry` module to use when fetching packages +from the registry. -* Type: String -* Default: `"b/"` +npm will retry idempotent read requests to the registry in the case of +network failures or 5xx HTTP errors. -Destination prefix to be used in `npm diff` output. +#### `fetch-retry-factor` -#### diff-text +* Default: 10 +* Type: Number -* Alias: `-a` -* Type: Boolean -* Default: false +The "factor" config for the `retry` module to use when fetching packages. -Treat all files as text in `npm diff`. +#### `fetch-retry-maxtimeout` -#### editor +* Default: 60000 (1 minute) +* Type: Number -* Default: `EDITOR` environment variable if set, or `"vi"` on Posix, - or `"notepad"` on Windows. -* Type: path +The "maxTimeout" config for the `retry` module to use when fetching +packages. -The command to run for `npm edit` or `npm config edit`. +#### `fetch-retry-mintimeout` -#### engine-strict +* Default: 10000 (10 seconds) +* Type: Number -* Default: false -* Type: Boolean +The "minTimeout" config for the `retry` module to use when fetching +packages. + +#### `fetch-timeout` -If set to true, then npm will stubbornly refuse to install (or even -consider installing) any package that claims to not be compatible with -the current Node.js version. +* Default: 300000 (5 minutes) +* Type: Number + +The maximum amount of time to wait for HTTP requests to complete. -#### force +#### `force` * Default: false * Type: Boolean @@ -467,17 +497,16 @@ mistakes, unnecessary performance degradation, and malicious input. * Allow installing packages that have an `engines` declaration requiring a different version of npm. * Allow installing packages that have an `engines` declaration requiring a - different version of `node`, even if `--engines-strict` is enabled. + different version of `node`, even if `--engine-strict` is enabled. * Allow `npm audit fix` to install modules outside your stated dependency range (including SemVer-major changes). -* Allow a module to be installed as a direct dependency of itself. * Allow unpublishing all versions of a published package. * Allow conflicting peerDependencies to be installed in the root project. If you don't have a clear idea of what you want to do, it is strongly recommended that you do not use this option! -#### foreground-scripts +#### `foreground-scripts` * Default: false * Type: Boolean @@ -486,249 +515,217 @@ Run all build scripts (ie, `preinstall`, `install`, and `postinstall`) scripts for installed packages in the foreground process, sharing standard input, output, and error with the main npm process. -Note that this will generally make installs run slower, and be much -noisier, but can be useful for debugging. +Note that this will generally make installs run slower, and be much noisier, +but can be useful for debugging. -#### format-package-lock +#### `format-package-lock` * Default: true * Type: Boolean -Format `package-lock.json` or `npm-shrinkwrap.json` as a human readable file. +Format `package-lock.json` or `npm-shrinkwrap.json` as a human readable +file. -#### fund +#### `fund` * Default: true * Type: Boolean When "true" displays the message at the end of each `npm install` -acknowledging the number of dependencies looking for funding. -See [`npm fund`](/commands/npm-fund) for details. +acknowledging the number of dependencies looking for funding. See [`npm +fund`](/commands/npm-fund) for details. -#### fetch-retries +#### `git` -* Default: 2 -* Type: Number - -The "retries" config for the `retry` module to use when fetching -packages from the registry. - -#### fetch-retry-factor - -* Default: 10 -* Type: Number - -The "factor" config for the `retry` module to use when fetching -packages. - -#### fetch-retry-mintimeout - -* Default: 10000 (10 seconds) -* Type: Number - -The "minTimeout" config for the `retry` module to use when fetching -packages. - -#### fetch-retry-maxtimeout - -* Default: 60000 (1 minute) -* Type: Number - -The "maxTimeout" config for the `retry` module to use when fetching -packages. - -#### fetch-timeout - -* Default: 300000 (5 minutes) -* Type: Number - -The maximum amount of time to wait for HTTP requests to complete. - -#### git - -* Default: `"git"` +* Default: "git" * Type: String -The command to use for git commands. If git is installed on the -computer, but is not in the `PATH`, then set this to the full path to -the git binary. +The command to use for git commands. If git is installed on the computer, +but is not in the `PATH`, then set this to the full path to the git binary. -#### git-tag-version +#### `git-tag-version` -* Default: `true` +* Default: true * Type: Boolean Tag the commit when using the `npm version` command. -#### global +#### `global` * Default: false * Type: Boolean -Operates in "global" mode, so that packages are installed into the -`prefix` folder instead of the current working directory. See +Operates in "global" mode, so that packages are installed into the `prefix` +folder instead of the current working directory. See [folders](/configuring-npm/folders) for more on the differences in behavior. -* packages are installed into the `{prefix}/lib/node_modules` folder, instead of the - current working directory. +* packages are installed into the `{prefix}/lib/node_modules` folder, instead + of the current working directory. * bin files are linked to `{prefix}/bin` * man pages are linked to `{prefix}/share/man` -#### globalconfig - -* Default: {prefix}/etc/npmrc -* Type: path - -The config file to read for global config options. - -#### global-style +#### `global-style` * Default: false * Type: Boolean Causes npm to install the package into your local `node_modules` folder with -the same layout it uses with the global `node_modules` folder. Only your +the same layout it uses with the global `node_modules` folder. Only your direct dependencies will show in `node_modules` and everything they depend -on will be flattened in their `node_modules` folders. This obviously will -eliminate some deduping. If used with `legacy-bundling`, `legacy-bundling` will be -preferred. +on will be flattened in their `node_modules` folders. This obviously will +eliminate some deduping. If used with `legacy-bundling`, `legacy-bundling` +will be preferred. + +#### `globalconfig` + +* Default: The global --prefix setting plus 'etc/npmrc'. For example, + '/usr/local/etc/npmrc' +* Type: Path -#### heading +The config file to read for global config options. + +#### `heading` -* Default: `"npm"` +* Default: "npm" * Type: String The string that starts all the debugging log output. -#### https-proxy +#### `https-proxy` * Default: null -* Type: url +* Type: null or URL A proxy to use for outgoing https requests. If the `HTTPS_PROXY` or `https_proxy` or `HTTP_PROXY` or `http_proxy` environment variables are set, -proxy settings will be honored by the underlying `request` library. +proxy settings will be honored by the underlying `make-fetch-happen` +library. -#### if-present +#### `if-present` * Default: false * Type: Boolean -If true, npm will not exit with an error code when `run-script` is invoked for -a script that isn't defined in the `scripts` section of `package.json`. This -option can be used when it's desirable to optionally run a script when it's -present and fail if the script fails. This is useful, for example, when running -scripts that may only apply for some builds in an otherwise generic CI setup. +If true, npm will not exit with an error code when `run-script` is invoked +for a script that isn't defined in the `scripts` section of `package.json`. +This option can be used when it's desirable to optionally run a script when +it's present and fail if the script fails. This is useful, for example, when +running scripts that may only apply for some builds in an otherwise generic +CI setup. -#### ignore-prepublish +#### `ignore-scripts` * Default: false * Type: Boolean -If true, npm will not run `prepublish` scripts. +If true, npm does not run scripts specified in package.json files. -#### ignore-scripts +#### `include` -* Default: false -* Type: Boolean +* Default: +* Type: "prod", "dev", "optional", or "peer" (can be set multiple times) -If true, npm does not run scripts specified in package.json files. +Option that allows for defining which types of dependencies to install. -#### include +This is the inverse of `--omit=<type>`. -* Default: `[prod|dev|optional|peer]` -* Type: Array +Dependency types specified in `--include` will not be omitted, regardless of +the order in which omit/include are specified on the command-line. -Option that allows for defining which types of dependencies to install. +#### `include-staged` -#### init-module +* Default: false +* Type: Boolean -* Alias: `init.module` -* Default: ~/.npm-init.js -* Type: path +Allow installing "staged" published packages, as defined by [npm RFC PR +#92](https://github.com/npm/rfcs/pull/92). -A module that will be loaded by the `npm init` command. See the -documentation for the -[init-package-json](https://github.com/npm/init-package-json) module -for more information, or [npm init](/commands/npm-init). +This is experimental, and not implemented by the npm public registry. -#### init-author-name +#### `init-author-email` -* Alias: `init.author.name` * Default: "" * Type: String -The value `npm init` should use by default for the package author's name. +The value `npm init` should use by default for the package author's email. -#### init-author-email +#### `init-author-name` -* Alias: `init.author.email` * Default: "" * Type: String -The value `npm init` should use by default for the package author's email. +The value `npm init` should use by default for the package author's name. -#### init-author-url +#### `init-author-url` -* Alias: `init.author.url` * Default: "" -* Type: String +* Type: "" or URL -The value `npm init` should use by default for the package author's homepage. +The value `npm init` should use by default for the package author's +homepage. -#### init-license +#### `init-license` -* Alias: `init.license` * Default: "ISC" * Type: String The value `npm init` should use by default for the package license. -#### init-version +#### `init-module` + +* Default: "~/.npm-init.js" +* Type: Path + +A module that will be loaded by the `npm init` command. See the +documentation for the +[init-package-json](https://github.com/npm/init-package-json) module for +more information, or [npm init](/commands/npm-init). + +#### `init-version` -* Alias: `init.version` * Default: "1.0.0" -* Type: semver +* Type: SemVer string -The value that `npm init` should use by default for the package -version number, if not already set in package.json. +The value that `npm init` should use by default for the package version +number, if not already set in package.json. -#### json +#### `json` * Default: false * Type: Boolean Whether or not to output JSON data, rather than the normal output. -This feature is currently experimental, and the output data structures for many -commands is either not implemented in JSON yet, or subject to change. Only the -output from `npm ls --json` and `npm search --json` are currently valid. +This feature is currently experimental, and the output data structures for +many commands is either not implemented in JSON yet, or subject to change. +Only the output from `npm ls --json` and `npm search --json` are currently +valid. -#### key +#### `key` -* Default: `null` -* Type: String +* Default: null +* Type: null or String -A client key to pass when accessing the registry. Values should be in PEM +A client key to pass when accessing the registry. Values should be in PEM format with newlines replaced by the string "\n". For example: -```json +```ini key="-----BEGIN PRIVATE KEY-----\nXXXX\nXXXX\n-----END PRIVATE KEY-----" ``` It is _not_ the path to a key file (and there is no "keyfile" option). -#### legacy-bundling +#### `legacy-bundling` * Default: false * Type: Boolean Causes npm to install the package such that versions of npm prior to 1.4, -such as the one included with node 0.8, can install the package. This +such as the one included with node 0.8, can install the package. This eliminates all automatic deduping. If used with `global-style` this option will be preferred. -#### legacy-peer-deps +#### `legacy-peer-deps` * Default: false * Type: Boolean @@ -736,9 +733,8 @@ will be preferred. Causes npm to completely ignore `peerDependencies` when building a package tree, as in npm versions 3 through 6. -If a package cannot be installed because of overly strict -`peerDependencies` that collide, it provides a way to move forward -resolving the situation. +If a package cannot be installed because of overly strict `peerDependencies` +that collide, it provides a way to move forward resolving the situation. This differs from `--omit=peer`, in that `--omit=peer` will avoid unpacking `peerDependencies` on disk, but will still design a tree such that @@ -747,7 +743,7 @@ This differs from `--omit=peer`, in that `--omit=peer` will avoid unpacking Use of `legacy-peer-deps` is not recommended, as it will not enforce the `peerDependencies` contract that meta-dependencies may rely on. -#### link +#### `link` * Default: false * Type: Boolean @@ -755,57 +751,57 @@ Use of `legacy-peer-deps` is not recommended, as it will not enforce the If true, then local installs will link if there is a suitable globally installed package. -Note that this means that local installs can cause things to be -installed into the global space at the same time. The link is only done -if one of the two conditions are met: +Note that this means that local installs can cause things to be installed +into the global space at the same time. The link is only done if one of the +two conditions are met: * The package is not already installed globally, or -* the globally installed version is identical to the version that is - being installed locally. +* the globally installed version is identical to the version that is being + installed locally. -#### local-address +#### `local-address` -* Default: undefined +* Default: null * Type: IP Address -The IP address of the local interface to use when making connections -to the npm registry. Must be IPv4 in versions of Node prior to 0.12. +The IP address of the local interface to use when making connections to the +npm registry. Must be IPv4 in versions of Node prior to 0.12. -#### loglevel +#### `loglevel` * Default: "notice" -* Type: String -* Values: "silent", "error", "warn", "notice", "http", "timing", "info", - "verbose", "silly" +* Type: "silent", "error", "warn", "notice", "http", "timing", "info", + "verbose", or "silly" -What level of logs to report. On failure, *all* logs are written to +What level of logs to report. On failure, *all* logs are written to `npm-debug.log` in the current working directory. -Any logs of a higher level than the setting are shown. The default is "notice". +Any logs of a higher level than the setting are shown. The default is +"notice". -#### logs-max +#### `logs-max` * Default: 10 * Type: Number The maximum number of log files to store. -#### long +#### `long` * Default: false * Type: Boolean Show extended information in `npm ls` and `npm search`. -#### maxsockets +#### `maxsockets` -* Default: 50 +* Default: Infinity * Type: Number The maximum number of connections to use per origin (protocol/host/port -combination). Passed to the `http` `Agent` used to make the request. +combination). -#### message +#### `message` * Default: "%s" * Type: String @@ -814,73 +810,83 @@ Commit message which is used by `npm version` when creating version commit. Any "%s" in the message will be replaced with the version number. -#### node-options +#### `node-options` * Default: null -* Type: String +* Type: null or String Options to pass through to Node.js via the `NODE_OPTIONS` environment -variable. This does not impact how npm itself is executed but it does -impact how lifecycle scripts are called. +variable. This does not impact how npm itself is executed but it does impact +how lifecycle scripts are called. -#### node-version +#### `node-version` -* Default: process.version -* Type: semver or false +* Default: Node.js `process.version` value +* Type: SemVer string -The node version to use when checking a package's `engines` map. +The node version to use when checking a package's `engines` setting. -#### noproxy +#### `noproxy` -* Default: null -* Type: String or Array +* Default: The value of the NO_PROXY environment variable +* Type: String (can be set multiple times) -A comma-separated string or an array of domain extensions that a proxy should not be used for. +Domain extensions that should bypass any proxies. -#### offline +Also accepts a comma-delimited string. -* Default: false -* Type: Boolean +#### `npm-version` -Force offline mode: no network requests will be done during install. To allow -the CLI to fill in missing cache data, see `--prefer-offline`. +* Default: Output of `npm --version` +* Type: SemVer string -#### only +The npm version to use when checking a package's `engines` setting. -* Default: null -* Type: String +#### `offline` -When "dev" or "development" and running local `npm install` without any -arguments, only devDependencies (and their dependencies) are installed. +* Default: false +* Type: Boolean -When "dev" or "development" and running local `npm ls`, `npm outdated`, or -`npm update`, is an alias for `--dev`. +Force offline mode: no network requests will be done during install. To +allow the CLI to fill in missing cache data, see `--prefer-offline`. -When "prod" or "production" and running local `npm install` without any -arguments, only non-devDependencies (and their dependencies) are -installed. +#### `omit` -When "prod" or "production" and running local `npm ls`, `npm outdated`, or -`npm update`, is an alias for `--production`. +* Default: 'dev' if the NODE_ENV environment variable is set to 'production', + otherwise empty. +* Type: "dev", "optional", or "peer" (can be set multiple times) -#### optional +Dependency types to omit from the installation tree on disk. -* Default: true -* Type: Boolean +Note that these dependencies _are_ still resolved and added to the +`package-lock.json` or `npm-shrinkwrap.json` file. They are just not +physically installed on disk. + +If a package type appears in both the `--include` and `--omit` lists, then +it will be included. -Attempt to install packages in the `optionalDependencies` object. Note -that if these packages fail to install, the overall installation -process is not aborted. +If the resulting omit list includes `'dev'`, then the `NODE_ENV` environment +variable will be set to `'production'` for all lifecycle scripts. -#### otp +#### `otp` * Default: null -* Type: Number +* Type: null or String -This is a one-time password from a two-factor authenticator. It's needed +This is a one-time password from a two-factor authenticator. It's needed when publishing or changing package permissions with `npm access`. -#### package-lock +If not set, and a registry response fails with a challenge for a one-time +password, npm will prompt on the command line for one. + +#### `package` + +* Default: +* Type: String (can be set multiple times) + +The package to install for [`npm exec`](/commands/npm-exec) + +#### `package-lock` * Default: true * Type: Boolean @@ -889,75 +895,63 @@ If set to false, then ignore `package-lock.json` files when installing. This will also prevent _writing_ `package-lock.json` if `save` is true. When package package-locks are disabled, automatic pruning of extraneous -modules will also be disabled. To remove extraneous modules with +modules will also be disabled. To remove extraneous modules with package-locks disabled use `npm prune`. -This option is an alias for `--shrinkwrap`. - -#### package-lock-only +#### `package-lock-only` * Default: false * Type: Boolean -If set to true, it will update only the `package-lock.json`, -instead of checking `node_modules` and downloading dependencies. +If set to true, it will update only the `package-lock.json`, instead of +checking `node_modules` and downloading dependencies. -#### parseable +#### `parseable` * Default: false * Type: Boolean -Output parseable results from commands that write to -standard output. For `npm search`, this will be tab-separated table format. +Output parseable results from commands that write to standard output. For +`npm search`, this will be tab-separated table format. -#### prefer-offline +#### `prefer-offline` * Default: false * Type: Boolean If true, staleness checks for cached data will be bypassed, but missing data -will be requested from the server. To force full offline mode, use `--offline`. - -This option is effectively equivalent to `--cache-min=9999999`. +will be requested from the server. To force full offline mode, use +`--offline`. -#### prefer-online +#### `prefer-online` * Default: false * Type: Boolean -If true, staleness checks for cached data will be forced, making the CLI look -for updates immediately even for fresh package data. +If true, staleness checks for cached data will be forced, making the CLI +look for updates immediately even for fresh package data. -#### prefix +#### `prefix` -* Default: see [folders](/configuring-npm/folders) -* Type: path +* Default: In global mode, the folder where the node executable is installed. + In local mode, the nearest parent folder containing either a package.json + file or a node_modules folder. +* Type: Path -The location to install global items. If set on the command line, then -it forces non-global commands to run in the specified folder. +The location to install global items. If set on the command line, then it +forces non-global commands to run in the specified folder. -#### preid +#### `preid` * Default: "" * Type: String -The "prerelease identifier" to use as a prefix for the "prerelease" part of a -semver. Like the `rc` in `1.2.0-rc.8`. +The "prerelease identifier" to use as a prefix for the "prerelease" part of +a semver. Like the `rc` in `1.2.0-rc.8`. -#### production +#### `progress` -* Default: false -* Type: Boolean - -Set to true to run in "production" mode. - -1. devDependencies are not installed at the topmost level when running - local `npm install` without any arguments. -2. Set the NODE_ENV="production" for lifecycle scripts. - -#### progress - -* Default: true, unless TRAVIS or CI env vars set. +* Default: `true` unless running in a known CI system * Type: Boolean When set to `true`, npm will display a progress bar during time intensive @@ -965,56 +959,48 @@ operations, if `process.stderr` is a TTY. Set to `false` to suppress the progress bar. -#### proxy +#### `proxy` * Default: null -* Type: url +* Type: null, false, or URL A proxy to use for outgoing http requests. If the `HTTP_PROXY` or -`http_proxy` environment variables are set, proxy settings will be -honored by the underlying `request` library. +`http_proxy` environment variables are set, proxy settings will be honored +by the underlying `request` library. -#### read-only +#### `read-only` * Default: false * Type: Boolean -This is used to mark a token as unable to publish when configuring limited access tokens with the `npm token create` command. +This is used to mark a token as unable to publish when configuring limited +access tokens with the `npm token create` command. -#### rebuild-bundle +#### `rebuild-bundle` * Default: true * Type: Boolean Rebuild bundled dependencies after installation. -#### registry +#### `registry` -* Default: https://registry.npmjs.org/ -* Type: url +* Default: "https://registry.npmjs.org/" +* Type: URL -The base URL of the npm package registry. +The base URL of the npm registry. -#### rollback - -* Default: true -* Type: Boolean - -Remove failed installs. - -#### save +#### `save` * Default: true * Type: Boolean Save installed packages to a package.json file as dependencies. -When used with the `npm rm` command, it removes it from the `dependencies` -object. - -Only works if there is already a package.json file present. +When used with the `npm rm` command, removes the dependency from +package.json. -#### save-bundle +#### `save-bundle` * Default: false * Type: Boolean @@ -1023,120 +1009,94 @@ If a package would be saved at install time by the use of `--save`, `--save-dev`, or `--save-optional`, then also put it in the `bundleDependencies` list. -When used with the `npm rm` command, it removes it from the -bundledDependencies list. +Ignore if `--save-peer` is set, since peerDependencies cannot be bundled. -#### save-prod +#### `save-dev` * Default: false * Type: Boolean -Makes sure that a package will be saved into `dependencies` specifically. This -is useful if a package already exists in `devDependencies` or -`optionalDependencies`, but you want to move it to be a production dep. This is -also the default behavior if `--save` is true, and neither `--save-dev` or -`--save-optional` are true. +Save installed packages to a package.json file as `devDependencies`. -#### save-dev +#### `save-exact` * Default: false * Type: Boolean -Save installed packages to a package.json file as `devDependencies`. - -When used with the `npm rm` command, it removes it from the -`devDependencies` object. - -Only works if there is already a package.json file present. +Dependencies saved to package.json will be configured with an exact version +rather than using npm's default semver range operator. -#### save-exact +#### `save-optional` * Default: false * Type: Boolean -Dependencies saved to package.json using `--save`, `--save-dev` or -`--save-optional` will be configured with an exact version rather than -using npm's default semver range operator. +Save installed packages to a package.json file as `optionalDependencies`. -#### save-optional +#### `save-peer` * Default: false * Type: Boolean -Save installed packages to a package.json file as -optionalDependencies. +Save installed packages. to a package.json file as `peerDependencies` -When used with the `npm rm` command, it removes it from the -`devDependencies` object. +#### `save-prefix` -Only works if there is already a package.json file present. - -#### save-prefix - -* Default: '^' +* Default: "^" * Type: String Configure how versions of packages installed to a package.json file via `--save` or `--save-dev` get prefixed. -For example if a package has version `1.2.3`, by default its version is -set to `^1.2.3` which allows minor upgrades for that package, but after -`npm config set save-prefix='~'` it would be set to `~1.2.3` which only allows +For example if a package has version `1.2.3`, by default its version is set +to `^1.2.3` which allows minor upgrades for that package, but after `npm +config set save-prefix='~'` it would be set to `~1.2.3` which only allows patch upgrades. -#### scope - -* Default: the scope of the current project, if any, or "" -* Type: String +#### `save-prod` -Associate an operation with a scope for a scoped registry. Useful when logging -in to a private registry for the first time: -`npm login --scope=@organization --registry=registry.organization.com`, which -will cause `@organization` to be mapped to the registry for future installation -of packages specified according to the pattern `@organization/package`. - -#### script-shell +* Default: false +* Type: Boolean -* Default: `null` -* Type: path +Save installed packages into `dependencies` specifically. This is useful if +a package already exists in `devDependencies` or `optionalDependencies`, but +you want to move it to be a non-optional production dependency. -The shell to use for scripts run with the `npm run` command. +This is the default behavior if `--save` is true, and neither `--save-dev` +or `--save-optional` are true. -#### scripts-prepend-node-path +#### `scope` -* Default: "warn-only" -* Type: Boolean, `"auto"` or `"warn-only"` +* Default: the scope of the current project, if any, or "" +* Type: String -If set to `true`, add the directory in which the current `node` executable -resides to the `PATH` environment variable when running scripts, -even if that means that `npm` will invoke a different `node` executable than -the one which it is running. +Associate an operation with a scope for a scoped registry. -If set to `false`, never modify `PATH` with that. +Useful when logging in to a private registry for the first time: -If set to `"warn-only"`, never modify `PATH` but print a warning if `npm` thinks -that you may want to run it with `true`, e.g. because the `node` executable -in the `PATH` is not the one `npm` was invoked with. +```bash +npm login --scope=@mycorp --registry=https://registry.mycorp.com +``` -If set to `auto`, only add that directory to the `PATH` environment variable -if the `node` executable with which `npm` was invoked and the one that is found -first on the `PATH` are different. +This will cause `@mycorp` to be mapped to the registry for future +installation of packages specified according to the pattern +`@mycorp/package`. -#### searchexclude +#### `script-shell` -* Default: "" -* Type: String +* Default: '/bin/sh' on POSIX systems, 'cmd.exe' on Windows +* Type: null or String -Space-separated options that limit the results from search. +The shell to use for scripts run with the `npm run` command. -#### searchopts +#### `searchexclude` * Default: "" * Type: String -Space-separated options that are always passed to search. +Space-separated options that limit the results from search. -#### searchlimit +#### `searchlimit` * Default: 20 * Type: Number @@ -1144,33 +1104,30 @@ Space-separated options that are always passed to search. Number of items to limit search results to. Will not apply at all to legacy searches. -#### searchstaleness +#### `searchopts` + +* Default: "" +* Type: String + +Space-separated options that are always passed to search. + +#### `searchstaleness` -* Default: 900 (15 minutes) +* Default: 900 * Type: Number The age of the cache, in seconds, before another registry request is made if using legacy search endpoint. -#### shell +#### `shell` -* Default: SHELL environment variable, or "bash" on Posix, or "cmd" on +* Default: SHELL environment variable, or "bash" on Posix, or "cmd.exe" on Windows -* Type: path +* Type: String The shell to run for the `npm explore` command. -#### shrinkwrap - -* Default: true -* Type: Boolean - -If set to false, then ignore `npm-shrinkwrap.json` files when installing. This -will also prevent _writing_ `npm-shrinkwrap.json` if `save` is true. - -This option is an alias for `--package-lock`. - -#### sign-git-commit +#### `sign-git-commit` * Default: false * Type: Boolean @@ -1178,36 +1135,21 @@ This option is an alias for `--package-lock`. If set to true, then the `npm version` command will commit the new package version using `-S` to add a signature. -Note that git requires you to have set up GPG keys in your git configs -for this to work properly. +Note that git requires you to have set up GPG keys in your git configs for +this to work properly. -#### sign-git-tag +#### `sign-git-tag` * Default: false * Type: Boolean -If set to true, then the `npm version` command will tag the version -using `-s` to add a signature. +If set to true, then the `npm version` command will tag the version using +`-s` to add a signature. -Note that git requires you to have set up GPG keys in your git configs -for this to work properly. - -#### sso-poll-frequency - -* Default: 500 -* Type: Number - -When used with SSO-enabled `auth-type`s, configures how regularly the registry -should be polled while the user is completing authentication. - -#### sso-type - -* Default: 'oauth' -* Type: 'oauth', 'saml', or null - -If `--auth-type=sso`, the type of SSO type to use. +Note that git requires you to have set up GPG keys in your git configs for +this to work properly. -#### strict-peer-deps +#### `strict-peer-deps` * Default: false * Type: Boolean @@ -1217,145 +1159,345 @@ conflicting `peerDependencies` will be treated as an install failure, even if npm could reasonably guess the appropriate resolution based on non-peer dependency relationships. -By default, conflicting `peerDependencies` in the dependency graph will be -resolved using the nearest non-peer dependency specification, even if doing -so will result in some packages receiving a peer dependency outside the -range set in their package's `peerDependencies` object. When such and -override is performed, a warning is printed, explaining the conflict and -the packages involved. If `--strict-peer-deps` is set, then the warning is -treated as a failure. +By default, conflicting `peerDependencies` deep in the dependency graph will +be resolved using the nearest non-peer dependency specification, even if +doing so will result in some packages receiving a peer dependency outside +the range set in their package's `peerDependencies` object. -#### strict-ssl +When such and override is performed, a warning is printed, explaining the +conflict and the packages involved. If `--strict-peer-deps` is set, then +this warning is treated as a failure. + +#### `strict-ssl` * Default: true * Type: Boolean -Whether or not to do SSL key validation when making requests to the -registry via https. +Whether or not to do SSL key validation when making requests to the registry +via https. See also the `ca` config. -#### tag +#### `tag` -* Default: latest +* Default: "latest" * Type: String -If you ask npm to install a package and don't tell it a specific version, then -it will install the specified tag. +If you ask npm to install a package and don't tell it a specific version, +then it will install the specified tag. -Also the tag that is added to the package@version specified by the `npm -tag` command, if no explicit tag is given. +Also the tag that is added to the package@version specified by the `npm tag` +command, if no explicit tag is given. -#### tag-version-prefix +#### `tag-version-prefix` -* Default: `"v"` +* Default: "v" * Type: String If set, alters the prefix used when tagging a new version when performing a -version increment using `npm-version`. To remove the prefix altogether, set it -to the empty string: `""`. +version increment using `npm-version`. To remove the prefix altogether, set +it to the empty string: `""`. -Because other tools may rely on the convention that npm version tags look like -`v1.0.0`, _only use this property if it is absolutely necessary_. In +Because other tools may rely on the convention that npm version tags look +like `v1.0.0`, _only use this property if it is absolutely necessary_. In particular, use care when overriding this setting for public packages. -#### timing +#### `timing` -* Default: `false` +* Default: false * Type: Boolean If true, writes an `npm-debug` log to `_logs` and timing information to -`_timing.json`, both in your cache. `_timing.json` is a newline delimited -list of JSON objects. You can quickly view it with this -[json](https://www.npmjs.com/package/json) command line: -`json -g < ~/.npm/_timing.json`. +`_timing.json`, both in your cache, even if the command completes +successfully. `_timing.json` is a newline delimited list of JSON objects. + +You can quickly view it with this [json](https://npm.im/json) command line: +`npm exec -- json -g < ~/.npm/_timing.json`. + +#### `umask` + +* Default: 0 +* Type: Octal numeric string in range 0000..0777 (0..511) -#### tmp +The "umask" value to use when setting the file creation mode on files and +folders. -* Default: TMPDIR environment variable, or "/tmp" -* Type: path +Folders and executables are given a mode which is `0o777` masked against +this value. Other files are given a mode which is `0o666` masked against +this value. -Where to store temporary files and folders. All temp files are deleted -on success, but left behind on failure for forensic purposes. +Note that the underlying system will _also_ apply its own umask value to +files and folders that are created, and npm does not circumvent this, but +rather adds the `--umask` config to it. -#### unicode +Thus, the effective default umask value on most POSIX systems is 0o22, +meaning that folders and executables are created with a mode of 0o755 and +other files are created with a mode of 0o644. -* Default: false on windows, true on mac/unix systems with a unicode locale +#### `unicode` + +* Default: false on windows, true on mac/unix systems with a unicode locale, + as defined by the LC_ALL, LC_CTYPE, or LANG environment variables. * Type: Boolean -When set to true, npm uses unicode characters in the tree output. When -false, it uses ascii characters to draw trees. +When set to true, npm uses unicode characters in the tree output. When +false, it uses ascii characters instead of unicode glyphs. -#### update-notifier +#### `update-notifier` * Default: true * Type: Boolean -Set to false to suppress the update notification when using an older -version of npm than the latest. +Set to false to suppress the update notification when using an older version +of npm than the latest. -#### usage +#### `usage` * Default: false * Type: Boolean -Set to show short usage output (like the -H output) -instead of complete help when doing [`npm help`](/commands/npm-help). - -#### userconfig - -* Default: ~/.npmrc -* Type: path +Show short usage output about the command specified. -The location of user-level configuration settings. +#### `user-agent` -#### umask +* Default: "npm/{npm-version} node/{node-version} {platform} {arch} {ci}" +* Type: String -* Default: 022 -* Type: Octal numeric string in range 0000..0777 (0..511) +Sets the User-Agent request header. The following fields are replaced with +their actual counterparts: -The "umask" value to use when setting the file creation mode on files -and folders. +* `{npm-version}` - The npm version in use +* `{node-version}` - The Node.js version in use +* `{platform}` - The value of `process.platform` +* `{arch}` - The value of `process.arch` +* `{ci}` - The value of the `ci-name` config, if set, prefixed with `ci/`, or + an empty string if `ci-name` is empty. -Folders and executables are given a mode which is `0777` masked against -this value. Other files are given a mode which is `0666` masked against -this value. Thus, the defaults are `0755` and `0644` respectively. +#### `userconfig` -#### user-agent +* Default: "~/.npmrc" +* Type: Path -* Default: node/{process.version} {process.platform} {process.arch} -* Type: String +The location of user-level configuration settings. -Sets a User-Agent to the request header +This may be overridden by the `npm_config_userconfig` environment variable +or the `--userconfig` command line option, but may _not_ be overridden by +settings in the `globalconfig` file. -#### version +#### `version` * Default: false -* Type: boolean +* Type: Boolean If true, output the npm version and exit successfully. Only relevant when specified explicitly on the command line. -#### versions +#### `versions` * Default: false -* Type: boolean +* Type: Boolean -If true, output the npm version as well as node's `process.versions` map, and -exit successfully. +If true, output the npm version as well as node's `process.versions` map and +the version in the current working directory's `package.json` file if one +exists, and exit successfully. Only relevant when specified explicitly on the command line. -#### viewer +#### `viewer` * Default: "man" on Posix, "browser" on Windows -* Type: path +* Type: String The program to use to view help content. Set to `"browser"` to view html help content in the default web browser. +#### `which` + +* Default: null +* Type: null or Number + +If there are multiple funding sources, which 1-indexed source URL to open. + +#### `workspace` + +* Default: +* Type: String (can be set multiple times) + +Enable running a command in the context of the configured workspaces of the +current project while filtering by running only the workspaces defined by +this configuration option. + +Valid values for the `workspace` config are either: - Workspace names - Path +to a workspace directory - Path to a parent workspace directory (will result +to selecting all of the nested workspaces) + +#### `workspaces` + +* Default: false +* Type: Boolean + +Enable running a command in the context of **all** the configured +workspaces. + +#### `yes` + +* Default: null +* Type: null or Boolean + +Automatically answer "yes" to any prompts that npm might print on the +command line. + +#### `also` + +* Default: null +* Type: null, "dev", or "development" +* DEPRECATED: Please use --include=dev instead. + +When set to `dev` or `development`, this is an alias for `--include=dev`. + +#### `auth-type` + +* Default: "legacy" +* Type: "legacy", "sso", "saml", or "oauth" +* DEPRECATED: This method of SSO/SAML/OAuth is deprecated and will be removed + in a future version of npm in favor of web-based login. + +What authentication strategy to use with `adduser`/`login`. + +#### `cache-max` + +* Default: Infinity +* Type: Number +* DEPRECATED: This option has been deprecated in favor of `--prefer-online` + +`--cache-max=0` is an alias for `--prefer-online` + +#### `cache-min` + +* Default: 0 +* Type: Number +* DEPRECATED: This option has been deprecated in favor of `--prefer-offline`. + +`--cache-min=9999 (or bigger)` is an alias for `--prefer-offline`. + +#### `init.author.email` + +* Default: "" +* Type: String +* DEPRECATED: Use `--init-author-email` instead. + +Alias for `--init-author-email` + +#### `init.author.name` + +* Default: "" +* Type: String +* DEPRECATED: Use `--init-author-name` instead. + +Alias for `--init-author-name` + +#### `init.author.url` + +* Default: "" +* Type: "" or URL +* DEPRECATED: Use `--init-author-url` instead. + +Alias for `--init-author-url` + +#### `init.license` + +* Default: "ISC" +* Type: String +* DEPRECATED: Use `--init-license` instead. + +Alias for `--init-license` + +#### `init.module` + +* Default: "~/.npm-init.js" +* Type: Path +* DEPRECATED: Use `--init-module` instead. + +Alias for `--init-module` + +#### `init.version` + +* Default: "1.0.0" +* Type: SemVer string +* DEPRECATED: Use `--init-version` instead. + +Alias for `--init-version` + +#### `only` + +* Default: null +* Type: null, "prod", or "production" +* DEPRECATED: Use `--omit=dev` to omit dev dependencies from the install. + +When set to `prod` or `production`, this is an alias for `--omit=dev`. + +#### `optional` + +* Default: null +* Type: null or Boolean +* DEPRECATED: Use `--omit=optional` to exclude optional dependencies, or + `--include=optional` to include them. + +Default value does install optional deps unless otherwise omitted. + +Alias for --include=optional or --omit=optional + +#### `production` + +* Default: false +* Type: Boolean +* DEPRECATED: Use `--omit=dev` instead. + +Alias for `--omit=dev` + +#### `shrinkwrap` + +* Default: true +* Type: Boolean +* DEPRECATED: Use the --package-lock setting instead. + +Alias for --package-lock + +#### `sso-poll-frequency` + +* Default: 500 +* Type: Number +* DEPRECATED: The --auth-type method of SSO/SAML/OAuth will be removed in a + future version of npm in favor of web-based login. + +When used with SSO-enabled `auth-type`s, configures how regularly the +registry should be polled while the user is completing authentication. + +#### `sso-type` + +* Default: "oauth" +* Type: null, "oauth", or "saml" +* DEPRECATED: The --auth-type method of SSO/SAML/OAuth will be removed in a + future version of npm in favor of web-based login. + +If `--auth-type=sso`, the type of SSO type to use. + +#### `tmp` + +* Default: The value returned by the Node.js `os.tmpdir()` method + <https://nodejs.org/api/os.html#os_os_tmpdir> +* Type: Path +* DEPRECATED: This setting is no longer used. npm stores temporary files in a + special location in the cache, and they are managed by + [`cacache`](http://npm.im/cacache). + +Historically, the location where temporary files were stored. No longer +relevant. + +<!-- AUTOGENERATED CONFIG DESCRIPTIONS END --> + ### See also * [npm config](/commands/npm-config) diff --git a/deps/npm/docs/content/using-npm/workspaces.md b/deps/npm/docs/content/using-npm/workspaces.md index 2024627c75..28fccd2200 100644 --- a/deps/npm/docs/content/using-npm/workspaces.md +++ b/deps/npm/docs/content/using-npm/workspaces.md @@ -88,8 +88,54 @@ This demonstrates how the nature of `node_modules` resolution allows for in such a way that is also easy to [publish](/commands/npm-publish) these nested workspaces to be consumed elsewhere. +### Running commands in the context of workspaces + +You man use the `workspace` configuration option to run commands in the context +of a configured workspace. + +Following is a quick example on how to use the `npm run` command in the context +of nested workspaces. For a project containing multiple workspaces, e.g: + +``` +. ++-- package.json +`-- packages + +-- a + | `-- package.json + `-- b + `-- package.json +``` + +By running a command using the `workspace` option, it's possible to run the +given command in the context of that specific workspace. e.g: + +``` +npm run test --workspace=a +``` + +This will run the `test` script defined within the +`./packages/a/package.json` file. + +Please note that you can also specify this argument multiple times in the +command-line in order to target multiple workspaces, e.g: + +``` +npm run test --workspace=a --workspace=b +``` + +It's also possible to use the `workspaces` (plural) configuration option to +enable the same behavior but running that command in the context of **all** +configured workspaces. e.g: + +``` +npm run test --workspaces +``` + +Will run the `test` script in both `./packages/a` and `./packages/b`. + ### See also * [npm install](/commands/npm-install) * [npm publish](/commands/npm-publish) +* [npm run-script](/commands/npm-run-script) diff --git a/deps/npm/docs/output/commands/npm-adduser.html b/deps/npm/docs/output/commands/npm-adduser.html index 95f0cdaa71..a079dfed71 100644 --- a/deps/npm/docs/output/commands/npm-adduser.html +++ b/deps/npm/docs/output/commands/npm-adduser.html @@ -149,6 +149,7 @@ npm command-line interface aliases: login, add-user </code></pre> +<p>Note: This command is unaware of workspaces.</p> <h3 id="description">Description</h3> <p>Create or verify a user named <code><username></code> in the specified registry, and save the credentials to the <code>.npmrc</code> file. If no registry is specified, diff --git a/deps/npm/docs/output/commands/npm-bin.html b/deps/npm/docs/output/commands/npm-bin.html index 703c9e9243..6145520259 100644 --- a/deps/npm/docs/output/commands/npm-bin.html +++ b/deps/npm/docs/output/commands/npm-bin.html @@ -147,6 +147,7 @@ npm command-line interface <div id="_content"><h3 id="synopsis">Synopsis</h3> <pre lang="bash"><code>npm bin [-g|--global] </code></pre> +<p>Note: This command is unaware of workspaces.</p> <h3 id="description">Description</h3> <p>Print the folder where npm will install executables.</p> <h3 id="see-also">See Also</h3> diff --git a/deps/npm/docs/output/commands/npm-cache.html b/deps/npm/docs/output/commands/npm-cache.html index 9dbf83b31a..22ca6f1999 100644 --- a/deps/npm/docs/output/commands/npm-cache.html +++ b/deps/npm/docs/output/commands/npm-cache.html @@ -155,6 +155,7 @@ aliases: npm cache clear, npm cache rm npm cache verify </code></pre> +<p>Note: This command is unaware of workspaces.</p> <h3 id="description">Description</h3> <p>Used to add, list, or clean the npm cache folder.</p> <ul> diff --git a/deps/npm/docs/output/commands/npm-completion.html b/deps/npm/docs/output/commands/npm-completion.html index 4f7016e4ac..b99d52b420 100644 --- a/deps/npm/docs/output/commands/npm-completion.html +++ b/deps/npm/docs/output/commands/npm-completion.html @@ -147,6 +147,7 @@ npm command-line interface <div id="_content"><h3 id="synopsis">Synopsis</h3> <pre lang="bash"><code>source <(npm completion) </code></pre> +<p>Note: This command is unaware of workspaces.</p> <h3 id="description">Description</h3> <p>Enables tab-completion in all npm commands.</p> <p>The synopsis above diff --git a/deps/npm/docs/output/commands/npm-config.html b/deps/npm/docs/output/commands/npm-config.html index 9245628227..55f6e5ffe6 100644 --- a/deps/npm/docs/output/commands/npm-config.html +++ b/deps/npm/docs/output/commands/npm-config.html @@ -155,6 +155,7 @@ npm get [<key> [<key> ...]] alias: c </code></pre> +<p>Note: This command is unaware of workspaces.</p> <h3 id="description">Description</h3> <p>npm gets its config settings from the command line, environment variables, <code>npmrc</code> files, and in some cases, the <code>package.json</code> file.</p> diff --git a/deps/npm/docs/output/commands/npm-dedupe.html b/deps/npm/docs/output/commands/npm-dedupe.html index 8a0ec7e0f7..ccd9a03f4d 100644 --- a/deps/npm/docs/output/commands/npm-dedupe.html +++ b/deps/npm/docs/output/commands/npm-dedupe.html @@ -136,7 +136,7 @@ npm command-line interface <section id="content"> <header class="title"> <h1 id="npm-dedupe">npm-dedupe</h1> -<span class="description">Reduce duplication</span> +<span class="description">Reduce duplication in the package tree</span> </header> <section id="table_of_contents"> @@ -148,7 +148,7 @@ npm command-line interface <pre lang="bash"><code>npm dedupe npm ddp -aliases: find-dupes, ddp +aliases: ddp </code></pre> <h3 id="description">Description</h3> <p>Searches the local package tree and attempts to simplify the overall @@ -193,6 +193,7 @@ result in new modules being installed.</p> <p>Using <code>npm find-dupes</code> will run the command in <code>--dry-run</code> mode.</p> <h3 id="see-also">See Also</h3> <ul> +<li><a href="../cli-commands/find-dupes.html">npm find-dupes</a></li> <li><a href="../cli-commands/ls.html">npm ls</a></li> <li><a href="../cli-commands/update.html">npm update</a></li> <li><a href="../cli-commands/install.html">npm install</a></li> diff --git a/deps/npm/docs/output/commands/npm-deprecate.html b/deps/npm/docs/output/commands/npm-deprecate.html index 949be43d9b..88299a80bc 100644 --- a/deps/npm/docs/output/commands/npm-deprecate.html +++ b/deps/npm/docs/output/commands/npm-deprecate.html @@ -147,6 +147,7 @@ npm command-line interface <div id="_content"><h3 id="synopsis">Synopsis</h3> <pre lang="bash"><code>npm deprecate <pkg>[@<version range>] <message> </code></pre> +<p>Note: This command is unaware of workspaces.</p> <h3 id="description">Description</h3> <p>This command will update the npm registry entry for a package, providing a deprecation warning to all who attempt to install it.</p> diff --git a/deps/npm/docs/output/commands/npm-doctor.html b/deps/npm/docs/output/commands/npm-doctor.html index a9b2001543..9ae1405755 100644 --- a/deps/npm/docs/output/commands/npm-doctor.html +++ b/deps/npm/docs/output/commands/npm-doctor.html @@ -147,6 +147,7 @@ npm command-line interface <div id="_content"><h3 id="synopsis">Synopsis</h3> <pre lang="bash"><code>npm doctor </code></pre> +<p>Note: This command is unaware of workspaces.</p> <h3 id="description">Description</h3> <p><code>npm doctor</code> runs a set of checks to ensure that your npm installation has what it needs to manage your JavaScript packages. npm is mostly a diff --git a/deps/npm/docs/output/commands/npm-edit.html b/deps/npm/docs/output/commands/npm-edit.html index 7ebb443a2f..8c4ee5ed1a 100644 --- a/deps/npm/docs/output/commands/npm-edit.html +++ b/deps/npm/docs/output/commands/npm-edit.html @@ -147,6 +147,7 @@ npm command-line interface <div id="_content"><h3 id="synopsis">Synopsis</h3> <pre lang="bash"><code>npm edit <pkg> </code></pre> +<p>Note: This command is unaware of workspaces.</p> <h3 id="description">Description</h3> <p>Selects a dependency in the current project and opens the package folder in the default editor (or whatever you’ve configured as the npm <code>editor</code> diff --git a/deps/npm/docs/output/commands/npm-exec.html b/deps/npm/docs/output/commands/npm-exec.html index 03059c5205..f8f882a2c5 100644 --- a/deps/npm/docs/output/commands/npm-exec.html +++ b/deps/npm/docs/output/commands/npm-exec.html @@ -141,7 +141,7 @@ npm command-line interface <section id="table_of_contents"> <h2 id="table-of-contents">Table of contents</h2> -<div id="_table_of_contents"><ul><li><a href="#synopsis">Synopsis</a></li><li><a href="#description">Description</a></li><li><a href="#npx-vs-npm-exec"><code>npx</code> vs <code>npm exec</code></a></li><li><a href="#examples">Examples</a></li><li><a href="#compatibility-with-older-npx-versions">Compatibility with Older npx Versions</a></li><li><a href="#a-note-on-caching">A note on caching</a></li><ul><li><a href="#prefer-online">prefer-online</a></li><li><a href="#prefer-offline">prefer-offline</a></li><li><a href="#offline">offline</a></li></ul><li><a href="#see-also">See Also</a></li></ul></div> +<div id="_table_of_contents"><ul><li><a href="#synopsis">Synopsis</a></li><li><a href="#description">Description</a></li><li><a href="#npx-vs-npm-exec"><code>npx</code> vs <code>npm exec</code></a></li><li><a href="#examples">Examples</a></li><li><a href="#workspaces-support">Workspaces support</a></li><ul><li><a href="#filtering-workspaces">Filtering workspaces</a></li></ul><li><a href="#compatibility-with-older-npx-versions">Compatibility with Older npx Versions</a></li><li><a href="#a-note-on-caching">A note on caching</a></li><ul><li><a href="#prefer-online">prefer-online</a></li><li><a href="#prefer-offline">prefer-offline</a></li><li><a href="#offline">offline</a></li><li><a href="#workspace">workspace</a></li><li><a href="#workspaces">workspaces</a></li></ul><li><a href="#see-also">See Also</a></li></ul></div> </section> <div id="_content"><h3 id="synopsis">Synopsis</h3> @@ -149,6 +149,7 @@ npm command-line interface npm exec --package=<pkg>[@<version>] -- <cmd> [args...] npm exec -c '<cmd> [args...]' npm exec --package=foo -c '<cmd> [args...]' +npm exec [-ws] [-w <workspace-name] [args...] npx <pkg>[@<specifier>] [args...] npx -p <pkg>[@<specifier>] <cmd> [args...] @@ -247,6 +248,49 @@ $ npx --package=foo bar --bar-argument <pre><code>$ npm x -c 'eslint && say "hooray, lint passed"' $ npx -c 'eslint && say "hooray, lint passed"' </code></pre> +<h3 id="workspaces-support">Workspaces support</h3> +<p>You may use the <code>workspace</code> or <code>workspaces</code> configs in order to run an +arbitrary command from an npm package (either one installed locally, or fetched +remotely) in the context of the specified workspaces. +If no positional argument or <code>--call</code> option is provided, it will open an +interactive subshell in the context of each of these configured workspaces one +at a time.</p> +<p>Given a project with configured workspaces, e.g:</p> +<pre><code>. ++-- package.json +`-- packages + +-- a + | `-- package.json + +-- b + | `-- package.json + `-- c + `-- package.json +</code></pre> +<p>Assuming the workspace configuration is properly set up at the root level +<code>package.json</code> file. e.g:</p> +<pre><code>{ + "workspaces": [ "./packages/*" ] +} +</code></pre> +<p>You can execute an arbitrary command from a package in the context of each of +the configured workspaces when using the <code>workspaces</code> configuration options, +in this example we’re using <strong>eslint</strong> to lint any js file found within each +workspace folder:</p> +<pre><code>npm exec -ws -- eslint ./*.js +</code></pre> +<h4 id="filtering-workspaces">Filtering workspaces</h4> +<p>It’s also possible to execute a command in a single workspace using the +<code>workspace</code> config along with a name or directory path:</p> +<pre><code>npm exec --workspace=a -- eslint ./*.js +</code></pre> +<p>The <code>workspace</code> config can also be specified multiple times in order to run a +specific script in the context of multiple workspaces. When defining values for +the <code>workspace</code> config in the command line, it also possible to use <code>-w</code> as a +shorthand, e.g:</p> +<pre><code>npm exec -w a -w b -- eslint ./*.js +</code></pre> +<p>This last command will run the <code>eslint</code> command in both <code>./packages/a</code> and +<code>./packages/b</code> folders.</p> <h3 id="compatibility-with-older-npx-versions">Compatibility with Older npx Versions</h3> <p>The <code>npx</code> binary was rewritten in npm v7.0.0, and the standalone <code>npx</code> package deprecated at that time. <code>npx</code> uses the <code>npm exec</code> @@ -287,6 +331,29 @@ requested from the server. To force full offline mode, use <code>offline</code>. <h4 id="offline">offline</h4> <p>Forces full offline mode. Any packages not locally cached will result in an error.</p> +<h4 id="workspace">workspace</h4> +<ul> +<li>Alias: <code>-w</code></li> +<li>Type: Array</li> +<li>Default: <code>[]</code></li> +</ul> +<p>Enable running scripts in the context of workspaces while also filtering by +the provided names or paths provided.</p> +<p>Valid values for the <code>workspace</code> config are either:</p> +<ul> +<li>Workspace names</li> +<li>Path to a workspace directory</li> +<li>Path to a parent workspace directory (will result to selecting all of the +children workspaces)</li> +</ul> +<h4 id="workspaces">workspaces</h4> +<ul> +<li>Alias: <code>-ws</code></li> +<li>Type: Boolean</li> +<li>Default: <code>false</code></li> +</ul> +<p>Run scripts in the context of all configured workspaces for the current +project.</p> <h3 id="see-also">See Also</h3> <ul> <li><a href="../commands/npm-run-script.html">npm run-script</a></li> diff --git a/deps/npm/docs/output/commands/npm-explore.html b/deps/npm/docs/output/commands/npm-explore.html index 0bb3505022..cd52ff96a6 100644 --- a/deps/npm/docs/output/commands/npm-explore.html +++ b/deps/npm/docs/output/commands/npm-explore.html @@ -147,6 +147,7 @@ npm command-line interface <div id="_content"><h3 id="synopsis">Synopsis</h3> <pre lang="bash"><code>npm explore <pkg> [ -- <command>] </code></pre> +<p>Note: This command is unaware of workspaces.</p> <h3 id="description">Description</h3> <p>Spawn a subshell in the directory of the installed package specified.</p> <p>If a command is specified, then it is run in the subshell, which then diff --git a/deps/npm/docs/output/commands/npm-find-dupes.html b/deps/npm/docs/output/commands/npm-find-dupes.html new file mode 100644 index 0000000000..32d8993b99 --- /dev/null +++ b/deps/npm/docs/output/commands/npm-find-dupes.html @@ -0,0 +1,174 @@ +<html><head> +<title>npm-find-dupes</title> +<style> +body { + background-color: #ffffff; + color: #24292e; + + margin: 0; + + line-height: 1.5; + + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; +} +#rainbar { + height: 10px; + background-image: linear-gradient(139deg, #fb8817, #ff4b01, #c12127, #e02aff); +} + +a { + text-decoration: none; + color: #0366d6; +} +a:hover { + text-decoration: underline; +} + +pre { + margin: 1em 0px; + padding: 1em; + border: solid 1px #e1e4e8; + border-radius: 6px; + + display: block; + overflow: auto; + + white-space: pre; + + background-color: #f6f8fa; + color: #393a34; +} +code { + font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace; + font-size: 85%; + padding: 0.2em 0.4em; + background-color: #f6f8fa; + color: #393a34; +} +pre > code { + padding: 0; + background-color: inherit; + color: inherit; +} +h1, h2, h3 { + font-weight: 600; +} + +#logobar { + background-color: #333333; + margin: 0 auto; + padding: 1em 4em; +} +#logobar .logo { + float: left; +} +#logobar .title { + font-weight: 600; + color: #dddddd; + float: left; + margin: 5px 0 0 1em; +} +#logobar:after { + content: ""; + display: block; + clear: both; +} + +#content { + margin: 0 auto; + padding: 0 4em; +} + +#table_of_contents > h2 { + font-size: 1.17em; +} +#table_of_contents ul:first-child { + border: solid 1px #e1e4e8; + border-radius: 6px; + padding: 1em; + background-color: #f6f8fa; + color: #393a34; +} +#table_of_contents ul { + list-style-type: none; + padding-left: 1.5em; +} +#table_of_contents li { + font-size: 0.9em; +} +#table_of_contents li a { + color: #000000; +} + +header.title { + border-bottom: solid 1px #e1e4e8; +} +header.title > h1 { + margin-bottom: 0.25em; +} +header.title > .description { + display: block; + margin-bottom: 0.5em; + line-height: 1; +} + +footer#edit { + border-top: solid 1px #e1e4e8; + margin: 3em 0 4em 0; + padding-top: 2em; +} +</style> +</head> +<body> +<div id="banner"> +<div id="rainbar"></div> +<div id="logobar"> +<svg class="logo" role="img" height="32" width="32" viewBox="0 0 700 700"> +<polygon fill="#cb0000" points="0,700 700,700 700,0 0,0"></polygon> +<polygon fill="#ffffff" points="150,550 350,550 350,250 450,250 450,550 550,550 550,150 150,150"></polygon> +</svg> +<div class="title"> +npm command-line interface +</div> +</div> +</div> + +<section id="content"> +<header class="title"> +<h1 id="npm-find-dupes">npm-find-dupes</h1> +<span class="description">Find duplication in the package tree</span> +</header> + +<section id="table_of_contents"> +<h2 id="table-of-contents">Table of contents</h2> +<div id="_table_of_contents"><ul><li><a href="#synopsis">Synopsis</a></li><li><a href="#description">Description</a></li><li><a href="#see-also">See Also</a></li></ul></div> +</section> + +<div id="_content"><h3 id="synopsis">Synopsis</h3> +<pre lang="bash"><code>npm find-dupes +</code></pre> +<h3 id="description">Description</h3> +<p>Runs <code>npm dedupe</code> in <code>--dry-run</code> mode, making npm only output the +duplications, without actually changing the package tree.</p> +<h3 id="see-also">See Also</h3> +<ul> +<li><a href="../cli-commands/dedupe.html">npm dedupe</a></li> +<li><a href="../cli-commands/ls.html">npm ls</a></li> +<li><a href="../cli-commands/update.html">npm update</a></li> +<li><a href="../cli-commands/install.html">npm install</a></li> +</ul> +</div> + +<footer id="edit"> +<a href="https://github.com/npm/cli/edit/latest/docs/content/commands/npm-find-dupes.md"> +<svg role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentcolor" style="vertical-align: text-bottom; margin-right: 0.3em;"> +<path fill-rule="evenodd" d="M11.013 1.427a1.75 1.75 0 012.474 0l1.086 1.086a1.75 1.75 0 010 2.474l-8.61 8.61c-.21.21-.47.364-.756.445l-3.251.93a.75.75 0 01-.927-.928l.929-3.25a1.75 1.75 0 01.445-.758l8.61-8.61zm1.414 1.06a.25.25 0 00-.354 0L10.811 3.75l1.439 1.44 1.263-1.263a.25.25 0 000-.354l-1.086-1.086zM11.189 6.25L9.75 4.81l-6.286 6.287a.25.25 0 00-.064.108l-.558 1.953 1.953-.558a.249.249 0 00.108-.064l6.286-6.286z"></path> +</svg> +Edit this page on GitHub +</a> +</footer> +</section> + + + +</body></html>
\ No newline at end of file diff --git a/deps/npm/docs/output/commands/npm-help-search.html b/deps/npm/docs/output/commands/npm-help-search.html index 00ebe9bf6c..77456ef549 100644 --- a/deps/npm/docs/output/commands/npm-help-search.html +++ b/deps/npm/docs/output/commands/npm-help-search.html @@ -147,6 +147,7 @@ npm command-line interface <div id="_content"><h3 id="synopsis">Synopsis</h3> <pre lang="bash"><code>npm help-search <text> </code></pre> +<p>Note: This command is unaware of workspaces.</p> <h3 id="description">Description</h3> <p>This command will search the npm markdown documentation files for the terms provided, and then list the results, sorted by relevance.</p> diff --git a/deps/npm/docs/output/commands/npm-help.html b/deps/npm/docs/output/commands/npm-help.html index e4f4226a5d..0327d1788f 100644 --- a/deps/npm/docs/output/commands/npm-help.html +++ b/deps/npm/docs/output/commands/npm-help.html @@ -147,6 +147,7 @@ npm command-line interface <div id="_content"><h3 id="synopsis">Synopsis</h3> <pre lang="bash"><code>npm help <term> [<terms..>] </code></pre> +<p>Note: This command is unaware of workspaces.</p> <h3 id="description">Description</h3> <p>If supplied a topic, then show the appropriate documentation page.</p> <p>If the topic does not exist, or if multiple terms are provided, then npm diff --git a/deps/npm/docs/output/commands/npm-hook.html b/deps/npm/docs/output/commands/npm-hook.html index dd7015df1b..2921e7e12c 100644 --- a/deps/npm/docs/output/commands/npm-hook.html +++ b/deps/npm/docs/output/commands/npm-hook.html @@ -150,6 +150,7 @@ npm hook add <entity> <url> <secret> npm hook update <id> <url> [secret] npm hook rm <id> </code></pre> +<p>Note: This command is unaware of workspaces.</p> <h3 id="description">Description</h3> <p>Allows you to manage <a href="https://blog.npmjs.org/post/145260155635/introducing-hooks-get-notifications-of-npm">npm hooks</a>, diff --git a/deps/npm/docs/output/commands/npm-init.html b/deps/npm/docs/output/commands/npm-init.html index 3abf8e967b..62dc20093b 100644 --- a/deps/npm/docs/output/commands/npm-init.html +++ b/deps/npm/docs/output/commands/npm-init.html @@ -136,7 +136,7 @@ npm command-line interface <section id="content"> <header class="title"> <h1 id="npm-init">npm-init</h1> -<span class="description">create a package.json file</span> +<span class="description">Create a package.json file</span> </header> <section id="table_of_contents"> diff --git a/deps/npm/docs/output/commands/npm-logout.html b/deps/npm/docs/output/commands/npm-logout.html index 02de412c73..4e19888ee8 100644 --- a/deps/npm/docs/output/commands/npm-logout.html +++ b/deps/npm/docs/output/commands/npm-logout.html @@ -147,6 +147,7 @@ npm command-line interface <div id="_content"><h3 id="synopsis">Synopsis</h3> <pre lang="bash"><code>npm logout [--registry=<url>] [--scope=<@scope>] </code></pre> +<p>Note: This command is unaware of workspaces.</p> <h3 id="description">Description</h3> <p>When logged into a registry that supports token-based authentication, tell the server to end this token’s session. This will invalidate the token diff --git a/deps/npm/docs/output/commands/npm-ls.html b/deps/npm/docs/output/commands/npm-ls.html index ae1e1a84c7..454c556744 100644 --- a/deps/npm/docs/output/commands/npm-ls.html +++ b/deps/npm/docs/output/commands/npm-ls.html @@ -159,7 +159,7 @@ tree at all, use <a href="../commands/npm-explain.html"><code>npm explain</code> the results to only the paths to the packages named. Note that nested packages will <em>also</em> show the paths to the specified packages. For example, running <code>npm ls promzard</code> in npm’s source tree will show:</p> -<pre lang="bash"><code>npm@7.6.3 /path/to/npm +<pre lang="bash"><code>npm@7.7.0 /path/to/npm └─┬ init-package-json@0.0.4 └── promzard@0.1.5 </code></pre> diff --git a/deps/npm/docs/output/commands/npm-org.html b/deps/npm/docs/output/commands/npm-org.html index d97f638b22..50c0995650 100644 --- a/deps/npm/docs/output/commands/npm-org.html +++ b/deps/npm/docs/output/commands/npm-org.html @@ -149,6 +149,7 @@ npm command-line interface npm org rm <orgname> <username> npm org ls <orgname> [<username>] </code></pre> +<p>Note: This command is unaware of workspaces.</p> <h3 id="example">Example</h3> <p>Add a new developer to an org:</p> <pre lang="bash"><code>$ npm org set my-org @mx-smith diff --git a/deps/npm/docs/output/commands/npm-owner.html b/deps/npm/docs/output/commands/npm-owner.html index 77f072da40..ada60ea095 100644 --- a/deps/npm/docs/output/commands/npm-owner.html +++ b/deps/npm/docs/output/commands/npm-owner.html @@ -151,6 +151,7 @@ npm owner ls [<@scope>/]<pkg> aliases: author </code></pre> +<p>Note: This command is unaware of workspaces.</p> <h3 id="description">Description</h3> <p>Manage ownership of published packages.</p> <ul> diff --git a/deps/npm/docs/output/commands/npm-ping.html b/deps/npm/docs/output/commands/npm-ping.html index e00fb30a01..ca124a1859 100644 --- a/deps/npm/docs/output/commands/npm-ping.html +++ b/deps/npm/docs/output/commands/npm-ping.html @@ -147,6 +147,7 @@ npm command-line interface <div id="_content"><h3 id="synopsis">Synopsis</h3> <pre lang="bash"><code>npm ping [--registry <registry>] </code></pre> +<p>Note: This command is unaware of workspaces.</p> <h3 id="description">Description</h3> <p>Ping the configured or given npm registry and verify authentication. If it works it will output something like:</p> diff --git a/deps/npm/docs/output/commands/npm-prefix.html b/deps/npm/docs/output/commands/npm-prefix.html index a330dfd1c3..493a1f8950 100644 --- a/deps/npm/docs/output/commands/npm-prefix.html +++ b/deps/npm/docs/output/commands/npm-prefix.html @@ -147,6 +147,7 @@ npm command-line interface <div id="_content"><h3 id="synopsis">Synopsis</h3> <pre lang="bash"><code>npm prefix [-g] </code></pre> +<p>Note: This command is unaware of workspaces.</p> <h3 id="description">Description</h3> <p>Print the local prefix to standard output. This is the closest parent directory to contain a <code>package.json</code> file or <code>node_modules</code> directory, unless <code>-g</code> is diff --git a/deps/npm/docs/output/commands/npm-profile.html b/deps/npm/docs/output/commands/npm-profile.html index 91013567a2..f103446479 100644 --- a/deps/npm/docs/output/commands/npm-profile.html +++ b/deps/npm/docs/output/commands/npm-profile.html @@ -151,6 +151,7 @@ npm profile set password npm profile enable-2fa [auth-and-writes|auth-only] npm profile disable-2fa </code></pre> +<p>Note: This command is unaware of workspaces.</p> <h3 id="description">Description</h3> <p>Change your profile information on the registry. Note that this command depends on the registry implementation, so third-party registries may not diff --git a/deps/npm/docs/output/commands/npm-run-script.html b/deps/npm/docs/output/commands/npm-run-script.html index a78a434760..6fc343dfba 100644 --- a/deps/npm/docs/output/commands/npm-run-script.html +++ b/deps/npm/docs/output/commands/npm-run-script.html @@ -141,11 +141,13 @@ npm command-line interface <section id="table_of_contents"> <h2 id="table-of-contents">Table of contents</h2> -<div id="_table_of_contents"><ul><li><a href="#synopsis">Synopsis</a></li><li><a href="#description">Description</a></li><li><a href="#configuration">Configuration</a></li><ul><li><a href="#if-present">if-present</a></li><li><a href="#ignore-scripts">ignore-scripts</a></li><li><a href="#script-shell">script-shell</a></li><li><a href="#silent">silent</a></li></ul><li><a href="#see-also">See Also</a></li></ul></div> +<div id="_table_of_contents"><ul><li><a href="#synopsis">Synopsis</a></li><li><a href="#description">Description</a></li><li><a href="#workspaces-support">Workspaces support</a></li><ul><li><a href="#filtering-workspaces">Filtering workspaces</a></li></ul><li><a href="#configuration">Configuration</a></li><ul><li><a href="#if-present">if-present</a></li><li><a href="#ignore-scripts">ignore-scripts</a></li><li><a href="#script-shell">script-shell</a></li><li><a href="#silent">silent</a></li><li><a href="#workspace">workspace</a></li><li><a href="#workspaces">workspaces</a></li></ul><li><a href="#see-also">See Also</a></li></ul></div> </section> <div id="_content"><h3 id="synopsis">Synopsis</h3> <pre lang="bash"><code>npm run-script <command> [--if-present] [--silent] [-- <args>] +npm run-script <command> [--workspace=<workspace-name>] +npm run-script <command> [--workspaces] aliases: run, rum, urn </code></pre> @@ -196,6 +198,45 @@ found in the <code>PATH</code>.</p> <p>If you try to run a script without having a <code>node_modules</code> directory and it fails, you will be given a warning to run <code>npm install</code>, just in case you’ve forgotten.</p> +<h3 id="workspaces-support">Workspaces support</h3> +<p>You may use the <code>workspace</code> or <code>workspaces</code> configs in order to run an +arbitrary command from a package’s <code>"scripts"</code> object in the context of the +specified workspaces. If no <code>"command"</code> is provided, it will list the available +scripts for each of these configured workspaces.</p> +<p>Given a project with configured workspaces, e.g:</p> +<pre><code>. ++-- package.json +`-- packages + +-- a + | `-- package.json + +-- b + | `-- package.json + `-- c + `-- package.json +</code></pre> +<p>Assuming the workspace configuration is properly set up at the root level +<code>package.json</code> file. e.g:</p> +<pre><code>{ + "workspaces": [ "./packages/*" ] +} +</code></pre> +<p>And that each of the configured workspaces has a configured <code>test</code> script, +we can run tests in all of them using the <code>workspaces</code> config:</p> +<pre><code>npm test --workspaces +</code></pre> +<h4 id="filtering-workspaces">Filtering workspaces</h4> +<p>It’s also possible to run a script in a single workspace using the <code>workspace</code> +config along with a name or directory path:</p> +<pre><code>npm test --workspace=a +</code></pre> +<p>The <code>workspace</code> config can also be specified multiple times in order to run a +specific script in the context of multiple workspaces. When defining values for +the <code>workspace</code> config in the command line, it also possible to use <code>-w</code> as a +shorthand, e.g:</p> +<pre><code>npm test -w a -w b +</code></pre> +<p>This last command will run <code>test</code> in both <code>./packages/a</code> and <code>./packages/b</code> +packages.</p> <h3 id="configuration">Configuration</h3> <h4 id="if-present">if-present</h4> <ul> @@ -224,6 +265,29 @@ to <code>/bin/sh</code> on Unix, defaults to <code>env.comspec</code> or <code>c <li>Default: false</li> </ul> <p>You can use the <code>--silent</code> flag to prevent showing <code>npm ERR!</code> output on error.</p> +<h4 id="workspace">workspace</h4> +<ul> +<li>Alias: <code>-w</code></li> +<li>Type: Array</li> +<li>Default: <code>[]</code></li> +</ul> +<p>Enable running scripts in the context of workspaces while also filtering by +the provided names or paths provided.</p> +<p>Valid values for the <code>workspace</code> config are either:</p> +<ul> +<li>Workspace names</li> +<li>Path to a workspace directory</li> +<li>Path to a parent workspace directory (will result to selecting all of the +children workspaces)</li> +</ul> +<h4 id="workspaces">workspaces</h4> +<ul> +<li>Alias: <code>-ws</code></li> +<li>Type: Boolean</li> +<li>Default: <code>false</code></li> +</ul> +<p>Run scripts in the context of all configured workspaces for the current +project.</p> <h3 id="see-also">See Also</h3> <ul> <li><a href="../using-npm/scripts.html">npm scripts</a></li> diff --git a/deps/npm/docs/output/commands/npm-search.html b/deps/npm/docs/output/commands/npm-search.html index bd15223050..974c163ae1 100644 --- a/deps/npm/docs/output/commands/npm-search.html +++ b/deps/npm/docs/output/commands/npm-search.html @@ -149,6 +149,7 @@ npm command-line interface aliases: s, se, find </code></pre> +<p>Note: This command is unaware of workspaces.</p> <h3 id="description">Description</h3> <p>Search the registry for packages matching the search terms. <code>npm search</code> performs a linear, incremental, lexically-ordered search through package diff --git a/deps/npm/docs/output/commands/npm-shrinkwrap.html b/deps/npm/docs/output/commands/npm-shrinkwrap.html index 63057cbe95..e2c09e8176 100644 --- a/deps/npm/docs/output/commands/npm-shrinkwrap.html +++ b/deps/npm/docs/output/commands/npm-shrinkwrap.html @@ -147,6 +147,7 @@ npm command-line interface <div id="_content"><h3 id="synopsis">Synopsis</h3> <pre lang="bash"><code>npm shrinkwrap </code></pre> +<p>Note: This command is unaware of workspaces.</p> <h3 id="description">Description</h3> <p>This command repurposes <code>package-lock.json</code> into a publishable <code>npm-shrinkwrap.json</code> or simply creates a new one. The file created and diff --git a/deps/npm/docs/output/commands/npm-star.html b/deps/npm/docs/output/commands/npm-star.html index 1f92bc2697..8589a50c02 100644 --- a/deps/npm/docs/output/commands/npm-star.html +++ b/deps/npm/docs/output/commands/npm-star.html @@ -147,6 +147,7 @@ npm command-line interface <div id="_content"><h3 id="synopsis">Synopsis</h3> <pre lang="bash"><code>npm star [<pkg>...] </code></pre> +<p>Note: This command is unaware of workspaces.</p> <h3 id="description">Description</h3> <p>“Starring” a package means that you have some interest in it. It’s a vaguely positive way to show that you care.</p> diff --git a/deps/npm/docs/output/commands/npm-stars.html b/deps/npm/docs/output/commands/npm-stars.html index fb80fc0cde..c4aa2a194c 100644 --- a/deps/npm/docs/output/commands/npm-stars.html +++ b/deps/npm/docs/output/commands/npm-stars.html @@ -147,6 +147,7 @@ npm command-line interface <div id="_content"><h3 id="synopsis">Synopsis</h3> <pre lang="bash"><code>npm stars [<user>] </code></pre> +<p>Note: This command is unaware of workspaces.</p> <h3 id="description">Description</h3> <p>If you have starred a lot of neat things and want to find them again quickly this command lets you do just that.</p> diff --git a/deps/npm/docs/output/commands/npm-team.html b/deps/npm/docs/output/commands/npm-team.html index bf29f4a5ea..586fd52721 100644 --- a/deps/npm/docs/output/commands/npm-team.html +++ b/deps/npm/docs/output/commands/npm-team.html @@ -153,6 +153,7 @@ npm team rm <scope:team> <user> npm team ls <scope>|<scope:team> </code></pre> +<p>Note: This command is unaware of workspaces.</p> <h3 id="description">Description</h3> <p>Used to manage teams in organizations, and change team memberships. Does not handle permissions for packages.</p> diff --git a/deps/npm/docs/output/commands/npm-token.html b/deps/npm/docs/output/commands/npm-token.html index de92432475..d913acdb54 100644 --- a/deps/npm/docs/output/commands/npm-token.html +++ b/deps/npm/docs/output/commands/npm-token.html @@ -149,6 +149,7 @@ npm command-line interface npm token create [--read-only] [--cidr=1.1.1.1/24,2.2.2.2/16] npm token revoke <id|token> </code></pre> +<p>Note: This command is unaware of workspaces.</p> <h3 id="description">Description</h3> <p>This lets you list, create and revoke authentication tokens.</p> <ul> diff --git a/deps/npm/docs/output/commands/npm-unstar.html b/deps/npm/docs/output/commands/npm-unstar.html index 77c7cd3495..3da3d28cbb 100644 --- a/deps/npm/docs/output/commands/npm-unstar.html +++ b/deps/npm/docs/output/commands/npm-unstar.html @@ -147,6 +147,7 @@ npm command-line interface <div id="_content"><h3 id="synopsis">Synopsis</h3> <pre lang="bash"><code>npm unstar [<pkg>...] </code></pre> +<p>Note: This command is unaware of workspaces.</p> <h3 id="description">Description</h3> <p>“Unstarring” a package is the opposite of <a href="../commands/npm-star.html"><code>npm star</code></a>, it removes an item from your list of favorite packages.</p> diff --git a/deps/npm/docs/output/commands/npm-whoami.html b/deps/npm/docs/output/commands/npm-whoami.html index e703e1665f..869e1351bc 100644 --- a/deps/npm/docs/output/commands/npm-whoami.html +++ b/deps/npm/docs/output/commands/npm-whoami.html @@ -147,6 +147,7 @@ npm command-line interface <div id="_content"><h3 id="synopsis">Synopsis</h3> <pre lang="bash"><code>npm whoami [--registry <registry>] </code></pre> +<p>Note: This command is unaware of workspaces.</p> <h3 id="description">Description</h3> <p>Print the <code>username</code> config to standard output.</p> <h3 id="see-also">See Also</h3> diff --git a/deps/npm/docs/output/commands/npm.html b/deps/npm/docs/output/commands/npm.html index c2d07cf5ca..f55659d9ee 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.6.3</p> +<p>7.7.0</p> <h3 id="description">Description</h3> <p>npm is the package manager for the Node JavaScript platform. It puts modules in place so that node can find them, and manages dependency diff --git a/deps/npm/docs/output/configuring-npm/package-json.html b/deps/npm/docs/output/configuring-npm/package-json.html index 114c18d61e..9c58ebf85f 100644 --- a/deps/npm/docs/output/configuring-npm/package-json.html +++ b/deps/npm/docs/output/configuring-npm/package-json.html @@ -392,6 +392,7 @@ be returned.</p> <p>This should be a module relative to the root of your package folder.</p> <p>For most modules, it makes the most sense to have a main script and often not much else.</p> +<p>If <code>main</code> is not set it defaults to <code>index.js</code> in the packages root folder.</p> <h3 id="browser">browser</h3> <p>If your module is meant to be used client-side the browser field should be used instead of the main field. This is helpful to hint users that it might @@ -565,8 +566,7 @@ space-separated descriptors. Dependencies can also be identified with a tarball or git URL.</p> <p><strong>Please do not put test harnesses or transpilers or other “development” time tools in your <code>dependencies</code> object.</strong> See <code>devDependencies</code>, below.</p> -<p>See <a href="%5B/using-npm/semver%5D(https://github.com/npm/node-semver#versions)">semver</a> -for more details about specifying version ranges.</p> +<p>See <a href="../using-npm/semver#versions.html">semver</a> for more details about specifying version ranges.</p> <ul> <li><code>version</code> Must match <code>version</code> exactly</li> <li><code>>version</code> Must be greater than <code>version</code></li> diff --git a/deps/npm/docs/output/using-npm/config.html b/deps/npm/docs/output/using-npm/config.html index 9d6ba9b5a6..dc50eb72b7 100644 --- a/deps/npm/docs/output/using-npm/config.html +++ b/deps/npm/docs/output/using-npm/config.html @@ -141,7 +141,7 @@ npm command-line interface <section id="table_of_contents"> <h2 id="table-of-contents">Table of contents</h2> -<div id="_table_of_contents"><ul><li><a href="#description">Description</a></li><ul><li><a href="#command-line-flags">Command Line Flags</a></li><li><a href="#environment-variables">Environment Variables</a></li><li><a href="#npmrc-files">npmrc Files</a></li><li><a href="#default-configs">Default Configs</a></li></ul><li><a href="#shorthands-and-other-cli-niceties">Shorthands and Other CLI Niceties</a></li><li><a href="#config-settings">Config Settings</a></li><ul><li><a href="#access">access</a></li><li><a href="#all">all</a></li><li><a href="#allow-same-version">allow-same-version</a></li><li><a href="#always-auth">always-auth</a></li><li><a href="#also">also</a></li><li><a href="#audit">audit</a></li><li><a href="#audit-level">audit-level</a></li><li><a href="#auth-type">auth-type</a></li><li><a href="#before">before</a></li><li><a href="#bin-links">bin-links</a></li><li><a href="#browser">browser</a></li><li><a href="#ca">ca</a></li><li><a href="#cafile">cafile</a></li><li><a href="#cache">cache</a></li><li><a href="#cache-lock-stale">cache-lock-stale</a></li><li><a href="#cache-lock-retries">cache-lock-retries</a></li><li><a href="#cache-lock-wait">cache-lock-wait</a></li><li><a href="#cache-max">cache-max</a></li><li><a href="#cache-min">cache-min</a></li><li><a href="#call">call</a></li><li><a href="#cert">cert</a></li><li><a href="#cidr">cidr</a></li><li><a href="#commit-hooks">commit-hooks</a></li><li><a href="#color">color</a></li><li><a href="#depth">depth</a></li><li><a href="#description2">description</a></li><li><a href="#dev">dev</a></li><li><a href="#dry-run">dry-run</a></li><li><a href="#diff">diff</a></li><li><a href="#diff-name-only">diff-name-only</a></li><li><a href="#diff-unified">diff-unified</a></li><li><a href="#diff-ignore-all-space">diff-ignore-all-space</a></li><li><a href="#diff-no-prefix">diff-no-prefix</a></li><li><a href="#diff-src-prefix">diff-src-prefix</a></li><li><a href="#diff-dst-prefix">diff-dst-prefix</a></li><li><a href="#diff-text">diff-text</a></li><li><a href="#editor">editor</a></li><li><a href="#engine-strict">engine-strict</a></li><li><a href="#force">force</a></li><li><a href="#foreground-scripts">foreground-scripts</a></li><li><a href="#format-package-lock">format-package-lock</a></li><li><a href="#fund">fund</a></li><li><a href="#fetch-retries">fetch-retries</a></li><li><a href="#fetch-retry-factor">fetch-retry-factor</a></li><li><a href="#fetch-retry-mintimeout">fetch-retry-mintimeout</a></li><li><a href="#fetch-retry-maxtimeout">fetch-retry-maxtimeout</a></li><li><a href="#fetch-timeout">fetch-timeout</a></li><li><a href="#git">git</a></li><li><a href="#git-tag-version">git-tag-version</a></li><li><a href="#global">global</a></li><li><a href="#globalconfig">globalconfig</a></li><li><a href="#global-style">global-style</a></li><li><a href="#heading">heading</a></li><li><a href="#https-proxy">https-proxy</a></li><li><a href="#if-present">if-present</a></li><li><a href="#ignore-prepublish">ignore-prepublish</a></li><li><a href="#ignore-scripts">ignore-scripts</a></li><li><a href="#include">include</a></li><li><a href="#init-module">init-module</a></li><li><a href="#init-author-name">init-author-name</a></li><li><a href="#init-author-email">init-author-email</a></li><li><a href="#init-author-url">init-author-url</a></li><li><a href="#init-license">init-license</a></li><li><a href="#init-version">init-version</a></li><li><a href="#json">json</a></li><li><a href="#key">key</a></li><li><a href="#legacy-bundling">legacy-bundling</a></li><li><a href="#legacy-peer-deps">legacy-peer-deps</a></li><li><a href="#link">link</a></li><li><a href="#local-address">local-address</a></li><li><a href="#loglevel">loglevel</a></li><li><a href="#logs-max">logs-max</a></li><li><a href="#long">long</a></li><li><a href="#maxsockets">maxsockets</a></li><li><a href="#message">message</a></li><li><a href="#node-options">node-options</a></li><li><a href="#node-version">node-version</a></li><li><a href="#noproxy">noproxy</a></li><li><a href="#offline">offline</a></li><li><a href="#only">only</a></li><li><a href="#optional">optional</a></li><li><a href="#otp">otp</a></li><li><a href="#package-lock">package-lock</a></li><li><a href="#package-lock-only">package-lock-only</a></li><li><a href="#parseable">parseable</a></li><li><a href="#prefer-offline">prefer-offline</a></li><li><a href="#prefer-online">prefer-online</a></li><li><a href="#prefix">prefix</a></li><li><a href="#preid">preid</a></li><li><a href="#production">production</a></li><li><a href="#progress">progress</a></li><li><a href="#proxy">proxy</a></li><li><a href="#read-only">read-only</a></li><li><a href="#rebuild-bundle">rebuild-bundle</a></li><li><a href="#registry">registry</a></li><li><a href="#rollback">rollback</a></li><li><a href="#save">save</a></li><li><a href="#save-bundle">save-bundle</a></li><li><a href="#save-prod">save-prod</a></li><li><a href="#save-dev">save-dev</a></li><li><a href="#save-exact">save-exact</a></li><li><a href="#save-optional">save-optional</a></li><li><a href="#save-prefix">save-prefix</a></li><li><a href="#scope">scope</a></li><li><a href="#script-shell">script-shell</a></li><li><a href="#scripts-prepend-node-path">scripts-prepend-node-path</a></li><li><a href="#searchexclude">searchexclude</a></li><li><a href="#searchopts">searchopts</a></li><li><a href="#searchlimit">searchlimit</a></li><li><a href="#searchstaleness">searchstaleness</a></li><li><a href="#shell">shell</a></li><li><a href="#shrinkwrap">shrinkwrap</a></li><li><a href="#sign-git-commit">sign-git-commit</a></li><li><a href="#sign-git-tag">sign-git-tag</a></li><li><a href="#sso-poll-frequency">sso-poll-frequency</a></li><li><a href="#sso-type">sso-type</a></li><li><a href="#strict-peer-deps">strict-peer-deps</a></li><li><a href="#strict-ssl">strict-ssl</a></li><li><a href="#tag">tag</a></li><li><a href="#tag-version-prefix">tag-version-prefix</a></li><li><a href="#timing">timing</a></li><li><a href="#tmp">tmp</a></li><li><a href="#unicode">unicode</a></li><li><a href="#update-notifier">update-notifier</a></li><li><a href="#usage">usage</a></li><li><a href="#userconfig">userconfig</a></li><li><a href="#umask">umask</a></li><li><a href="#user-agent">user-agent</a></li><li><a href="#version">version</a></li><li><a href="#versions">versions</a></li><li><a href="#viewer">viewer</a></li></ul><li><a href="#see-also">See also</a></li></ul></div> +<div id="_table_of_contents"><ul><li><a href="#description">Description</a></li><ul><li><a href="#command-line-flags">Command Line Flags</a></li><li><a href="#environment-variables">Environment Variables</a></li><li><a href="#npmrc-files">npmrc Files</a></li><li><a href="#default-configs">Default Configs</a></li></ul><li><a href="#shorthands-and-other-cli-niceties">Shorthands and Other CLI Niceties</a></li><li><a href="#config-settings">Config Settings</a></li><ul><li><a href="#auth"><code>_auth</code></a></li><li><a href="#access"><code>access</code></a></li><li><a href="#all"><code>all</code></a></li><li><a href="#allow-same-version"><code>allow-same-version</code></a></li><li><a href="#always-auth"><code>always-auth</code></a></li><li><a href="#audit"><code>audit</code></a></li><li><a href="#audit-level"><code>audit-level</code></a></li><li><a href="#before"><code>before</code></a></li><li><a href="#bin-links"><code>bin-links</code></a></li><li><a href="#browser"><code>browser</code></a></li><li><a href="#ca"><code>ca</code></a></li><li><a href="#cache"><code>cache</code></a></li><li><a href="#cafile"><code>cafile</code></a></li><li><a href="#call"><code>call</code></a></li><li><a href="#cert"><code>cert</code></a></li><li><a href="#ci-name"><code>ci-name</code></a></li><li><a href="#cidr"><code>cidr</code></a></li><li><a href="#color"><code>color</code></a></li><li><a href="#commit-hooks"><code>commit-hooks</code></a></li><li><a href="#depth"><code>depth</code></a></li><li><a href="#description2"><code>description</code></a></li><li><a href="#diff"><code>diff</code></a></li><li><a href="#diff-dst-prefix"><code>diff-dst-prefix</code></a></li><li><a href="#diff-ignore-all-space"><code>diff-ignore-all-space</code></a></li><li><a href="#diff-name-only"><code>diff-name-only</code></a></li><li><a href="#diff-no-prefix"><code>diff-no-prefix</code></a></li><li><a href="#diff-src-prefix"><code>diff-src-prefix</code></a></li><li><a href="#diff-text"><code>diff-text</code></a></li><li><a href="#diff-unified"><code>diff-unified</code></a></li><li><a href="#dry-run"><code>dry-run</code></a></li><li><a href="#editor"><code>editor</code></a></li><li><a href="#engine-strict"><code>engine-strict</code></a></li><li><a href="#fetch-retries"><code>fetch-retries</code></a></li><li><a href="#fetch-retry-factor"><code>fetch-retry-factor</code></a></li><li><a href="#fetch-retry-maxtimeout"><code>fetch-retry-maxtimeout</code></a></li><li><a href="#fetch-retry-mintimeout"><code>fetch-retry-mintimeout</code></a></li><li><a href="#fetch-timeout"><code>fetch-timeout</code></a></li><li><a href="#force"><code>force</code></a></li><li><a href="#foreground-scripts"><code>foreground-scripts</code></a></li><li><a href="#format-package-lock"><code>format-package-lock</code></a></li><li><a href="#fund"><code>fund</code></a></li><li><a href="#git"><code>git</code></a></li><li><a href="#git-tag-version"><code>git-tag-version</code></a></li><li><a href="#global"><code>global</code></a></li><li><a href="#global-style"><code>global-style</code></a></li><li><a href="#globalconfig"><code>globalconfig</code></a></li><li><a href="#heading"><code>heading</code></a></li><li><a href="#https-proxy"><code>https-proxy</code></a></li><li><a href="#if-present"><code>if-present</code></a></li><li><a href="#ignore-scripts"><code>ignore-scripts</code></a></li><li><a href="#include"><code>include</code></a></li><li><a href="#include-staged"><code>include-staged</code></a></li><li><a href="#init-author-email"><code>init-author-email</code></a></li><li><a href="#init-author-name"><code>init-author-name</code></a></li><li><a href="#init-author-url"><code>init-author-url</code></a></li><li><a href="#init-license"><code>init-license</code></a></li><li><a href="#init-module"><code>init-module</code></a></li><li><a href="#init-version"><code>init-version</code></a></li><li><a href="#json"><code>json</code></a></li><li><a href="#key"><code>key</code></a></li><li><a href="#legacy-bundling"><code>legacy-bundling</code></a></li><li><a href="#legacy-peer-deps"><code>legacy-peer-deps</code></a></li><li><a href="#link"><code>link</code></a></li><li><a href="#local-address"><code>local-address</code></a></li><li><a href="#loglevel"><code>loglevel</code></a></li><li><a href="#logs-max"><code>logs-max</code></a></li><li><a href="#long"><code>long</code></a></li><li><a href="#maxsockets"><code>maxsockets</code></a></li><li><a href="#message"><code>message</code></a></li><li><a href="#node-options"><code>node-options</code></a></li><li><a href="#node-version"><code>node-version</code></a></li><li><a href="#noproxy"><code>noproxy</code></a></li><li><a href="#npm-version"><code>npm-version</code></a></li><li><a href="#offline"><code>offline</code></a></li><li><a href="#omit"><code>omit</code></a></li><li><a href="#otp"><code>otp</code></a></li><li><a href="#package"><code>package</code></a></li><li><a href="#package-lock"><code>package-lock</code></a></li><li><a href="#package-lock-only"><code>package-lock-only</code></a></li><li><a href="#parseable"><code>parseable</code></a></li><li><a href="#prefer-offline"><code>prefer-offline</code></a></li><li><a href="#prefer-online"><code>prefer-online</code></a></li><li><a href="#prefix"><code>prefix</code></a></li><li><a href="#preid"><code>preid</code></a></li><li><a href="#progress"><code>progress</code></a></li><li><a href="#proxy"><code>proxy</code></a></li><li><a href="#read-only"><code>read-only</code></a></li><li><a href="#rebuild-bundle"><code>rebuild-bundle</code></a></li><li><a href="#registry"><code>registry</code></a></li><li><a href="#save"><code>save</code></a></li><li><a href="#save-bundle"><code>save-bundle</code></a></li><li><a href="#save-dev"><code>save-dev</code></a></li><li><a href="#save-exact"><code>save-exact</code></a></li><li><a href="#save-optional"><code>save-optional</code></a></li><li><a href="#save-peer"><code>save-peer</code></a></li><li><a href="#save-prefix"><code>save-prefix</code></a></li><li><a href="#save-prod"><code>save-prod</code></a></li><li><a href="#scope"><code>scope</code></a></li><li><a href="#script-shell"><code>script-shell</code></a></li><li><a href="#searchexclude"><code>searchexclude</code></a></li><li><a href="#searchlimit"><code>searchlimit</code></a></li><li><a href="#searchopts"><code>searchopts</code></a></li><li><a href="#searchstaleness"><code>searchstaleness</code></a></li><li><a href="#shell"><code>shell</code></a></li><li><a href="#sign-git-commit"><code>sign-git-commit</code></a></li><li><a href="#sign-git-tag"><code>sign-git-tag</code></a></li><li><a href="#strict-peer-deps"><code>strict-peer-deps</code></a></li><li><a href="#strict-ssl"><code>strict-ssl</code></a></li><li><a href="#tag"><code>tag</code></a></li><li><a href="#tag-version-prefix"><code>tag-version-prefix</code></a></li><li><a href="#timing"><code>timing</code></a></li><li><a href="#umask"><code>umask</code></a></li><li><a href="#unicode"><code>unicode</code></a></li><li><a href="#update-notifier"><code>update-notifier</code></a></li><li><a href="#usage"><code>usage</code></a></li><li><a href="#user-agent"><code>user-agent</code></a></li><li><a href="#userconfig"><code>userconfig</code></a></li><li><a href="#version"><code>version</code></a></li><li><a href="#versions"><code>versions</code></a></li><li><a href="#viewer"><code>viewer</code></a></li><li><a href="#which"><code>which</code></a></li><li><a href="#workspace"><code>workspace</code></a></li><li><a href="#workspaces"><code>workspaces</code></a></li><li><a href="#yes"><code>yes</code></a></li><li><a href="#also"><code>also</code></a></li><li><a href="#auth-type"><code>auth-type</code></a></li><li><a href="#cache-max"><code>cache-max</code></a></li><li><a href="#cache-min"><code>cache-min</code></a></li><li><a href="#initauthoremail"><code>init.author.email</code></a></li><li><a href="#initauthorname"><code>init.author.name</code></a></li><li><a href="#initauthorurl"><code>init.author.url</code></a></li><li><a href="#initlicense"><code>init.license</code></a></li><li><a href="#initmodule"><code>init.module</code></a></li><li><a href="#initversion"><code>init.version</code></a></li><li><a href="#only"><code>only</code></a></li><li><a href="#optional"><code>optional</code></a></li><li><a href="#production"><code>production</code></a></li><li><a href="#shrinkwrap"><code>shrinkwrap</code></a></li><li><a href="#sso-poll-frequency"><code>sso-poll-frequency</code></a></li><li><a href="#sso-type"><code>sso-type</code></a></li><li><a href="#tmp"><code>tmp</code></a></li></ul><li><a href="#see-also">See also</a></li></ul></div> </section> <div id="_content"><h3 id="description">Description</h3> @@ -185,32 +185,49 @@ CLI option <code>--globalconfig</code> or environment variable <code>$NPM_CONFIG internal to npm, and are defaults if nothing else is specified.</p> <h3 id="shorthands-and-other-cli-niceties">Shorthands and Other CLI Niceties</h3> <p>The following shorthands are parsed on the command-line:</p> +<!-- raw HTML omitted --> +<!-- raw HTML omitted --> <ul> -<li><code>-v</code>: <code>--version</code></li> -<li><code>-h</code>, <code>-?</code>, <code>--help</code>, <code>-H</code>: <code>--usage</code></li> -<li><code>-s</code>, <code>--silent</code>: <code>--loglevel silent</code></li> -<li><code>-q</code>, <code>--quiet</code>: <code>--loglevel warn</code></li> -<li><code>-d</code>: <code>--loglevel info</code></li> -<li><code>-dd</code>, <code>--verbose</code>: <code>--loglevel verbose</code></li> -<li><code>-ddd</code>: <code>--loglevel silly</code></li> +<li><code>-a</code>: <code>--all</code></li> +<li><code>--enjoy-by</code>: <code>--before</code></li> +<li><code>-c</code>: <code>--call</code></li> +<li><code>--desc</code>: <code>--description</code></li> +<li><code>-f</code>: <code>--force</code></li> <li><code>-g</code>: <code>--global</code></li> -<li><code>-C</code>: <code>--prefix</code></li> +<li><code>-d</code>: <code>--loglevel info</code></li> +<li><code>-s</code>: <code>--loglevel silent</code></li> +<li><code>--silent</code>: <code>--loglevel silent</code></li> +<li><code>--ddd</code>: <code>--loglevel silly</code></li> +<li><code>--dd</code>: <code>--loglevel verbose</code></li> +<li><code>--verbose</code>: <code>--loglevel verbose</code></li> +<li><code>-q</code>: <code>--loglevel warn</code></li> +<li><code>--quiet</code>: <code>--loglevel warn</code></li> <li><code>-l</code>: <code>--long</code></li> <li><code>-m</code>: <code>--message</code></li> -<li><code>-p</code>, <code>--porcelain</code>: <code>--parseable</code></li> -<li><code>-reg</code>: <code>--registry</code></li> -<li><code>-f</code>: <code>--force</code></li> -<li><code>-desc</code>: <code>--description</code></li> +<li><code>--local</code>: <code>--no-global</code></li> +<li><code>-n</code>: <code>--no-yes</code></li> +<li><code>--no</code>: <code>--no-yes</code></li> +<li><code>-p</code>: <code>--parseable</code></li> +<li><code>--porcelain</code>: <code>--parseable</code></li> +<li><code>-C</code>: <code>--prefix</code></li> +<li><code>--readonly</code>: <code>--read-only</code></li> +<li><code>--reg</code>: <code>--registry</code></li> <li><code>-S</code>: <code>--save</code></li> -<li><code>-P</code>: <code>--save-prod</code></li> -<li><code>-D</code>: <code>--save-dev</code></li> -<li><code>-O</code>: <code>--save-optional</code></li> <li><code>-B</code>: <code>--save-bundle</code></li> +<li><code>-D</code>: <code>--save-dev</code></li> <li><code>-E</code>: <code>--save-exact</code></li> +<li><code>-O</code>: <code>--save-optional</code></li> +<li><code>-P</code>: <code>--save-prod</code></li> +<li><code>-?</code>: <code>--usage</code></li> +<li><code>-h</code>: <code>--usage</code></li> +<li><code>-H</code>: <code>--usage</code></li> +<li><code>--help</code>: <code>--usage</code></li> +<li><code>-v</code>: <code>--version</code></li> +<li><code>-w</code>: <code>--workspace</code></li> +<li><code>--ws</code>: <code>--workspaces</code></li> <li><code>-y</code>: <code>--yes</code></li> -<li><code>-n</code>: <code>--yes false</code></li> -<li><code>ll</code> and <code>la</code> commands: <code>ls --long</code></li> </ul> +<!-- raw HTML omitted --> <p>If the specified configuration param resolves unambiguously to a known configuration parameter, then it is expanded to that configuration parameter. For example:</p> @@ -227,162 +244,128 @@ example:</p> npm ls --global --parseable --long --loglevel info </code></pre> <h3 id="config-settings">Config Settings</h3> -<h4 id="access">access</h4> +<!-- raw HTML omitted --> +<!-- raw HTML omitted --> +<h4 id="auth"><code>_auth</code></h4> <ul> -<li>Default: <code>restricted</code></li> -<li>Type: Access</li> +<li>Default: null</li> +<li>Type: null or String</li> </ul> -<p>When publishing scoped packages, the access level defaults to <code>restricted</code>. If -you want your scoped package to be publicly viewable (and installable) set -<code>--access=public</code>. The only valid values for <code>access</code> are <code>public</code> and +<p>A basic-auth string to use when authenticating against the npm registry.</p> +<p>Warning: This should generally not be set via a command-line option. It is +safer to use a registry-provided authentication bearer token stored in the +~/.npmrc file by running <code>npm login</code>.</p> +<h4 id="access"><code>access</code></h4> +<ul> +<li>Default: ‘restricted’ for scoped packages, ‘public’ for unscoped packages</li> +<li>Type: null, “restricted”, or “public”</li> +</ul> +<p>When publishing scoped packages, the access level defaults to <code>restricted</code>. +If you want your scoped package to be publicly viewable (and installable) +set <code>--access=public</code>. The only valid values for <code>access</code> are <code>public</code> and <code>restricted</code>. Unscoped packages <em>always</em> have an access level of <code>public</code>.</p> -<h4 id="all">all</h4> +<h4 id="all"><code>all</code></h4> <ul> -<li>Default: <code>false</code></li> +<li>Default: false</li> <li>Type: Boolean</li> </ul> <p>When running <code>npm outdated</code> and <code>npm ls</code>, setting <code>--all</code> will show all outdated or installed packages, rather than only those directly depended upon by the current project.</p> -<h4 id="allow-same-version">allow-same-version</h4> +<h4 id="allow-same-version"><code>allow-same-version</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> </ul> <p>Prevents throwing an error when <code>npm version</code> is used to set the new version to the same value as the current version.</p> -<h4 id="always-auth">always-auth</h4> +<h4 id="always-auth"><code>always-auth</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> </ul> -<p>Force npm to always require authentication when accessing the registry, -even for <code>GET</code> requests.</p> -<h4 id="also">also</h4> -<ul> -<li>Default: null</li> -<li>Type: String</li> -</ul> -<p>When “dev” or “development” and running local <code>npm shrinkwrap</code>, -<code>npm outdated</code>, or <code>npm update</code>, is an alias for <code>--dev</code>.</p> -<h4 id="audit">audit</h4> +<p>Force npm to always require authentication when accessing the registry, even +for <code>GET</code> requests.</p> +<h4 id="audit"><code>audit</code></h4> <ul> <li>Default: true</li> <li>Type: Boolean</li> </ul> <p>When “true” submit audit reports alongside <code>npm install</code> runs to the default -registry and all registries configured for scopes. See the documentation -for <a href="../commands/npm-audit.html"><code>npm audit</code></a> for details on what is submitted.</p> -<h4 id="audit-level">audit-level</h4> -<ul> -<li>Default: <code>"low"</code></li> -<li>Type: <code>'low'</code>, <code>'moderate'</code>, <code>'high'</code>, <code>'critical'</code></li> -</ul> -<p>The minimum level of vulnerability for <code>npm audit</code> to exit with -a non-zero exit code.</p> -<h4 id="auth-type">auth-type</h4> +registry and all registries configured for scopes. See the documentation for +<a href="../commands/npm-audit.html"><code>npm audit</code></a> for details on what is submitted.</p> +<h4 id="audit-level"><code>audit-level</code></h4> <ul> -<li>Default: <code>'legacy'</code></li> -<li>Type: <code>'legacy'</code>, <code>'sso'</code>, <code>'saml'</code>, <code>'oauth'</code></li> +<li>Default: null</li> +<li>Type: “low”, “moderate”, “high”, “critical”, “none”, or null</li> </ul> -<p>What authentication strategy to use with <code>adduser</code>/<code>login</code>.</p> -<h4 id="before">before</h4> +<p>The minimum level of vulnerability for <code>npm audit</code> to exit with a non-zero +exit code.</p> +<h4 id="before"><code>before</code></h4> <ul> -<li>Alias: enjoy-by</li> <li>Default: null</li> -<li>Type: Date</li> +<li>Type: null or Date</li> </ul> -<p>If passed to <code>npm install</code>, will rebuild the npm tree such that only versions -that were available <strong>on or before</strong> the <code>--before</code> time get installed. -If there’s no versions available for the current set of direct dependencies, the -command will error.</p> +<p>If passed to <code>npm install</code>, will rebuild the npm tree such that only +versions that were available <strong>on or before</strong> the <code>--before</code> time get +installed. If there’s no versions available for the current set of direct +dependencies, the command will error.</p> <p>If the requested version is a <code>dist-tag</code> and the given tag does not pass the -<code>--before</code> filter, the most recent version less than or equal to that tag will -be used. For example, <code>foo@latest</code> might install <code>foo@1.2</code> even though <code>latest</code> -is <code>2.0</code>.</p> -<h4 id="bin-links">bin-links</h4> +<code>--before</code> filter, the most recent version less than or equal to that tag +will be used. For example, <code>foo@latest</code> might install <code>foo@1.2</code> even though +<code>latest</code> is <code>2.0</code>.</p> +<h4 id="bin-links"><code>bin-links</code></h4> <ul> -<li>Default: <code>true</code></li> +<li>Default: true</li> <li>Type: Boolean</li> </ul> <p>Tells npm to create symlinks (or <code>.cmd</code> shims on Windows) for package executables.</p> -<p>Set to false to have it not do this. This can be used to work around -the fact that some file systems don’t support symlinks, even on -ostensibly Unix systems.</p> -<h4 id="browser">browser</h4> +<p>Set to false to have it not do this. This can be used to work around the +fact that some file systems don’t support symlinks, even on ostensibly Unix +systems.</p> +<h4 id="browser"><code>browser</code></h4> <ul> <li>Default: OS X: <code>"open"</code>, Windows: <code>"start"</code>, Others: <code>"xdg-open"</code></li> -<li>Type: String or Boolean</li> +<li>Type: null, Boolean, or String</li> </ul> <p>The browser that is called by npm commands to open websites.</p> <p>Set to <code>false</code> to suppress browser behavior and instead print urls to terminal.</p> <p>Set to <code>true</code> to use default system URL opener.</p> -<h4 id="ca">ca</h4> +<h4 id="ca"><code>ca</code></h4> <ul> -<li>Default: The npm CA certificate</li> -<li>Type: String, Array or null</li> +<li>Default: null</li> +<li>Type: null or String (can be set multiple times)</li> </ul> <p>The Certificate Authority signing certificate that is trusted for SSL -connections to the registry. Values should be in PEM format (Windows calls it “Base-64 encoded X.509 (.CER)”) with newlines -replaced by the string “\n”. For example:</p> -<pre lang="bash"><code>ca="-----BEGIN CERTIFICATE-----\nXXXX\nXXXX\n-----END CERTIFICATE-----" +connections to the registry. Values should be in PEM format (Windows calls +it “Base-64 encoded X.509 (.CER)”) with newlines replaced by the string +“\n”. For example:</p> +<pre lang="ini"><code>ca="-----BEGIN CERTIFICATE-----\nXXXX\nXXXX\n-----END CERTIFICATE-----" </code></pre> -<p>Set to <code>null</code> to only allow “known” registrars, or to a specific CA cert -to trust only that specific signing authority.</p> +<p>Set to <code>null</code> to only allow “known” registrars, or to a specific CA cert to +trust only that specific signing authority.</p> <p>Multiple CAs can be trusted by specifying an array of certificates:</p> -<pre lang="bash"><code>ca[]="..." +<pre lang="ini"><code>ca[]="..." ca[]="..." </code></pre> <p>See also the <code>strict-ssl</code> config.</p> -<h4 id="cafile">cafile</h4> +<h4 id="cache"><code>cache</code></h4> <ul> -<li>Default: <code>null</code></li> -<li>Type: path</li> +<li>Default: Windows: <code>%LocalAppData%\npm-cache</code>, Posix: <code>~/.npm</code></li> +<li>Type: Path</li> +</ul> +<p>The location of npm’s cache directory. See <a href="../commands/npm-cache.html"><code>npm cache</code></a></p> +<h4 id="cafile"><code>cafile</code></h4> +<ul> +<li>Default: null</li> +<li>Type: Path</li> </ul> <p>A path to a file containing one or multiple Certificate Authority signing certificates. Similar to the <code>ca</code> setting, but allows for multiple CA’s, as well as for the CA information to be stored in a file on disk.</p> -<h4 id="cache">cache</h4> -<ul> -<li>Default: Windows: <code>%AppData%\npm-cache</code>, Posix: <code>~/.npm</code></li> -<li>Type: path</li> -</ul> -<p>The location of npm’s cache directory. See <a href="../commands/npm-cache.html"><code>npm cache</code></a></p> -<h4 id="cache-lock-stale">cache-lock-stale</h4> -<ul> -<li>Default: 60000 (1 minute)</li> -<li>Type: Number</li> -</ul> -<p>The number of ms before cache folder lockfiles are considered stale.</p> -<h4 id="cache-lock-retries">cache-lock-retries</h4> -<ul> -<li>Default: 10</li> -<li>Type: Number</li> -</ul> -<p>Number of times to retry to acquire a lock on cache folder lockfiles.</p> -<h4 id="cache-lock-wait">cache-lock-wait</h4> -<ul> -<li>Default: 10000 (10 seconds)</li> -<li>Type: Number</li> -</ul> -<p>Number of ms to wait for cache lock files to expire.</p> -<h4 id="cache-max">cache-max</h4> -<ul> -<li>Default: Infinity</li> -<li>Type: Number</li> -</ul> -<p><strong>DEPRECATED</strong>: This option has been deprecated in favor of <code>--prefer-online</code>.</p> -<p><code>--cache-max=0</code> is an alias for <code>--prefer-online</code>.</p> -<h4 id="cache-min">cache-min</h4> -<ul> -<li>Default: 10</li> -<li>Type: Number</li> -</ul> -<p><strong>DEPRECATED</strong>: This option has been deprecated in favor of <code>--prefer-offline</code>.</p> -<p><code>--cache-min=9999 (or bigger)</code> is an alias for <code>--prefer-offline</code>.</p> -<h4 id="call">call</h4> +<h4 id="call"><code>call</code></h4> <ul> <li>Default: “”</li> <li>Type: String</li> @@ -391,131 +374,174 @@ well as for the CA information to be stored in a file on disk.</p> custom command to be run along with the installed packages.</p> <pre lang="bash"><code>npm exec --package yo --package generator-node --call "yo node" </code></pre> -<h4 id="cert">cert</h4> +<h4 id="cert"><code>cert</code></h4> <ul> -<li>Default: <code>null</code></li> -<li>Type: String</li> +<li>Default: null</li> +<li>Type: null or String</li> </ul> -<p>A client certificate to pass when accessing the registry. Values should be in -PEM format (Windows calls it “Base-64 encoded X.509 (.CER)”) with newlines replaced by the string “\n”. For example:</p> -<pre lang="bash"><code>cert="-----BEGIN CERTIFICATE-----\nXXXX\nXXXX\n-----END CERTIFICATE-----" +<p>A client certificate to pass when accessing the registry. Values should be +in PEM format (Windows calls it “Base-64 encoded X.509 (.CER)”) with +newlines replaced by the string “\n”. For example:</p> +<pre lang="ini"><code>cert="-----BEGIN CERTIFICATE-----\nXXXX\nXXXX\n-----END CERTIFICATE-----" </code></pre> -<p>It is <em>not</em> the path to a certificate file (and there is no “certfile” option).</p> -<h4 id="cidr">cidr</h4> +<p>It is <em>not</em> the path to a certificate file (and there is no “certfile” +option).</p> +<h4 id="ci-name"><code>ci-name</code></h4> <ul> -<li>Default: <code>null</code></li> -<li>Type: String, Array, null</li> +<li>Default: The name of the current CI system, or <code>null</code> when not on a known CI +platform.</li> +<li>Type: null or String</li> </ul> -<p>This is a list of CIDR address to be used when configuring limited access tokens with the <code>npm token create</code> command.</p> -<h4 id="commit-hooks">commit-hooks</h4> +<p>The name of a continuous integration system. If not set explicitly, npm will +detect the current CI environment using the +<a href="http://npm.im/@npmcli/ci-detect"><code>@npmcli/ci-detect</code></a> module.</p> +<h4 id="cidr"><code>cidr</code></h4> <ul> -<li>Default: <code>true</code></li> -<li>Type: Boolean</li> +<li>Default: null</li> +<li>Type: null or String (can be set multiple times)</li> </ul> -<p>Run git commit hooks when using the <code>npm version</code> command.</p> -<h4 id="color">color</h4> +<p>This is a list of CIDR address to be used when configuring limited access +tokens with the <code>npm token create</code> command.</p> +<h4 id="color"><code>color</code></h4> +<ul> +<li>Default: true unless the NO_COLOR environ is set to something other than ‘0’</li> +<li>Type: “always” or Boolean</li> +</ul> +<p>If false, never shows colors. If <code>"always"</code> then always shows colors. If +true, then only prints color codes for tty file descriptors.</p> +<h4 id="commit-hooks"><code>commit-hooks</code></h4> <ul> <li>Default: true</li> -<li>Type: Boolean or <code>"always"</code></li> +<li>Type: Boolean</li> </ul> -<p>If false, never shows colors. If <code>"always"</code> then always shows colors. -If true, then only prints color codes for tty file descriptors.</p> -<p>This option can also be changed using the environment: colors are -disabled when the environment variable <code>NO_COLOR</code> is set to any value.</p> -<h4 id="depth">depth</h4> +<p>Run git commit hooks when using the <code>npm version</code> command.</p> +<h4 id="depth"><code>depth</code></h4> <ul> -<li>Default: null</li> +<li>Default: <code>Infinity</code> if <code>--all</code> is set, otherwise <code>1</code></li> <li>Type: null or Number</li> </ul> <p>The depth to go when recursing packages for <code>npm ls</code>.</p> -<p>To make this default to <code>Infinity</code> instead of <code>null</code>, set <code>--all</code>.</p> -<h4 id="description2">description</h4> +<p>If not set, <code>npm ls</code> will show only the immediate dependencies of the root +project. If <code>--all</code> is set, then npm will show all dependencies by default.</p> +<h4 id="description2"><code>description</code></h4> <ul> <li>Default: true</li> <li>Type: Boolean</li> </ul> <p>Show the description in <code>npm search</code></p> -<h4 id="dev">dev</h4> +<h4 id="diff"><code>diff</code></h4> +<ul> +<li>Default:</li> +<li>Type: String (can be set multiple times)</li> +</ul> +<p>Define arguments to compare in <code>npm diff</code>.</p> +<h4 id="diff-dst-prefix"><code>diff-dst-prefix</code></h4> +<ul> +<li>Default: “b/”</li> +<li>Type: String</li> +</ul> +<p>Destination prefix to be used in <code>npm diff</code> output.</p> +<h4 id="diff-ignore-all-space"><code>diff-ignore-all-space</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> </ul> -<p>[Deprecated] Install <code>dev-dependencies</code> along with packages.</p> -<h4 id="dry-run">dry-run</h4> +<p>Ignore whitespace when comparing lines in <code>npm diff</code>.</p> +<h4 id="diff-name-only"><code>diff-name-only</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> </ul> -<p>Indicates that you don’t want npm to make any changes and that it should -only report what it would have done. This can be passed into any of the -commands that modify your local installation, eg, <code>install</code>, <code>update</code>, -<code>dedupe</code>, <code>uninstall</code>. This is NOT currently honored by some network related -commands, eg <code>dist-tags</code>, <code>owner</code>, etc.</p> -<h4 id="diff">diff</h4> +<p>Prints only filenames when using <code>npm diff</code>.</p> +<h4 id="diff-no-prefix"><code>diff-no-prefix</code></h4> <ul> -<li>Default: null</li> -<li>Type: String, Array, null</li> +<li>Default: false</li> +<li>Type: Boolean</li> </ul> -<p>Define arguments to compare in <code>npm diff</code>.</p> -<h4 id="diff-name-only">diff-name-only</h4> +<p>Do not show any source or destination prefix in <code>npm diff</code> output.</p> +<p>Note: this causes <code>npm diff</code> to ignore the <code>--diff-src-prefix</code> and +<code>--diff-dst-prefix</code> configs.</p> +<h4 id="diff-src-prefix"><code>diff-src-prefix</code></h4> +<ul> +<li>Default: “a/”</li> +<li>Type: String</li> +</ul> +<p>Source prefix to be used in <code>npm diff</code> output.</p> +<h4 id="diff-text"><code>diff-text</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> </ul> -<p>Prints only filenames when using <code>npm diff</code>.</p> -<h4 id="diff-unified">diff-unified</h4> +<p>Treat all files as text in <code>npm diff</code>.</p> +<h4 id="diff-unified"><code>diff-unified</code></h4> <ul> -<li>Type: number</li> -<li>Default: <code>3</code></li> +<li>Default: 3</li> +<li>Type: Number</li> </ul> <p>The number of lines of context to print in <code>npm diff</code>.</p> -<h4 id="diff-ignore-all-space">diff-ignore-all-space</h4> +<h4 id="dry-run"><code>dry-run</code></h4> <ul> -<li>Type: Boolean</li> <li>Default: false</li> +<li>Type: Boolean</li> </ul> -<p>Ignore whitespace when comparing lines in `npm diff.</p> -<h4 id="diff-no-prefix">diff-no-prefix</h4> +<p>Indicates that you don’t want npm to make any changes and that it should +only report what it would have done. This can be passed into any of the +commands that modify your local installation, eg, <code>install</code>, <code>update</code>, +<code>dedupe</code>, <code>uninstall</code>, as well as <code>pack</code> and <code>publish</code>.</p> +<p>Note: This is NOT honored by other network related commands, eg <code>dist-tags</code>, +<code>owner</code>, etc.</p> +<h4 id="editor"><code>editor</code></h4> +<ul> +<li>Default: The EDITOR or VISUAL environment variables, or ‘notepad.exe’ on +Windows, or ‘vim’ on Unix systems</li> +<li>Type: String</li> +</ul> +<p>The command to run for <code>npm edit</code> and <code>npm config edit</code>.</p> +<h4 id="engine-strict"><code>engine-strict</code></h4> <ul> -<li>Type: Boolean</li> <li>Default: false</li> +<li>Type: Boolean</li> </ul> -<p>Do not show any source or destination prefix in <code>npm diff</code> output.</p> -<h4 id="diff-src-prefix">diff-src-prefix</h4> +<p>If set to true, then npm will stubbornly refuse to install (or even consider +installing) any package that claims to not be compatible with the current +Node.js version.</p> +<p>This can be overridden by setting the <code>--force</code> flag.</p> +<h4 id="fetch-retries"><code>fetch-retries</code></h4> <ul> -<li>Type: String</li> -<li>Default: <code>"a/"</code></li> +<li>Default: 2</li> +<li>Type: Number</li> </ul> -<p>Source prefix to be used in <code>npm diff</code> output.</p> -<h4 id="diff-dst-prefix">diff-dst-prefix</h4> +<p>The “retries” config for the <code>retry</code> module to use when fetching packages +from the registry.</p> +<p>npm will retry idempotent read requests to the registry in the case of +network failures or 5xx HTTP errors.</p> +<h4 id="fetch-retry-factor"><code>fetch-retry-factor</code></h4> <ul> -<li>Type: String</li> -<li>Default: <code>"b/"</code></li> +<li>Default: 10</li> +<li>Type: Number</li> </ul> -<p>Destination prefix to be used in <code>npm diff</code> output.</p> -<h4 id="diff-text">diff-text</h4> +<p>The “factor” config for the <code>retry</code> module to use when fetching packages.</p> +<h4 id="fetch-retry-maxtimeout"><code>fetch-retry-maxtimeout</code></h4> <ul> -<li>Alias: <code>-a</code></li> -<li>Type: Boolean</li> -<li>Default: false</li> +<li>Default: 60000 (1 minute)</li> +<li>Type: Number</li> </ul> -<p>Treat all files as text in <code>npm diff</code>.</p> -<h4 id="editor">editor</h4> +<p>The “maxTimeout” config for the <code>retry</code> module to use when fetching +packages.</p> +<h4 id="fetch-retry-mintimeout"><code>fetch-retry-mintimeout</code></h4> <ul> -<li>Default: <code>EDITOR</code> environment variable if set, or <code>"vi"</code> on Posix, -or <code>"notepad"</code> on Windows.</li> -<li>Type: path</li> +<li>Default: 10000 (10 seconds)</li> +<li>Type: Number</li> </ul> -<p>The command to run for <code>npm edit</code> or <code>npm config edit</code>.</p> -<h4 id="engine-strict">engine-strict</h4> +<p>The “minTimeout” config for the <code>retry</code> module to use when fetching +packages.</p> +<h4 id="fetch-timeout"><code>fetch-timeout</code></h4> <ul> -<li>Default: false</li> -<li>Type: Boolean</li> +<li>Default: 300000 (5 minutes)</li> +<li>Type: Number</li> </ul> -<p>If set to true, then npm will stubbornly refuse to install (or even -consider installing) any package that claims to not be compatible with -the current Node.js version.</p> -<h4 id="force">force</h4> +<p>The maximum amount of time to wait for HTTP requests to complete.</p> +<h4 id="force"><code>force</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> @@ -529,16 +555,15 @@ mistakes, unnecessary performance degradation, and malicious input.</p> <li>Allow installing packages that have an <code>engines</code> declaration requiring a different version of npm.</li> <li>Allow installing packages that have an <code>engines</code> declaration requiring a -different version of <code>node</code>, even if <code>--engines-strict</code> is enabled.</li> +different version of <code>node</code>, even if <code>--engine-strict</code> is enabled.</li> <li>Allow <code>npm audit fix</code> to install modules outside your stated dependency range (including SemVer-major changes).</li> -<li>Allow a module to be installed as a direct dependency of itself.</li> <li>Allow unpublishing all versions of a published package.</li> <li>Allow conflicting peerDependencies to be installed in the root project.</li> </ul> <p>If you don’t have a clear idea of what you want to do, it is strongly recommended that you do not use this option!</p> -<h4 id="foreground-scripts">foreground-scripts</h4> +<h4 id="foreground-scripts"><code>foreground-scripts</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> @@ -546,347 +571,322 @@ recommended that you do not use this option!</p> <p>Run all build scripts (ie, <code>preinstall</code>, <code>install</code>, and <code>postinstall</code>) scripts for installed packages in the foreground process, sharing standard input, output, and error with the main npm process.</p> -<p>Note that this will generally make installs run slower, and be much -noisier, but can be useful for debugging.</p> -<h4 id="format-package-lock">format-package-lock</h4> +<p>Note that this will generally make installs run slower, and be much noisier, +but can be useful for debugging.</p> +<h4 id="format-package-lock"><code>format-package-lock</code></h4> <ul> <li>Default: true</li> <li>Type: Boolean</li> </ul> -<p>Format <code>package-lock.json</code> or <code>npm-shrinkwrap.json</code> as a human readable file.</p> -<h4 id="fund">fund</h4> +<p>Format <code>package-lock.json</code> or <code>npm-shrinkwrap.json</code> as a human readable +file.</p> +<h4 id="fund"><code>fund</code></h4> <ul> <li>Default: true</li> <li>Type: Boolean</li> </ul> <p>When “true” displays the message at the end of each <code>npm install</code> -acknowledging the number of dependencies looking for funding. -See <a href="../commands/npm-fund.html"><code>npm fund</code></a> for details.</p> -<h4 id="fetch-retries">fetch-retries</h4> -<ul> -<li>Default: 2</li> -<li>Type: Number</li> -</ul> -<p>The “retries” config for the <code>retry</code> module to use when fetching -packages from the registry.</p> -<h4 id="fetch-retry-factor">fetch-retry-factor</h4> -<ul> -<li>Default: 10</li> -<li>Type: Number</li> -</ul> -<p>The “factor” config for the <code>retry</code> module to use when fetching -packages.</p> -<h4 id="fetch-retry-mintimeout">fetch-retry-mintimeout</h4> -<ul> -<li>Default: 10000 (10 seconds)</li> -<li>Type: Number</li> -</ul> -<p>The “minTimeout” config for the <code>retry</code> module to use when fetching -packages.</p> -<h4 id="fetch-retry-maxtimeout">fetch-retry-maxtimeout</h4> -<ul> -<li>Default: 60000 (1 minute)</li> -<li>Type: Number</li> -</ul> -<p>The “maxTimeout” config for the <code>retry</code> module to use when fetching -packages.</p> -<h4 id="fetch-timeout">fetch-timeout</h4> +acknowledging the number of dependencies looking for funding. See <a href="../commands/npm-fund.html"><code>npm fund</code></a> for details.</p> +<h4 id="git"><code>git</code></h4> <ul> -<li>Default: 300000 (5 minutes)</li> -<li>Type: Number</li> -</ul> -<p>The maximum amount of time to wait for HTTP requests to complete.</p> -<h4 id="git">git</h4> -<ul> -<li>Default: <code>"git"</code></li> +<li>Default: “git”</li> <li>Type: String</li> </ul> -<p>The command to use for git commands. If git is installed on the -computer, but is not in the <code>PATH</code>, then set this to the full path to -the git binary.</p> -<h4 id="git-tag-version">git-tag-version</h4> +<p>The command to use for git commands. If git is installed on the computer, +but is not in the <code>PATH</code>, then set this to the full path to the git binary.</p> +<h4 id="git-tag-version"><code>git-tag-version</code></h4> <ul> -<li>Default: <code>true</code></li> +<li>Default: true</li> <li>Type: Boolean</li> </ul> <p>Tag the commit when using the <code>npm version</code> command.</p> -<h4 id="global">global</h4> +<h4 id="global"><code>global</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> </ul> -<p>Operates in “global” mode, so that packages are installed into the -<code>prefix</code> folder instead of the current working directory. See +<p>Operates in “global” mode, so that packages are installed into the <code>prefix</code> +folder instead of the current working directory. See <a href="../configuring-npm/folders.html">folders</a> for more on the differences in behavior.</p> <ul> -<li>packages are installed into the <code>{prefix}/lib/node_modules</code> folder, instead of the -current working directory.</li> +<li>packages are installed into the <code>{prefix}/lib/node_modules</code> folder, instead +of the current working directory.</li> <li>bin files are linked to <code>{prefix}/bin</code></li> <li>man pages are linked to <code>{prefix}/share/man</code></li> </ul> -<h4 id="globalconfig">globalconfig</h4> -<ul> -<li>Default: {prefix}/etc/npmrc</li> -<li>Type: path</li> -</ul> -<p>The config file to read for global config options.</p> -<h4 id="global-style">global-style</h4> +<h4 id="global-style"><code>global-style</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> </ul> <p>Causes npm to install the package into your local <code>node_modules</code> folder with -the same layout it uses with the global <code>node_modules</code> folder. Only your +the same layout it uses with the global <code>node_modules</code> folder. Only your direct dependencies will show in <code>node_modules</code> and everything they depend -on will be flattened in their <code>node_modules</code> folders. This obviously will -eliminate some deduping. If used with <code>legacy-bundling</code>, <code>legacy-bundling</code> will be -preferred.</p> -<h4 id="heading">heading</h4> +on will be flattened in their <code>node_modules</code> folders. This obviously will +eliminate some deduping. If used with <code>legacy-bundling</code>, <code>legacy-bundling</code> +will be preferred.</p> +<h4 id="globalconfig"><code>globalconfig</code></h4> <ul> -<li>Default: <code>"npm"</code></li> +<li>Default: The global –prefix setting plus ‘etc/npmrc’. For example, +‘/usr/local/etc/npmrc’</li> +<li>Type: Path</li> +</ul> +<p>The config file to read for global config options.</p> +<h4 id="heading"><code>heading</code></h4> +<ul> +<li>Default: “npm”</li> <li>Type: String</li> </ul> <p>The string that starts all the debugging log output.</p> -<h4 id="https-proxy">https-proxy</h4> +<h4 id="https-proxy"><code>https-proxy</code></h4> <ul> <li>Default: null</li> -<li>Type: url</li> +<li>Type: null or URL</li> </ul> <p>A proxy to use for outgoing https requests. If the <code>HTTPS_PROXY</code> or <code>https_proxy</code> or <code>HTTP_PROXY</code> or <code>http_proxy</code> environment variables are set, -proxy settings will be honored by the underlying <code>request</code> library.</p> -<h4 id="if-present">if-present</h4> -<ul> -<li>Default: false</li> -<li>Type: Boolean</li> -</ul> -<p>If true, npm will not exit with an error code when <code>run-script</code> is invoked for -a script that isn’t defined in the <code>scripts</code> section of <code>package.json</code>. This -option can be used when it’s desirable to optionally run a script when it’s -present and fail if the script fails. This is useful, for example, when running -scripts that may only apply for some builds in an otherwise generic CI setup.</p> -<h4 id="ignore-prepublish">ignore-prepublish</h4> +proxy settings will be honored by the underlying <code>make-fetch-happen</code> +library.</p> +<h4 id="if-present"><code>if-present</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> </ul> -<p>If true, npm will not run <code>prepublish</code> scripts.</p> -<h4 id="ignore-scripts">ignore-scripts</h4> +<p>If true, npm will not exit with an error code when <code>run-script</code> is invoked +for a script that isn’t defined in the <code>scripts</code> section of <code>package.json</code>. +This option can be used when it’s desirable to optionally run a script when +it’s present and fail if the script fails. This is useful, for example, when +running scripts that may only apply for some builds in an otherwise generic +CI setup.</p> +<h4 id="ignore-scripts"><code>ignore-scripts</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> </ul> <p>If true, npm does not run scripts specified in package.json files.</p> -<h4 id="include">include</h4> +<h4 id="include"><code>include</code></h4> <ul> -<li>Default: <code>[prod|dev|optional|peer]</code></li> -<li>Type: Array</li> +<li>Default:</li> +<li>Type: “prod”, “dev”, “optional”, or “peer” (can be set multiple times)</li> </ul> <p>Option that allows for defining which types of dependencies to install.</p> -<h4 id="init-module">init-module</h4> +<p>This is the inverse of <code>--omit=<type></code>.</p> +<p>Dependency types specified in <code>--include</code> will not be omitted, regardless of +the order in which omit/include are specified on the command-line.</p> +<h4 id="include-staged"><code>include-staged</code></h4> <ul> -<li>Alias: <code>init.module</code></li> -<li>Default: ~/.npm-init.js</li> -<li>Type: path</li> +<li>Default: false</li> +<li>Type: Boolean</li> </ul> -<p>A module that will be loaded by the <code>npm init</code> command. See the -documentation for the -<a href="https://github.com/npm/init-package-json">init-package-json</a> module -for more information, or <a href="../commands/npm-init.html">npm init</a>.</p> -<h4 id="init-author-name">init-author-name</h4> +<p>Allow installing “staged” published packages, as defined by <a href="https://github.com/npm/rfcs/pull/92">npm RFC PR +#92</a>.</p> +<p>This is experimental, and not implemented by the npm public registry.</p> +<h4 id="init-author-email"><code>init-author-email</code></h4> <ul> -<li>Alias: <code>init.author.name</code></li> <li>Default: “”</li> <li>Type: String</li> </ul> -<p>The value <code>npm init</code> should use by default for the package author’s name.</p> -<h4 id="init-author-email">init-author-email</h4> +<p>The value <code>npm init</code> should use by default for the package author’s email.</p> +<h4 id="init-author-name"><code>init-author-name</code></h4> <ul> -<li>Alias: <code>init.author.email</code></li> <li>Default: “”</li> <li>Type: String</li> </ul> -<p>The value <code>npm init</code> should use by default for the package author’s email.</p> -<h4 id="init-author-url">init-author-url</h4> +<p>The value <code>npm init</code> should use by default for the package author’s name.</p> +<h4 id="init-author-url"><code>init-author-url</code></h4> <ul> -<li>Alias: <code>init.author.url</code></li> <li>Default: “”</li> -<li>Type: String</li> +<li>Type: “” or URL</li> </ul> -<p>The value <code>npm init</code> should use by default for the package author’s homepage.</p> -<h4 id="init-license">init-license</h4> +<p>The value <code>npm init</code> should use by default for the package author’s +homepage.</p> +<h4 id="init-license"><code>init-license</code></h4> <ul> -<li>Alias: <code>init.license</code></li> <li>Default: “ISC”</li> <li>Type: String</li> </ul> <p>The value <code>npm init</code> should use by default for the package license.</p> -<h4 id="init-version">init-version</h4> +<h4 id="init-module"><code>init-module</code></h4> +<ul> +<li>Default: “~/.npm-init.js”</li> +<li>Type: Path</li> +</ul> +<p>A module that will be loaded by the <code>npm init</code> command. See the +documentation for the +<a href="https://github.com/npm/init-package-json">init-package-json</a> module for +more information, or <a href="../commands/npm-init.html">npm init</a>.</p> +<h4 id="init-version"><code>init-version</code></h4> <ul> -<li>Alias: <code>init.version</code></li> <li>Default: “1.0.0”</li> -<li>Type: semver</li> +<li>Type: SemVer string</li> </ul> -<p>The value that <code>npm init</code> should use by default for the package -version number, if not already set in package.json.</p> -<h4 id="json">json</h4> +<p>The value that <code>npm init</code> should use by default for the package version +number, if not already set in package.json.</p> +<h4 id="json"><code>json</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> </ul> <p>Whether or not to output JSON data, rather than the normal output.</p> -<p>This feature is currently experimental, and the output data structures for many -commands is either not implemented in JSON yet, or subject to change. Only the -output from <code>npm ls --json</code> and <code>npm search --json</code> are currently valid.</p> -<h4 id="key">key</h4> +<p>This feature is currently experimental, and the output data structures for +many commands is either not implemented in JSON yet, or subject to change. +Only the output from <code>npm ls --json</code> and <code>npm search --json</code> are currently +valid.</p> +<h4 id="key"><code>key</code></h4> <ul> -<li>Default: <code>null</code></li> -<li>Type: String</li> +<li>Default: null</li> +<li>Type: null or String</li> </ul> -<p>A client key to pass when accessing the registry. Values should be in PEM +<p>A client key to pass when accessing the registry. Values should be in PEM format with newlines replaced by the string “\n”. For example:</p> -<pre lang="json"><code>key="-----BEGIN PRIVATE KEY-----\nXXXX\nXXXX\n-----END PRIVATE KEY-----" +<pre lang="ini"><code>key="-----BEGIN PRIVATE KEY-----\nXXXX\nXXXX\n-----END PRIVATE KEY-----" </code></pre> <p>It is <em>not</em> the path to a key file (and there is no “keyfile” option).</p> -<h4 id="legacy-bundling">legacy-bundling</h4> +<h4 id="legacy-bundling"><code>legacy-bundling</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> </ul> <p>Causes npm to install the package such that versions of npm prior to 1.4, -such as the one included with node 0.8, can install the package. This +such as the one included with node 0.8, can install the package. This eliminates all automatic deduping. If used with <code>global-style</code> this option will be preferred.</p> -<h4 id="legacy-peer-deps">legacy-peer-deps</h4> +<h4 id="legacy-peer-deps"><code>legacy-peer-deps</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> </ul> <p>Causes npm to completely ignore <code>peerDependencies</code> when building a package tree, as in npm versions 3 through 6.</p> -<p>If a package cannot be installed because of overly strict -<code>peerDependencies</code> that collide, it provides a way to move forward -resolving the situation.</p> +<p>If a package cannot be installed because of overly strict <code>peerDependencies</code> +that collide, it provides a way to move forward resolving the situation.</p> <p>This differs from <code>--omit=peer</code>, in that <code>--omit=peer</code> will avoid unpacking <code>peerDependencies</code> on disk, but will still design a tree such that <code>peerDependencies</code> <em>could</em> be unpacked in a correct place.</p> <p>Use of <code>legacy-peer-deps</code> is not recommended, as it will not enforce the <code>peerDependencies</code> contract that meta-dependencies may rely on.</p> -<h4 id="link">link</h4> +<h4 id="link"><code>link</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> </ul> <p>If true, then local installs will link if there is a suitable globally installed package.</p> -<p>Note that this means that local installs can cause things to be -installed into the global space at the same time. The link is only done -if one of the two conditions are met:</p> +<p>Note that this means that local installs can cause things to be installed +into the global space at the same time. The link is only done if one of the +two conditions are met:</p> <ul> <li>The package is not already installed globally, or</li> -<li>the globally installed version is identical to the version that is -being installed locally.</li> +<li>the globally installed version is identical to the version that is being +installed locally.</li> </ul> -<h4 id="local-address">local-address</h4> +<h4 id="local-address"><code>local-address</code></h4> <ul> -<li>Default: undefined</li> +<li>Default: null</li> <li>Type: IP Address</li> </ul> -<p>The IP address of the local interface to use when making connections -to the npm registry. Must be IPv4 in versions of Node prior to 0.12.</p> -<h4 id="loglevel">loglevel</h4> +<p>The IP address of the local interface to use when making connections to the +npm registry. Must be IPv4 in versions of Node prior to 0.12.</p> +<h4 id="loglevel"><code>loglevel</code></h4> <ul> <li>Default: “notice”</li> -<li>Type: String</li> -<li>Values: “silent”, “error”, “warn”, “notice”, “http”, “timing”, “info”, -“verbose”, “silly”</li> +<li>Type: “silent”, “error”, “warn”, “notice”, “http”, “timing”, “info”, +“verbose”, or “silly”</li> </ul> -<p>What level of logs to report. On failure, <em>all</em> logs are written to +<p>What level of logs to report. On failure, <em>all</em> logs are written to <code>npm-debug.log</code> in the current working directory.</p> -<p>Any logs of a higher level than the setting are shown. The default is “notice”.</p> -<h4 id="logs-max">logs-max</h4> +<p>Any logs of a higher level than the setting are shown. The default is +“notice”.</p> +<h4 id="logs-max"><code>logs-max</code></h4> <ul> <li>Default: 10</li> <li>Type: Number</li> </ul> <p>The maximum number of log files to store.</p> -<h4 id="long">long</h4> +<h4 id="long"><code>long</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> </ul> <p>Show extended information in <code>npm ls</code> and <code>npm search</code>.</p> -<h4 id="maxsockets">maxsockets</h4> +<h4 id="maxsockets"><code>maxsockets</code></h4> <ul> -<li>Default: 50</li> +<li>Default: Infinity</li> <li>Type: Number</li> </ul> <p>The maximum number of connections to use per origin (protocol/host/port -combination). Passed to the <code>http</code> <code>Agent</code> used to make the request.</p> -<h4 id="message">message</h4> +combination).</p> +<h4 id="message"><code>message</code></h4> <ul> <li>Default: “%s”</li> <li>Type: String</li> </ul> <p>Commit message which is used by <code>npm version</code> when creating version commit.</p> <p>Any “%s” in the message will be replaced with the version number.</p> -<h4 id="node-options">node-options</h4> +<h4 id="node-options"><code>node-options</code></h4> <ul> <li>Default: null</li> -<li>Type: String</li> +<li>Type: null or String</li> </ul> <p>Options to pass through to Node.js via the <code>NODE_OPTIONS</code> environment -variable. This does not impact how npm itself is executed but it does -impact how lifecycle scripts are called.</p> -<h4 id="node-version">node-version</h4> +variable. This does not impact how npm itself is executed but it does impact +how lifecycle scripts are called.</p> +<h4 id="node-version"><code>node-version</code></h4> <ul> -<li>Default: process.version</li> -<li>Type: semver or false</li> +<li>Default: Node.js <code>process.version</code> value</li> +<li>Type: SemVer string</li> </ul> -<p>The node version to use when checking a package’s <code>engines</code> map.</p> -<h4 id="noproxy">noproxy</h4> +<p>The node version to use when checking a package’s <code>engines</code> setting.</p> +<h4 id="noproxy"><code>noproxy</code></h4> <ul> -<li>Default: null</li> -<li>Type: String or Array</li> +<li>Default: The value of the NO_PROXY environment variable</li> +<li>Type: String (can be set multiple times)</li> </ul> -<p>A comma-separated string or an array of domain extensions that a proxy should not be used for.</p> -<h4 id="offline">offline</h4> +<p>Domain extensions that should bypass any proxies.</p> +<p>Also accepts a comma-delimited string.</p> +<h4 id="npm-version"><code>npm-version</code></h4> <ul> -<li>Default: false</li> -<li>Type: Boolean</li> +<li>Default: Output of <code>npm --version</code></li> +<li>Type: SemVer string</li> </ul> -<p>Force offline mode: no network requests will be done during install. To allow -the CLI to fill in missing cache data, see <code>--prefer-offline</code>.</p> -<h4 id="only">only</h4> +<p>The npm version to use when checking a package’s <code>engines</code> setting.</p> +<h4 id="offline"><code>offline</code></h4> <ul> -<li>Default: null</li> -<li>Type: String</li> +<li>Default: false</li> +<li>Type: Boolean</li> </ul> -<p>When “dev” or “development” and running local <code>npm install</code> without any -arguments, only devDependencies (and their dependencies) are installed.</p> -<p>When “dev” or “development” and running local <code>npm ls</code>, <code>npm outdated</code>, or -<code>npm update</code>, is an alias for <code>--dev</code>.</p> -<p>When “prod” or “production” and running local <code>npm install</code> without any -arguments, only non-devDependencies (and their dependencies) are -installed.</p> -<p>When “prod” or “production” and running local <code>npm ls</code>, <code>npm outdated</code>, or -<code>npm update</code>, is an alias for <code>--production</code>.</p> -<h4 id="optional">optional</h4> +<p>Force offline mode: no network requests will be done during install. To +allow the CLI to fill in missing cache data, see <code>--prefer-offline</code>.</p> +<h4 id="omit"><code>omit</code></h4> <ul> -<li>Default: true</li> -<li>Type: Boolean</li> +<li>Default: ‘dev’ if the NODE_ENV environment variable is set to ‘production’, +otherwise empty.</li> +<li>Type: “dev”, “optional”, or “peer” (can be set multiple times)</li> </ul> -<p>Attempt to install packages in the <code>optionalDependencies</code> object. Note -that if these packages fail to install, the overall installation -process is not aborted.</p> -<h4 id="otp">otp</h4> +<p>Dependency types to omit from the installation tree on disk.</p> +<p>Note that these dependencies <em>are</em> still resolved and added to the +<code>package-lock.json</code> or <code>npm-shrinkwrap.json</code> file. They are just not +physically installed on disk.</p> +<p>If a package type appears in both the <code>--include</code> and <code>--omit</code> lists, then +it will be included.</p> +<p>If the resulting omit list includes <code>'dev'</code>, then the <code>NODE_ENV</code> environment +variable will be set to <code>'production'</code> for all lifecycle scripts.</p> +<h4 id="otp"><code>otp</code></h4> <ul> <li>Default: null</li> -<li>Type: Number</li> +<li>Type: null or String</li> </ul> -<p>This is a one-time password from a two-factor authenticator. It’s needed +<p>This is a one-time password from a two-factor authenticator. It’s needed when publishing or changing package permissions with <code>npm access</code>.</p> -<h4 id="package-lock">package-lock</h4> +<p>If not set, and a registry response fails with a challenge for a one-time +password, npm will prompt on the command line for one.</p> +<h4 id="package"><code>package</code></h4> +<ul> +<li>Default:</li> +<li>Type: String (can be set multiple times)</li> +</ul> +<p>The package to install for <a href="../commands/npm-exec.html"><code>npm exec</code></a></p> +<h4 id="package-lock"><code>package-lock</code></h4> <ul> <li>Default: true</li> <li>Type: Boolean</li> @@ -894,113 +894,97 @@ when publishing or changing package permissions with <code>npm access</code>.</p <p>If set to false, then ignore <code>package-lock.json</code> files when installing. This will also prevent <em>writing</em> <code>package-lock.json</code> if <code>save</code> is true.</p> <p>When package package-locks are disabled, automatic pruning of extraneous -modules will also be disabled. To remove extraneous modules with +modules will also be disabled. To remove extraneous modules with package-locks disabled use <code>npm prune</code>.</p> -<p>This option is an alias for <code>--shrinkwrap</code>.</p> -<h4 id="package-lock-only">package-lock-only</h4> +<h4 id="package-lock-only"><code>package-lock-only</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> </ul> -<p>If set to true, it will update only the <code>package-lock.json</code>, -instead of checking <code>node_modules</code> and downloading dependencies.</p> -<h4 id="parseable">parseable</h4> +<p>If set to true, it will update only the <code>package-lock.json</code>, instead of +checking <code>node_modules</code> and downloading dependencies.</p> +<h4 id="parseable"><code>parseable</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> </ul> -<p>Output parseable results from commands that write to -standard output. For <code>npm search</code>, this will be tab-separated table format.</p> -<h4 id="prefer-offline">prefer-offline</h4> +<p>Output parseable results from commands that write to standard output. For +<code>npm search</code>, this will be tab-separated table format.</p> +<h4 id="prefer-offline"><code>prefer-offline</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> </ul> <p>If true, staleness checks for cached data will be bypassed, but missing data -will be requested from the server. To force full offline mode, use <code>--offline</code>.</p> -<p>This option is effectively equivalent to <code>--cache-min=9999999</code>.</p> -<h4 id="prefer-online">prefer-online</h4> +will be requested from the server. To force full offline mode, use +<code>--offline</code>.</p> +<h4 id="prefer-online"><code>prefer-online</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> </ul> -<p>If true, staleness checks for cached data will be forced, making the CLI look -for updates immediately even for fresh package data.</p> -<h4 id="prefix">prefix</h4> +<p>If true, staleness checks for cached data will be forced, making the CLI +look for updates immediately even for fresh package data.</p> +<h4 id="prefix"><code>prefix</code></h4> <ul> -<li>Default: see <a href="../configuring-npm/folders.html">folders</a></li> -<li>Type: path</li> +<li>Default: In global mode, the folder where the node executable is installed. +In local mode, the nearest parent folder containing either a package.json +file or a node_modules folder.</li> +<li>Type: Path</li> </ul> -<p>The location to install global items. If set on the command line, then -it forces non-global commands to run in the specified folder.</p> -<h4 id="preid">preid</h4> +<p>The location to install global items. If set on the command line, then it +forces non-global commands to run in the specified folder.</p> +<h4 id="preid"><code>preid</code></h4> <ul> <li>Default: “”</li> <li>Type: String</li> </ul> -<p>The “prerelease identifier” to use as a prefix for the “prerelease” part of a -semver. Like the <code>rc</code> in <code>1.2.0-rc.8</code>.</p> -<h4 id="production">production</h4> -<ul> -<li>Default: false</li> -<li>Type: Boolean</li> -</ul> -<p>Set to true to run in “production” mode.</p> -<ol> -<li>devDependencies are not installed at the topmost level when running -local <code>npm install</code> without any arguments.</li> -<li>Set the NODE_ENV=“production” for lifecycle scripts.</li> -</ol> -<h4 id="progress">progress</h4> +<p>The “prerelease identifier” to use as a prefix for the “prerelease” part of +a semver. Like the <code>rc</code> in <code>1.2.0-rc.8</code>.</p> +<h4 id="progress"><code>progress</code></h4> <ul> -<li>Default: true, unless TRAVIS or CI env vars set.</li> +<li>Default: <code>true</code> unless running in a known CI system</li> <li>Type: Boolean</li> </ul> <p>When set to <code>true</code>, npm will display a progress bar during time intensive operations, if <code>process.stderr</code> is a TTY.</p> <p>Set to <code>false</code> to suppress the progress bar.</p> -<h4 id="proxy">proxy</h4> +<h4 id="proxy"><code>proxy</code></h4> <ul> <li>Default: null</li> -<li>Type: url</li> +<li>Type: null, false, or URL</li> </ul> <p>A proxy to use for outgoing http requests. If the <code>HTTP_PROXY</code> or -<code>http_proxy</code> environment variables are set, proxy settings will be -honored by the underlying <code>request</code> library.</p> -<h4 id="read-only">read-only</h4> +<code>http_proxy</code> environment variables are set, proxy settings will be honored +by the underlying <code>request</code> library.</p> +<h4 id="read-only"><code>read-only</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> </ul> -<p>This is used to mark a token as unable to publish when configuring limited access tokens with the <code>npm token create</code> command.</p> -<h4 id="rebuild-bundle">rebuild-bundle</h4> +<p>This is used to mark a token as unable to publish when configuring limited +access tokens with the <code>npm token create</code> command.</p> +<h4 id="rebuild-bundle"><code>rebuild-bundle</code></h4> <ul> <li>Default: true</li> <li>Type: Boolean</li> </ul> <p>Rebuild bundled dependencies after installation.</p> -<h4 id="registry">registry</h4> -<ul> -<li>Default: <a href="https://registry.npmjs.org/">https://registry.npmjs.org/</a></li> -<li>Type: url</li> -</ul> -<p>The base URL of the npm package registry.</p> -<h4 id="rollback">rollback</h4> +<h4 id="registry"><code>registry</code></h4> <ul> -<li>Default: true</li> -<li>Type: Boolean</li> +<li>Default: “<a href="https://registry.npmjs.org/">https://registry.npmjs.org/</a>”</li> +<li>Type: URL</li> </ul> -<p>Remove failed installs.</p> -<h4 id="save">save</h4> +<p>The base URL of the npm registry.</p> +<h4 id="save"><code>save</code></h4> <ul> <li>Default: true</li> <li>Type: Boolean</li> </ul> <p>Save installed packages to a package.json file as dependencies.</p> -<p>When used with the <code>npm rm</code> command, it removes it from the <code>dependencies</code> -object.</p> -<p>Only works if there is already a package.json file present.</p> -<h4 id="save-bundle">save-bundle</h4> +<p>When used with the <code>npm rm</code> command, removes the dependency from +package.json.</p> +<h4 id="save-bundle"><code>save-bundle</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> @@ -1008,161 +992,122 @@ object.</p> <p>If a package would be saved at install time by the use of <code>--save</code>, <code>--save-dev</code>, or <code>--save-optional</code>, then also put it in the <code>bundleDependencies</code> list.</p> -<p>When used with the <code>npm rm</code> command, it removes it from the -bundledDependencies list.</p> -<h4 id="save-prod">save-prod</h4> +<p>Ignore if <code>--save-peer</code> is set, since peerDependencies cannot be bundled.</p> +<h4 id="save-dev"><code>save-dev</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> </ul> -<p>Makes sure that a package will be saved into <code>dependencies</code> specifically. This -is useful if a package already exists in <code>devDependencies</code> or -<code>optionalDependencies</code>, but you want to move it to be a production dep. This is -also the default behavior if <code>--save</code> is true, and neither <code>--save-dev</code> or -<code>--save-optional</code> are true.</p> -<h4 id="save-dev">save-dev</h4> +<p>Save installed packages to a package.json file as <code>devDependencies</code>.</p> +<h4 id="save-exact"><code>save-exact</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> </ul> -<p>Save installed packages to a package.json file as <code>devDependencies</code>.</p> -<p>When used with the <code>npm rm</code> command, it removes it from the -<code>devDependencies</code> object.</p> -<p>Only works if there is already a package.json file present.</p> -<h4 id="save-exact">save-exact</h4> +<p>Dependencies saved to package.json will be configured with an exact version +rather than using npm’s default semver range operator.</p> +<h4 id="save-optional"><code>save-optional</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> </ul> -<p>Dependencies saved to package.json using <code>--save</code>, <code>--save-dev</code> or -<code>--save-optional</code> will be configured with an exact version rather than -using npm’s default semver range operator.</p> -<h4 id="save-optional">save-optional</h4> +<p>Save installed packages to a package.json file as <code>optionalDependencies</code>.</p> +<h4 id="save-peer"><code>save-peer</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> </ul> -<p>Save installed packages to a package.json file as -optionalDependencies.</p> -<p>When used with the <code>npm rm</code> command, it removes it from the -<code>devDependencies</code> object.</p> -<p>Only works if there is already a package.json file present.</p> -<h4 id="save-prefix">save-prefix</h4> +<p>Save installed packages. to a package.json file as <code>peerDependencies</code></p> +<h4 id="save-prefix"><code>save-prefix</code></h4> <ul> -<li>Default: ‘^’</li> +<li>Default: “^”</li> <li>Type: String</li> </ul> <p>Configure how versions of packages installed to a package.json file via <code>--save</code> or <code>--save-dev</code> get prefixed.</p> -<p>For example if a package has version <code>1.2.3</code>, by default its version is -set to <code>^1.2.3</code> which allows minor upgrades for that package, but after -<code>npm config set save-prefix='~'</code> it would be set to <code>~1.2.3</code> which only allows +<p>For example if a package has version <code>1.2.3</code>, by default its version is set +to <code>^1.2.3</code> which allows minor upgrades for that package, but after <code>npm config set save-prefix='~'</code> it would be set to <code>~1.2.3</code> which only allows patch upgrades.</p> -<h4 id="scope">scope</h4> +<h4 id="save-prod"><code>save-prod</code></h4> +<ul> +<li>Default: false</li> +<li>Type: Boolean</li> +</ul> +<p>Save installed packages into <code>dependencies</code> specifically. This is useful if +a package already exists in <code>devDependencies</code> or <code>optionalDependencies</code>, but +you want to move it to be a non-optional production dependency.</p> +<p>This is the default behavior if <code>--save</code> is true, and neither <code>--save-dev</code> +or <code>--save-optional</code> are true.</p> +<h4 id="scope"><code>scope</code></h4> <ul> <li>Default: the scope of the current project, if any, or “”</li> <li>Type: String</li> </ul> -<p>Associate an operation with a scope for a scoped registry. Useful when logging -in to a private registry for the first time: -<code>npm login --scope=@organization --registry=registry.organization.com</code>, which -will cause <code>@organization</code> to be mapped to the registry for future installation -of packages specified according to the pattern <code>@organization/package</code>.</p> -<h4 id="script-shell">script-shell</h4> +<p>Associate an operation with a scope for a scoped registry.</p> +<p>Useful when logging in to a private registry for the first time:</p> +<pre lang="bash"><code>npm login --scope=@mycorp --registry=https://registry.mycorp.com +</code></pre> +<p>This will cause <code>@mycorp</code> to be mapped to the registry for future +installation of packages specified according to the pattern +<code>@mycorp/package</code>.</p> +<h4 id="script-shell"><code>script-shell</code></h4> <ul> -<li>Default: <code>null</code></li> -<li>Type: path</li> +<li>Default: ‘/bin/sh’ on POSIX systems, ‘cmd.exe’ on Windows</li> +<li>Type: null or String</li> </ul> <p>The shell to use for scripts run with the <code>npm run</code> command.</p> -<h4 id="scripts-prepend-node-path">scripts-prepend-node-path</h4> -<ul> -<li>Default: “warn-only”</li> -<li>Type: Boolean, <code>"auto"</code> or <code>"warn-only"</code></li> -</ul> -<p>If set to <code>true</code>, add the directory in which the current <code>node</code> executable -resides to the <code>PATH</code> environment variable when running scripts, -even if that means that <code>npm</code> will invoke a different <code>node</code> executable than -the one which it is running.</p> -<p>If set to <code>false</code>, never modify <code>PATH</code> with that.</p> -<p>If set to <code>"warn-only"</code>, never modify <code>PATH</code> but print a warning if <code>npm</code> thinks -that you may want to run it with <code>true</code>, e.g. because the <code>node</code> executable -in the <code>PATH</code> is not the one <code>npm</code> was invoked with.</p> -<p>If set to <code>auto</code>, only add that directory to the <code>PATH</code> environment variable -if the <code>node</code> executable with which <code>npm</code> was invoked and the one that is found -first on the <code>PATH</code> are different.</p> -<h4 id="searchexclude">searchexclude</h4> +<h4 id="searchexclude"><code>searchexclude</code></h4> <ul> <li>Default: “”</li> <li>Type: String</li> </ul> <p>Space-separated options that limit the results from search.</p> -<h4 id="searchopts">searchopts</h4> -<ul> -<li>Default: “”</li> -<li>Type: String</li> -</ul> -<p>Space-separated options that are always passed to search.</p> -<h4 id="searchlimit">searchlimit</h4> +<h4 id="searchlimit"><code>searchlimit</code></h4> <ul> <li>Default: 20</li> <li>Type: Number</li> </ul> <p>Number of items to limit search results to. Will not apply at all to legacy searches.</p> -<h4 id="searchstaleness">searchstaleness</h4> +<h4 id="searchopts"><code>searchopts</code></h4> +<ul> +<li>Default: “”</li> +<li>Type: String</li> +</ul> +<p>Space-separated options that are always passed to search.</p> +<h4 id="searchstaleness"><code>searchstaleness</code></h4> <ul> -<li>Default: 900 (15 minutes)</li> +<li>Default: 900</li> <li>Type: Number</li> </ul> <p>The age of the cache, in seconds, before another registry request is made if using legacy search endpoint.</p> -<h4 id="shell">shell</h4> +<h4 id="shell"><code>shell</code></h4> <ul> -<li>Default: SHELL environment variable, or “bash” on Posix, or “cmd” on +<li>Default: SHELL environment variable, or “bash” on Posix, or “cmd.exe” on Windows</li> -<li>Type: path</li> +<li>Type: String</li> </ul> <p>The shell to run for the <code>npm explore</code> command.</p> -<h4 id="shrinkwrap">shrinkwrap</h4> -<ul> -<li>Default: true</li> -<li>Type: Boolean</li> -</ul> -<p>If set to false, then ignore <code>npm-shrinkwrap.json</code> files when installing. This -will also prevent <em>writing</em> <code>npm-shrinkwrap.json</code> if <code>save</code> is true.</p> -<p>This option is an alias for <code>--package-lock</code>.</p> -<h4 id="sign-git-commit">sign-git-commit</h4> +<h4 id="sign-git-commit"><code>sign-git-commit</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> </ul> <p>If set to true, then the <code>npm version</code> command will commit the new package version using <code>-S</code> to add a signature.</p> -<p>Note that git requires you to have set up GPG keys in your git configs -for this to work properly.</p> -<h4 id="sign-git-tag">sign-git-tag</h4> +<p>Note that git requires you to have set up GPG keys in your git configs for +this to work properly.</p> +<h4 id="sign-git-tag"><code>sign-git-tag</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> </ul> -<p>If set to true, then the <code>npm version</code> command will tag the version -using <code>-s</code> to add a signature.</p> -<p>Note that git requires you to have set up GPG keys in your git configs -for this to work properly.</p> -<h4 id="sso-poll-frequency">sso-poll-frequency</h4> -<ul> -<li>Default: 500</li> -<li>Type: Number</li> -</ul> -<p>When used with SSO-enabled <code>auth-type</code>s, configures how regularly the registry -should be polled while the user is completing authentication.</p> -<h4 id="sso-type">sso-type</h4> -<ul> -<li>Default: ‘oauth’</li> -<li>Type: ‘oauth’, ‘saml’, or null</li> -</ul> -<p>If <code>--auth-type=sso</code>, the type of SSO type to use.</p> -<h4 id="strict-peer-deps">strict-peer-deps</h4> +<p>If set to true, then the <code>npm version</code> command will tag the version using +<code>-s</code> to add a signature.</p> +<p>Note that git requires you to have set up GPG keys in your git configs for +this to work properly.</p> +<h4 id="strict-peer-deps"><code>strict-peer-deps</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> @@ -1171,122 +1116,296 @@ should be polled while the user is completing authentication.</p> conflicting <code>peerDependencies</code> will be treated as an install failure, even if npm could reasonably guess the appropriate resolution based on non-peer dependency relationships.</p> -<p>By default, conflicting <code>peerDependencies</code> in the dependency graph will be -resolved using the nearest non-peer dependency specification, even if doing -so will result in some packages receiving a peer dependency outside the -range set in their package’s <code>peerDependencies</code> object. When such and -override is performed, a warning is printed, explaining the conflict and -the packages involved. If <code>--strict-peer-deps</code> is set, then the warning is -treated as a failure.</p> -<h4 id="strict-ssl">strict-ssl</h4> +<p>By default, conflicting <code>peerDependencies</code> deep in the dependency graph will +be resolved using the nearest non-peer dependency specification, even if +doing so will result in some packages receiving a peer dependency outside +the range set in their package’s <code>peerDependencies</code> object.</p> +<p>When such and override is performed, a warning is printed, explaining the +conflict and the packages involved. If <code>--strict-peer-deps</code> is set, then +this warning is treated as a failure.</p> +<h4 id="strict-ssl"><code>strict-ssl</code></h4> <ul> <li>Default: true</li> <li>Type: Boolean</li> </ul> -<p>Whether or not to do SSL key validation when making requests to the -registry via https.</p> +<p>Whether or not to do SSL key validation when making requests to the registry +via https.</p> <p>See also the <code>ca</code> config.</p> -<h4 id="tag">tag</h4> +<h4 id="tag"><code>tag</code></h4> <ul> -<li>Default: latest</li> +<li>Default: “latest”</li> <li>Type: String</li> </ul> -<p>If you ask npm to install a package and don’t tell it a specific version, then -it will install the specified tag.</p> -<p>Also the tag that is added to the package@version specified by the <code>npm tag</code> command, if no explicit tag is given.</p> -<h4 id="tag-version-prefix">tag-version-prefix</h4> +<p>If you ask npm to install a package and don’t tell it a specific version, +then it will install the specified tag.</p> +<p>Also the tag that is added to the package@version specified by the <code>npm tag</code> +command, if no explicit tag is given.</p> +<h4 id="tag-version-prefix"><code>tag-version-prefix</code></h4> <ul> -<li>Default: <code>"v"</code></li> +<li>Default: “v”</li> <li>Type: String</li> </ul> <p>If set, alters the prefix used when tagging a new version when performing a -version increment using <code>npm-version</code>. To remove the prefix altogether, set it -to the empty string: <code>""</code>.</p> -<p>Because other tools may rely on the convention that npm version tags look like -<code>v1.0.0</code>, <em>only use this property if it is absolutely necessary</em>. In +version increment using <code>npm-version</code>. To remove the prefix altogether, set +it to the empty string: <code>""</code>.</p> +<p>Because other tools may rely on the convention that npm version tags look +like <code>v1.0.0</code>, <em>only use this property if it is absolutely necessary</em>. In particular, use care when overriding this setting for public packages.</p> -<h4 id="timing">timing</h4> +<h4 id="timing"><code>timing</code></h4> <ul> -<li>Default: <code>false</code></li> +<li>Default: false</li> <li>Type: Boolean</li> </ul> <p>If true, writes an <code>npm-debug</code> log to <code>_logs</code> and timing information to -<code>_timing.json</code>, both in your cache. <code>_timing.json</code> is a newline delimited -list of JSON objects. You can quickly view it with this -<a href="https://www.npmjs.com/package/json">json</a> command line: -<code>json -g < ~/.npm/_timing.json</code>.</p> -<h4 id="tmp">tmp</h4> +<code>_timing.json</code>, both in your cache, even if the command completes +successfully. <code>_timing.json</code> is a newline delimited list of JSON objects.</p> +<p>You can quickly view it with this <a href="https://npm.im/json">json</a> command line: +<code>npm exec -- json -g < ~/.npm/_timing.json</code>.</p> +<h4 id="umask"><code>umask</code></h4> <ul> -<li>Default: TMPDIR environment variable, or “/tmp”</li> -<li>Type: path</li> +<li>Default: 0</li> +<li>Type: Octal numeric string in range 0000..0777 (0..511)</li> </ul> -<p>Where to store temporary files and folders. All temp files are deleted -on success, but left behind on failure for forensic purposes.</p> -<h4 id="unicode">unicode</h4> -<ul> -<li>Default: false on windows, true on mac/unix systems with a unicode locale</li> +<p>The “umask” value to use when setting the file creation mode on files and +folders.</p> +<p>Folders and executables are given a mode which is <code>0o777</code> masked against +this value. Other files are given a mode which is <code>0o666</code> masked against +this value.</p> +<p>Note that the underlying system will <em>also</em> apply its own umask value to +files and folders that are created, and npm does not circumvent this, but +rather adds the <code>--umask</code> config to it.</p> +<p>Thus, the effective default umask value on most POSIX systems is 0o22, +meaning that folders and executables are created with a mode of 0o755 and +other files are created with a mode of 0o644.</p> +<h4 id="unicode"><code>unicode</code></h4> +<ul> +<li>Default: false on windows, true on mac/unix systems with a unicode locale, +as defined by the LC_ALL, LC_CTYPE, or LANG environment variables.</li> <li>Type: Boolean</li> </ul> -<p>When set to true, npm uses unicode characters in the tree output. When -false, it uses ascii characters to draw trees.</p> -<h4 id="update-notifier">update-notifier</h4> +<p>When set to true, npm uses unicode characters in the tree output. When +false, it uses ascii characters instead of unicode glyphs.</p> +<h4 id="update-notifier"><code>update-notifier</code></h4> <ul> <li>Default: true</li> <li>Type: Boolean</li> </ul> -<p>Set to false to suppress the update notification when using an older -version of npm than the latest.</p> -<h4 id="usage">usage</h4> +<p>Set to false to suppress the update notification when using an older version +of npm than the latest.</p> +<h4 id="usage"><code>usage</code></h4> <ul> <li>Default: false</li> <li>Type: Boolean</li> </ul> -<p>Set to show short usage output (like the -H output) -instead of complete help when doing <a href="../commands/npm-help.html"><code>npm help</code></a>.</p> -<h4 id="userconfig">userconfig</h4> +<p>Show short usage output about the command specified.</p> +<h4 id="user-agent"><code>user-agent</code></h4> <ul> -<li>Default: ~/.npmrc</li> -<li>Type: path</li> +<li>Default: “npm/{npm-version} node/{node-version} {platform} {arch} {ci}”</li> +<li>Type: String</li> </ul> -<p>The location of user-level configuration settings.</p> -<h4 id="umask">umask</h4> +<p>Sets the User-Agent request header. The following fields are replaced with +their actual counterparts:</p> <ul> -<li>Default: 022</li> -<li>Type: Octal numeric string in range 0000..0777 (0..511)</li> +<li><code>{npm-version}</code> - The npm version in use</li> +<li><code>{node-version}</code> - The Node.js version in use</li> +<li><code>{platform}</code> - The value of <code>process.platform</code></li> +<li><code>{arch}</code> - The value of <code>process.arch</code></li> +<li><code>{ci}</code> - The value of the <code>ci-name</code> config, if set, prefixed with <code>ci/</code>, or +an empty string if <code>ci-name</code> is empty.</li> </ul> -<p>The “umask” value to use when setting the file creation mode on files -and folders.</p> -<p>Folders and executables are given a mode which is <code>0777</code> masked against -this value. Other files are given a mode which is <code>0666</code> masked against -this value. Thus, the defaults are <code>0755</code> and <code>0644</code> respectively.</p> -<h4 id="user-agent">user-agent</h4> +<h4 id="userconfig"><code>userconfig</code></h4> <ul> -<li>Default: node/{process.version} {process.platform} {process.arch}</li> -<li>Type: String</li> +<li>Default: “~/.npmrc”</li> +<li>Type: Path</li> </ul> -<p>Sets a User-Agent to the request header</p> -<h4 id="version">version</h4> +<p>The location of user-level configuration settings.</p> +<p>This may be overridden by the <code>npm_config_userconfig</code> environment variable +or the <code>--userconfig</code> command line option, but may <em>not</em> be overridden by +settings in the <code>globalconfig</code> file.</p> +<h4 id="version"><code>version</code></h4> <ul> <li>Default: false</li> -<li>Type: boolean</li> +<li>Type: Boolean</li> </ul> <p>If true, output the npm version and exit successfully.</p> <p>Only relevant when specified explicitly on the command line.</p> -<h4 id="versions">versions</h4> +<h4 id="versions"><code>versions</code></h4> <ul> <li>Default: false</li> -<li>Type: boolean</li> +<li>Type: Boolean</li> </ul> -<p>If true, output the npm version as well as node’s <code>process.versions</code> map, and -exit successfully.</p> +<p>If true, output the npm version as well as node’s <code>process.versions</code> map and +the version in the current working directory’s <code>package.json</code> file if one +exists, and exit successfully.</p> <p>Only relevant when specified explicitly on the command line.</p> -<h4 id="viewer">viewer</h4> +<h4 id="viewer"><code>viewer</code></h4> <ul> <li>Default: “man” on Posix, “browser” on Windows</li> -<li>Type: path</li> +<li>Type: String</li> </ul> <p>The program to use to view help content.</p> <p>Set to <code>"browser"</code> to view html help content in the default web browser.</p> +<h4 id="which"><code>which</code></h4> +<ul> +<li>Default: null</li> +<li>Type: null or Number</li> +</ul> +<p>If there are multiple funding sources, which 1-indexed source URL to open.</p> +<h4 id="workspace"><code>workspace</code></h4> +<ul> +<li>Default:</li> +<li>Type: String (can be set multiple times)</li> +</ul> +<p>Enable running a command in the context of the configured workspaces of the +current project while filtering by running only the workspaces defined by +this configuration option.</p> +<p>Valid values for the <code>workspace</code> config are either: - Workspace names - Path +to a workspace directory - Path to a parent workspace directory (will result +to selecting all of the nested workspaces)</p> +<h4 id="workspaces"><code>workspaces</code></h4> +<ul> +<li>Default: false</li> +<li>Type: Boolean</li> +</ul> +<p>Enable running a command in the context of <strong>all</strong> the configured +workspaces.</p> +<h4 id="yes"><code>yes</code></h4> +<ul> +<li>Default: null</li> +<li>Type: null or Boolean</li> +</ul> +<p>Automatically answer “yes” to any prompts that npm might print on the +command line.</p> +<h4 id="also"><code>also</code></h4> +<ul> +<li>Default: null</li> +<li>Type: null, “dev”, or “development”</li> +<li>DEPRECATED: Please use –include=dev instead.</li> +</ul> +<p>When set to <code>dev</code> or <code>development</code>, this is an alias for <code>--include=dev</code>.</p> +<h4 id="auth-type"><code>auth-type</code></h4> +<ul> +<li>Default: “legacy”</li> +<li>Type: “legacy”, “sso”, “saml”, or “oauth”</li> +<li>DEPRECATED: This method of SSO/SAML/OAuth is deprecated and will be removed +in a future version of npm in favor of web-based login.</li> +</ul> +<p>What authentication strategy to use with <code>adduser</code>/<code>login</code>.</p> +<h4 id="cache-max"><code>cache-max</code></h4> +<ul> +<li>Default: Infinity</li> +<li>Type: Number</li> +<li>DEPRECATED: This option has been deprecated in favor of <code>--prefer-online</code></li> +</ul> +<p><code>--cache-max=0</code> is an alias for <code>--prefer-online</code></p> +<h4 id="cache-min"><code>cache-min</code></h4> +<ul> +<li>Default: 0</li> +<li>Type: Number</li> +<li>DEPRECATED: This option has been deprecated in favor of <code>--prefer-offline</code>.</li> +</ul> +<p><code>--cache-min=9999 (or bigger)</code> is an alias for <code>--prefer-offline</code>.</p> +<h4 id="initauthoremail"><code>init.author.email</code></h4> +<ul> +<li>Default: “”</li> +<li>Type: String</li> +<li>DEPRECATED: Use <code>--init-author-email</code> instead.</li> +</ul> +<p>Alias for <code>--init-author-email</code></p> +<h4 id="initauthorname"><code>init.author.name</code></h4> +<ul> +<li>Default: “”</li> +<li>Type: String</li> +<li>DEPRECATED: Use <code>--init-author-name</code> instead.</li> +</ul> +<p>Alias for <code>--init-author-name</code></p> +<h4 id="initauthorurl"><code>init.author.url</code></h4> +<ul> +<li>Default: “”</li> +<li>Type: “” or URL</li> +<li>DEPRECATED: Use <code>--init-author-url</code> instead.</li> +</ul> +<p>Alias for <code>--init-author-url</code></p> +<h4 id="initlicense"><code>init.license</code></h4> +<ul> +<li>Default: “ISC”</li> +<li>Type: String</li> +<li>DEPRECATED: Use <code>--init-license</code> instead.</li> +</ul> +<p>Alias for <code>--init-license</code></p> +<h4 id="initmodule"><code>init.module</code></h4> +<ul> +<li>Default: “~/.npm-init.js”</li> +<li>Type: Path</li> +<li>DEPRECATED: Use <code>--init-module</code> instead.</li> +</ul> +<p>Alias for <code>--init-module</code></p> +<h4 id="initversion"><code>init.version</code></h4> +<ul> +<li>Default: “1.0.0”</li> +<li>Type: SemVer string</li> +<li>DEPRECATED: Use <code>--init-version</code> instead.</li> +</ul> +<p>Alias for <code>--init-version</code></p> +<h4 id="only"><code>only</code></h4> +<ul> +<li>Default: null</li> +<li>Type: null, “prod”, or “production”</li> +<li>DEPRECATED: Use <code>--omit=dev</code> to omit dev dependencies from the install.</li> +</ul> +<p>When set to <code>prod</code> or <code>production</code>, this is an alias for <code>--omit=dev</code>.</p> +<h4 id="optional"><code>optional</code></h4> +<ul> +<li>Default: null</li> +<li>Type: null or Boolean</li> +<li>DEPRECATED: Use <code>--omit=optional</code> to exclude optional dependencies, or +<code>--include=optional</code> to include them.</li> +</ul> +<p>Default value does install optional deps unless otherwise omitted.</p> +<p>Alias for –include=optional or –omit=optional</p> +<h4 id="production"><code>production</code></h4> +<ul> +<li>Default: false</li> +<li>Type: Boolean</li> +<li>DEPRECATED: Use <code>--omit=dev</code> instead.</li> +</ul> +<p>Alias for <code>--omit=dev</code></p> +<h4 id="shrinkwrap"><code>shrinkwrap</code></h4> +<ul> +<li>Default: true</li> +<li>Type: Boolean</li> +<li>DEPRECATED: Use the –package-lock setting instead.</li> +</ul> +<p>Alias for –package-lock</p> +<h4 id="sso-poll-frequency"><code>sso-poll-frequency</code></h4> +<ul> +<li>Default: 500</li> +<li>Type: Number</li> +<li>DEPRECATED: The –auth-type method of SSO/SAML/OAuth will be removed in a +future version of npm in favor of web-based login.</li> +</ul> +<p>When used with SSO-enabled <code>auth-type</code>s, configures how regularly the +registry should be polled while the user is completing authentication.</p> +<h4 id="sso-type"><code>sso-type</code></h4> +<ul> +<li>Default: “oauth”</li> +<li>Type: null, “oauth”, or “saml”</li> +<li>DEPRECATED: The –auth-type method of SSO/SAML/OAuth will be removed in a +future version of npm in favor of web-based login.</li> +</ul> +<p>If <code>--auth-type=sso</code>, the type of SSO type to use.</p> +<h4 id="tmp"><code>tmp</code></h4> +<ul> +<li>Default: The value returned by the Node.js <code>os.tmpdir()</code> method +<a href="https://nodejs.org/api/os.html#os_os_tmpdir">https://nodejs.org/api/os.html#os_os_tmpdir</a></li> +<li>Type: Path</li> +<li>DEPRECATED: This setting is no longer used. npm stores temporary files in a +special location in the cache, and they are managed by +<a href="http://npm.im/cacache"><code>cacache</code></a>.</li> +</ul> +<p>Historically, the location where temporary files were stored. No longer +relevant.</p> +<!-- raw HTML omitted --> <h3 id="see-also">See also</h3> <ul> <li><a href="../commands/npm-config.html">npm config</a></li> diff --git a/deps/npm/docs/output/using-npm/workspaces.html b/deps/npm/docs/output/using-npm/workspaces.html index ffec6467c4..0fb1391c79 100644 --- a/deps/npm/docs/output/using-npm/workspaces.html +++ b/deps/npm/docs/output/using-npm/workspaces.html @@ -141,7 +141,7 @@ npm command-line interface <section id="table_of_contents"> <h2 id="table-of-contents">Table of contents</h2> -<div id="_table_of_contents"><ul><li><a href="#description">Description</a></li><li><a href="#installing-workspaces">Installing workspaces</a></li><li><a href="#using-workspaces">Using workspaces</a></li><li><a href="#see-also">See also</a></li></ul></div> +<div id="_table_of_contents"><ul><li><a href="#description">Description</a></li><li><a href="#installing-workspaces">Installing workspaces</a></li><li><a href="#using-workspaces">Using workspaces</a></li><li><a href="#running-commands-in-the-context-of-workspaces">Running commands in the context of workspaces</a></li><li><a href="#see-also">See also</a></li></ul></div> </section> <div id="_content"><h3 id="description">Description</h3> @@ -206,10 +206,40 @@ console.log(moduleA) // -> a <strong>workspaces</strong> to enable a portable workflow for requiring each <strong>workspace</strong> in such a way that is also easy to <a href="../commands/npm-publish.html">publish</a> these nested workspaces to be consumed elsewhere.</p> +<h3 id="running-commands-in-the-context-of-workspaces">Running commands in the context of workspaces</h3> +<p>You man use the <code>workspace</code> configuration option to run commands in the context +of a configured workspace.</p> +<p>Following is a quick example on how to use the <code>npm run</code> command in the context +of nested workspaces. For a project containing multiple workspaces, e.g:</p> +<pre><code>. ++-- package.json +`-- packages + +-- a + | `-- package.json + `-- b + `-- package.json +</code></pre> +<p>By running a command using the <code>workspace</code> option, it’s possible to run the +given command in the context of that specific workspace. e.g:</p> +<pre><code>npm run test --workspace=a +</code></pre> +<p>This will run the <code>test</code> script defined within the +<code>./packages/a/package.json</code> file.</p> +<p>Please note that you can also specify this argument multiple times in the +command-line in order to target multiple workspaces, e.g:</p> +<pre><code>npm run test --workspace=a --workspace=b +</code></pre> +<p>It’s also possible to use the <code>workspaces</code> (plural) configuration option to +enable the same behavior but running that command in the context of <strong>all</strong> +configured workspaces. e.g:</p> +<pre><code>npm run test --workspaces +</code></pre> +<p>Will run the <code>test</code> script in both <code>./packages/a</code> and <code>./packages/b</code>.</p> <h3 id="see-also">See also</h3> <ul> <li><a href="../commands/npm-install.html">npm install</a></li> <li><a href="../commands/npm-publish.html">npm publish</a></li> +<li><a href="../commands/npm-run-script.html">npm run-script</a></li> </ul> </div> diff --git a/deps/npm/lib/access.js b/deps/npm/lib/access.js index 0df36beeac..3df611e564 100644 --- a/deps/npm/lib/access.js +++ b/deps/npm/lib/access.js @@ -20,6 +20,10 @@ const subcommands = [ ] class Access extends BaseCommand { + static get description () { + return 'Set access level on published packages' + } + static get name () { return 'access' } @@ -75,7 +79,7 @@ class Access extends BaseCommand { if (!subcommands.includes(cmd) || !this[cmd]) throw this.usageError(`${cmd} is not a recognized subcommand.`) - return this[cmd](args, { ...this.npm.flatOptions }) + return this[cmd](args, this.npm.flatOptions) } public ([pkg], opts) { diff --git a/deps/npm/lib/adduser.js b/deps/npm/lib/adduser.js index da318a1f3f..f35b9829fe 100644 --- a/deps/npm/lib/adduser.js +++ b/deps/npm/lib/adduser.js @@ -9,12 +9,20 @@ const authTypes = { } class AddUser extends BaseCommand { + static get description () { + return 'Add a registry user account' + } + static get name () { return 'adduser' } - static get usage () { - return ['[--registry=url] [--scope=@orgname] [--always-auth]'] + static get params () { + return [ + 'registry', + 'scope', + 'always-auth', + ] } exec (args, cb) { diff --git a/deps/npm/lib/audit.js b/deps/npm/lib/audit.js index 6e64987b61..f990e1fa5e 100644 --- a/deps/npm/lib/audit.js +++ b/deps/npm/lib/audit.js @@ -6,18 +6,31 @@ const BaseCommand = require('./base-command.js') class Audit extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Run a security audit' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'audit' } /* istanbul ignore next - see test/lib/load-all-commands.js */ - static get usage () { + static get params () { return [ - '[--json] [--production]', - 'fix [--force|--package-lock-only|--dry-run|--production|--only=(dev|prod)]', + 'dry-run', + 'force', + 'json', + 'package-lock-only', + 'production', ] } + /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get usage () { + return ['[fix]'] + } + async completion (opts) { const argv = opts.conf.argv.remain @@ -37,11 +50,14 @@ class Audit extends BaseCommand { } async audit (args) { - const arb = new Arborist({ + const reporter = this.npm.config.get('json') ? 'json' : 'detail' + const opts = { ...this.npm.flatOptions, audit: true, path: this.npm.prefix, - }) + reporter, + } + const arb = new Arborist(opts) const fix = args[0] === 'fix' await arb.audit({ fix }) if (fix) @@ -49,11 +65,7 @@ class Audit extends BaseCommand { else { // will throw if there's an error, because this is an audit command auditError(this.npm, arb.auditReport) - const reporter = this.npm.flatOptions.json ? 'json' : 'detail' - const result = auditReport(arb.auditReport, { - ...this.npm.flatOptions, - reporter, - }) + const result = auditReport(arb.auditReport, opts) process.exitCode = process.exitCode || result.exitCode this.npm.output(result.report) } diff --git a/deps/npm/lib/base-command.js b/deps/npm/lib/base-command.js index 8e48caa2ef..7a9e4b8ee3 100644 --- a/deps/npm/lib/base-command.js +++ b/deps/npm/lib/base-command.js @@ -1,11 +1,20 @@ // Base class for npm.commands[cmd] const usageUtil = require('./utils/usage.js') +const ConfigDefinitions = require('./utils/config/definitions.js') class BaseCommand { constructor (npm) { this.npm = npm } + get name () { + return this.constructor.name + } + + get description () { + return this.constructor.description + } + get usage () { let usage = `npm ${this.constructor.name}\n\n` if (this.constructor.description) @@ -17,6 +26,9 @@ class BaseCommand { else usage = `${usage}${this.constructor.usage.map(u => `npm ${this.constructor.name} ${u}`).join('\n')}` + if (this.constructor.params) + usage = `${usage}\n\nOptions:\n[${this.constructor.params.map(p => ConfigDefinitions[p].usage).join('] [')}]` + // Mostly this just appends aliases, this could be more clear usage = usageUtil(this.constructor.name, usage) usage = `${usage}\n\nRun "npm help ${this.constructor.name}" for more info` @@ -34,5 +46,12 @@ class BaseCommand { code: 'EUSAGE', }) } + + execWorkspaces (args, filters, cb) { + throw Object.assign( + new Error('This command does not support workspaces.'), + { code: 'ENOWORKSPACES' } + ) + } } module.exports = BaseCommand diff --git a/deps/npm/lib/bin.js b/deps/npm/lib/bin.js index 1450fb539b..20e13f160f 100644 --- a/deps/npm/lib/bin.js +++ b/deps/npm/lib/bin.js @@ -2,12 +2,16 @@ const envPath = require('./utils/path.js') const BaseCommand = require('./base-command.js') class Bin extends BaseCommand { + static get description () { + return 'Display npm bin folder' + } + static get name () { return 'bin' } - static get usage () { - return ['[-g]'] + static get params () { + return ['global'] } exec (args, cb) { @@ -17,7 +21,7 @@ class Bin extends BaseCommand { async bin (args) { const b = this.npm.bin this.npm.output(b) - if (this.npm.flatOptions.global && !envPath.includes(b)) + if (this.npm.config.get('global') && !envPath.includes(b)) console.error('(not in PATH env variable)') } } diff --git a/deps/npm/lib/birthday.js b/deps/npm/lib/birthday.js index 5ea855512f..92b1dd1c2e 100644 --- a/deps/npm/lib/birthday.js +++ b/deps/npm/lib/birthday.js @@ -1,16 +1,9 @@ -class Birthday { - constructor (npm) { - this.npm = npm - Object.defineProperty(this.npm, 'flatOptions', { - value: { - ...npm.flatOptions, - package: ['@npmcli/npm-birthday'], - yes: true, - }, - }) - } +const BaseCommand = require('./base-command.js') +class Birthday extends BaseCommand { exec (args, cb) { + this.npm.config.set('package', ['@npmcli/npm-birthday']) + this.npm.config.set('yes', true) return this.npm.commands.exec(['npm-birthday'], cb) } } diff --git a/deps/npm/lib/bugs.js b/deps/npm/lib/bugs.js index 1814dd7bc4..a0cef4c5ec 100644 --- a/deps/npm/lib/bugs.js +++ b/deps/npm/lib/bugs.js @@ -5,6 +5,10 @@ const hostedFromMani = require('./utils/hosted-git-info-from-manifest.js') const BaseCommand = require('./base-command.js') class Bugs extends BaseCommand { + static get description () { + return 'Report bugs for a package in a web browser' + } + static get name () { return 'bugs' } diff --git a/deps/npm/lib/cache.js b/deps/npm/lib/cache.js index 80a5c68ebc..43902f43bb 100644 --- a/deps/npm/lib/cache.js +++ b/deps/npm/lib/cache.js @@ -7,6 +7,10 @@ const rimraf = promisify(require('rimraf')) const BaseCommand = require('./base-command.js') class Cache extends BaseCommand { + static get description () { + return 'Manipulates packages cache' + } + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'cache' @@ -63,7 +67,7 @@ class Cache extends BaseCommand { throw new Error('npm cache clear does not accept arguments') const cachePath = path.join(this.npm.cache, '_cacache') - if (!this.npm.flatOptions.force) { + if (!this.npm.config.get('force')) { throw new Error(`As of npm@5, the npm cache self-heals from corruption issues by treating integrity mismatches as cache misses. As a result, data extracted from the cache is guaranteed to be valid. If you @@ -100,7 +104,6 @@ with --force.`) throw Object.assign(new Error(usage), { code: 'EUSAGE' }) log.silly('cache add', 'spec', spec) - const opts = { ...this.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 @@ -108,7 +111,7 @@ with --force.`) await pacote.tarball.stream(spec, stream => { stream.resume() return stream.promise() - }, opts) + }, this.npm.flatOptions) } async verify () { diff --git a/deps/npm/lib/ci.js b/deps/npm/lib/ci.js index 3ea1993761..b73b3a8591 100644 --- a/deps/npm/lib/ci.js +++ b/deps/npm/lib/ci.js @@ -21,6 +21,11 @@ const BaseCommand = require('./base-command.js') class CI extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Install a project with a clean slate' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'ci' } @@ -30,14 +35,13 @@ class CI extends BaseCommand { } async ci () { - if (this.npm.flatOptions.global) { + if (this.npm.config.get('global')) { const err = new Error('`npm ci` does not work for global packages') err.code = 'ECIGLOBAL' throw err } const where = this.npm.prefix - const { scriptShell, ignoreScripts } = this.npm.flatOptions const arb = new Arborist({ ...this.npm.flatOptions, path: where }) await Promise.all([ @@ -54,6 +58,7 @@ class CI extends BaseCommand { // npm ci should never modify the lockfile or package.json await arb.reify({ ...this.npm.flatOptions, save: false }) + const ignoreScripts = this.npm.config.get('ignore-scripts') // run the same set of scripts that `npm install` runs. if (!ignoreScripts) { const scripts = [ @@ -65,6 +70,7 @@ class CI extends BaseCommand { 'prepare', 'postprepare', ] + const scriptShell = this.npm.config.get('script-shell') || undefined for (const event of scripts) { await runScript({ path: where, diff --git a/deps/npm/lib/cli.js b/deps/npm/lib/cli.js index 910b674eaa..46859f150e 100644 --- a/deps/npm/lib/cli.js +++ b/deps/npm/lib/cli.js @@ -40,11 +40,14 @@ module.exports = (process) => { npm.load(async er => { if (er) return errorHandler(er) + + // npm --version=cli if (npm.config.get('version', 'cli')) { - console.log(npm.version) + npm.output(npm.version) return errorHandler.exit(0) } + // npm --versions=cli if (npm.config.get('versions', 'cli')) { npm.argv = ['version'] npm.config.set('usage', false, 'cli') @@ -57,9 +60,20 @@ module.exports = (process) => { if (impl) impl(npm.argv, errorHandler) else { - npm.config.set('usage', false) - npm.argv.unshift(cmd) - npm.commands.help(npm.argv, errorHandler) + try { + // I don't know why this is needed but we get a cb() not called if we + // omit it + npm.log.level = 'silent' + if (cmd) { + const didYouMean = require('./utils/did-you-mean.js') + const suggestions = await didYouMean(npm, npm.localPrefix, cmd) + npm.output(`Unknown command: "${cmd}"${suggestions}\n\nTo see a list of supported npm commands, run:\n npm help`) + } else + npm.output(npm.usage) + process.exitCode = 1 + } catch (err) { + errorHandler(err) + } } }) } diff --git a/deps/npm/lib/completion.js b/deps/npm/lib/completion.js index 3ee68cdaca..fa3b5f2dd3 100644 --- a/deps/npm/lib/completion.js +++ b/deps/npm/lib/completion.js @@ -29,13 +29,13 @@ // as an array. // -const { types, shorthands } = require('./utils/config.js') +const { definitions, shorthands } = require('./utils/config/index.js') const deref = require('./utils/deref-command.js') const { aliases, cmdList, plumbing } = require('./utils/cmd-list.js') const aliasNames = Object.keys(aliases) const fullList = cmdList.concat(aliasNames).filter(c => !plumbing.includes(c)) const nopt = require('nopt') -const configNames = Object.keys(types) +const configNames = Object.keys(definitions) const shorthandNames = Object.keys(shorthands) const allConfs = configNames.concat(shorthandNames) const isWindowsShell = require('./utils/is-windows-shell.js') @@ -46,13 +46,13 @@ const BaseCommand = require('./base-command.js') class Completion extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ - static get name () { - return 'completion' + static get description () { + return 'Tab Completion for npm' } /* istanbul ignore next - see test/lib/load-all-commands.js */ - static get description () { - return 'npm command completion script. save to ~/.bashrc or ~/.zshrc' + static get name () { + return 'completion' } // completion for the completion command @@ -147,6 +147,10 @@ class Completion extends BaseCommand { // take a little shortcut and use npm's arg parsing logic. // don't have to worry about the last arg being implicitly // boolean'ed, since the last block will catch that. + const types = Object.entries(definitions).reduce((types, [key, def]) => { + types[key] = def.type + return types + }, {}) const parsed = opts.conf = nopt(types, shorthands, partialWords.slice(0, -1), 0) // check if there's a command already. @@ -256,7 +260,7 @@ const isFlag = word => { const split = word.match(/^(-*)((?:no-)+)?(.*)$/) const no = split[2] const conf = split[3] - const type = types[conf] + const {type} = definitions[conf] return no || type === Boolean || (Array.isArray(type) && type.includes(Boolean)) || diff --git a/deps/npm/lib/config.js b/deps/npm/lib/config.js index c29253e430..d5ef6ec50a 100644 --- a/deps/npm/lib/config.js +++ b/deps/npm/lib/config.js @@ -1,4 +1,5 @@ -const { defaults, types } = require('./utils/config.js') +// don't expand so that we only assemble the set of defaults when needed +const configDefs = require('./utils/config/index.js') const mkdirp = require('mkdirp-infer-owner') const { dirname } = require('path') @@ -29,6 +30,10 @@ const publicVar = k => !/^(\/\/[^:]+:)?_/.test(k) const BaseCommand = require('./base-command.js') class Config extends BaseCommand { + static get description () { + return 'Manage the npm configuration files' + } + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'config' @@ -70,7 +75,7 @@ class Config extends BaseCommand { case 'get': case 'delete': case 'rm': - return Object.keys(types) + return Object.keys(configDefs.definitions) case 'edit': case 'list': case 'ls': @@ -100,7 +105,7 @@ class Config extends BaseCommand { break case 'list': case 'ls': - await (this.npm.flatOptions.json ? this.listJson() : this.list()) + await (this.npm.config.get('json') ? this.listJson() : this.list()) break case 'edit': await this.edit() @@ -117,7 +122,7 @@ class Config extends BaseCommand { if (!args.length) throw this.usageError() - const where = this.npm.flatOptions.global ? 'global' : 'user' + const where = this.npm.config.get('global') ? 'global' : 'user' for (const [key, val] of Object.entries(keyValues(args))) { this.npm.log.info('config', 'set %j %j', key, val) this.npm.config.set(key, val || '', where) @@ -147,14 +152,15 @@ class Config extends BaseCommand { if (!keys.length) throw this.usageError() - const where = this.npm.flatOptions.global ? 'global' : 'user' + const where = this.npm.config.get('global') ? 'global' : 'user' for (const key of keys) this.npm.config.delete(key, where) await this.npm.config.save(where) } async edit () { - const { editor: e, global } = this.npm.flatOptions + const global = this.npm.config.get('global') + const e = this.npm.config.get('editor') const where = global ? 'global' : 'user' const file = this.npm.config.data.get(where).source @@ -165,7 +171,8 @@ class Config extends BaseCommand { const data = ( await readFile(file, 'utf8').catch(() => '') ).replace(/\r\n/g, '\n') - const defData = Object.entries(defaults).reduce((str, [key, val]) => { + const entries = Object.entries(configDefs.defaults) + const defData = entries.reduce((str, [key, val]) => { const obj = { [key]: val } const i = ini.stringify(obj) .replace(/\r\n/g, '\n') // normalizes output from ini.stringify @@ -210,7 +217,7 @@ ${defData} async list () { const msg = [] - const { long } = this.npm.flatOptions + const long = this.npm.config.get('long') for (const [where, { data, source }] of this.npm.config.data.entries()) { if (where === 'default' && !long) continue diff --git a/deps/npm/lib/dedupe.js b/deps/npm/lib/dedupe.js index 50a56211fc..b80a777fcc 100644 --- a/deps/npm/lib/dedupe.js +++ b/deps/npm/lib/dedupe.js @@ -6,6 +6,11 @@ const BaseCommand = require('./base-command.js') class Dedupe extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Reduce duplication in the package tree' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'dedupe' } @@ -23,12 +28,13 @@ class Dedupe extends BaseCommand { const dryRun = this.npm.config.get('dry-run') const where = this.npm.prefix - const arb = new Arborist({ + const opts = { ...this.npm.flatOptions, path: where, dryRun, - }) - await arb.dedupe(this.npm.flatOptions) + } + const arb = new Arborist(opts) + await arb.dedupe(opts) await reifyFinish(this.npm, arb) } } diff --git a/deps/npm/lib/deprecate.js b/deps/npm/lib/deprecate.js index a0c67f805d..c640bcfe09 100644 --- a/deps/npm/lib/deprecate.js +++ b/deps/npm/lib/deprecate.js @@ -7,6 +7,10 @@ const libaccess = require('libnpmaccess') const BaseCommand = require('./base-command.js') class Deprecate extends BaseCommand { + static get description () { + return 'Deprecate a version of a package' + } + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'deprecate' diff --git a/deps/npm/lib/diff.js b/deps/npm/lib/diff.js index 0e322ec643..c5e4b403ef 100644 --- a/deps/npm/lib/diff.js +++ b/deps/npm/lib/diff.js @@ -12,6 +12,10 @@ const readLocalPkg = require('./utils/read-local-package.js') const BaseCommand = require('./base-command.js') class Diff extends BaseCommand { + static get description () { + return 'The registry diff command' + } + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'diff' @@ -30,7 +34,7 @@ class Diff extends BaseCommand { get where () { const globalTop = resolve(this.npm.globalDir, '..') - const { global } = this.npm.flatOptions + const global = this.npm.config.get('global') return global ? globalTop : this.npm.prefix } @@ -39,7 +43,7 @@ class Diff extends BaseCommand { } async diff (args) { - const specs = this.npm.flatOptions.diff.filter(d => d) + const specs = this.npm.config.get('diff').filter(d => d) if (specs.length > 2) { throw new TypeError( 'Can\'t use more than two --diff arguments.\n\n' + @@ -91,7 +95,7 @@ class Diff extends BaseCommand { } return [ - `${pkgName}@${this.npm.flatOptions.defaultTag}`, + `${pkgName}@${this.npm.config.get('tag')}`, `file:${this.npm.prefix}`, ] } diff --git a/deps/npm/lib/dist-tag.js b/deps/npm/lib/dist-tag.js index cdc95ac6f0..13ec37fd8c 100644 --- a/deps/npm/lib/dist-tag.js +++ b/deps/npm/lib/dist-tag.js @@ -8,6 +8,10 @@ const readLocalPkgName = require('./utils/read-local-package.js') const BaseCommand = require('./base-command.js') class DistTag extends BaseCommand { + static get description () { + return 'Modify package distribution tags' + } + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'dist-tag' @@ -61,7 +65,7 @@ class DistTag extends BaseCommand { async add (spec, tag, opts) { spec = npa(spec || '') const version = spec.rawSpec - const defaultTag = tag || opts.defaultTag + const defaultTag = tag || this.npm.config.get('tag') log.verbose('dist-tag add', defaultTag, 'to', spec.name + '@' + version) diff --git a/deps/npm/lib/docs.js b/deps/npm/lib/docs.js index 2dad7a26db..089d77eb04 100644 --- a/deps/npm/lib/docs.js +++ b/deps/npm/lib/docs.js @@ -1,17 +1,23 @@ const log = require('npmlog') const pacote = require('pacote') const openUrl = require('./utils/open-url.js') -const usageUtil = require('./utils/usage.js') const hostedFromMani = require('./utils/hosted-git-info-from-manifest.js') -class Docs { - constructor (npm) { - this.npm = npm +const BaseCommand = require('./base-command.js') +class Docs extends BaseCommand { + /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Open documentation for a package in a web browser' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get name () { + return 'docs' } /* istanbul ignore next - see test/lib/load-all-commands.js */ - get usage () { - return usageUtil('docs', 'npm docs [<pkgname> [<pkgname> ...]]') + static get usage () { + return ['[<pkgname> [<pkgname> ...]]'] } exec (args, cb) { diff --git a/deps/npm/lib/doctor.js b/deps/npm/lib/doctor.js index fbe4471414..99beb25279 100644 --- a/deps/npm/lib/doctor.js +++ b/deps/npm/lib/doctor.js @@ -11,7 +11,7 @@ const { promisify } = require('util') const ansiTrim = require('./utils/ansi-trim.js') const isWindows = require('./utils/is-windows.js') const ping = require('./utils/ping.js') -const { defaults: { registry: defaultRegistry } } = require('./utils/config.js') +const { registry: { default: defaultRegistry } } = require('./utils/config/definitions.js') const lstat = promisify(fs.lstat) const readdir = promisify(fs.readdir) const access = promisify(fs.access) @@ -33,6 +33,11 @@ const maskLabel = mask => { const BaseCommand = require('./base-command.js') class Doctor extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Check your npm environment' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'doctor' } diff --git a/deps/npm/lib/edit.js b/deps/npm/lib/edit.js index 1dbe8e4c10..79d41462eb 100644 --- a/deps/npm/lib/edit.js +++ b/deps/npm/lib/edit.js @@ -9,6 +9,10 @@ const completion = require('./utils/completion/installed-shallow.js') const BaseCommand = require('./base-command.js') class Edit extends BaseCommand { + static get description () { + return 'Edit an installed package' + } + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'edit' diff --git a/deps/npm/lib/exec.js b/deps/npm/lib/exec.js index b2443b17ac..0a61de7c12 100644 --- a/deps/npm/lib/exec.js +++ b/deps/npm/lib/exec.js @@ -1,5 +1,6 @@ const { promisify } = require('util') const read = promisify(require('read')) +const chalk = require('chalk') const mkdirp = require('mkdirp-infer-owner') const readPackageJson = require('read-package-json-fast') const Arborist = require('@npmcli/arborist') @@ -12,6 +13,7 @@ const npa = require('npm-package-arg') const fileExists = require('./utils/file-exists.js') const PATH = require('./utils/path.js') const BaseCommand = require('./base-command.js') +const getWorkspaces = require('./workspaces/get-workspaces.js') // it's like this: // @@ -24,7 +26,7 @@ const BaseCommand = require('./base-command.js') // // npm x -p pkg@version -- foo --registry=/dev/null // -// const pkg = npm.flatOptions.package || getPackageFrom(args[0]) +// const pkg = npm.config.get('package') || getPackageFrom(args[0]) // const cmd = getCommand(pkg, args[0]) // --> npm x -c 'cmd ...args.slice(1)' // @@ -38,15 +40,22 @@ const BaseCommand = require('./base-command.js') // runScript({ pkg, event: 'npx', ... }) // process.env.npm_lifecycle_event = 'npx' +const nocolor = { + reset: s => s, + bold: s => s, + dim: s => s, + green: s => s, +} + class Exec extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ - static get name () { - return 'exec' + static get description () { + return 'Run a command from a local or remote npm package' } /* istanbul ignore next - see test/lib/load-all-commands.js */ - static get description () { - return 'Run a command from a local or remote npm package.' + static get name () { + return 'exec' } /* istanbul ignore next - see test/lib/load-all-commands.js */ @@ -60,17 +69,27 @@ class Exec extends BaseCommand { } exec (args, cb) { - this._exec(args).then(() => cb()).catch(cb) + const path = this.npm.localPrefix + const runPath = process.cwd() + this._exec(args, { path, runPath }).then(() => cb()).catch(cb) + } + + execWorkspaces (args, filters, cb) { + this._execWorkspaces(args, filters).then(() => cb()).catch(cb) } // When commands go async and we can dump the boilerplate exec methods this // can be named correctly - async _exec (args) { - const { package: packages, call, shell } = this.npm.flatOptions + async _exec (_args, { locationMsg, path, runPath }) { + const call = this.npm.config.get('call') + const shell = this.npm.config.get('shell') + // dereferenced because we manipulate it later + const packages = [...this.npm.config.get('package')] - if (call && args.length) + if (call && _args.length) throw this.usage + const args = [..._args] const pathArr = [...PATH] // nothing to maybe install, skip the arborist dance @@ -78,8 +97,11 @@ class Exec extends BaseCommand { return await this.run({ args, call, + locationMsg, shell, + path, pathArr, + runPath, }) } @@ -102,7 +124,10 @@ class Exec extends BaseCommand { return await this.run({ args, call, + locationMsg, + path, pathArr, + runPath, shell, }) } @@ -117,11 +142,11 @@ class Exec extends BaseCommand { // node_modules/${name}/package.json, and only pacote fetch if // that fails. const manis = await Promise.all(packages.map(async p => { - const spec = npa(p, this.npm.localPrefix) + const spec = npa(p, path) if (spec.type === 'tag' && spec.rawSpec === '') { // fall through to the pacote.manifest() approach try { - const pj = resolve(this.npm.localPrefix, 'node_modules', spec.name) + const pj = resolve(path, 'node_modules', spec.name) return await readPackageJson(pj) } catch (er) {} } @@ -140,7 +165,7 @@ class Exec extends BaseCommand { // figure out whether we need to install stuff, or if local is fine const localArb = new Arborist({ ...this.npm.flatOptions, - path: this.npm.localPrefix, + path, }) const tree = await localArb.loadActual() @@ -165,10 +190,10 @@ class Exec extends BaseCommand { // no need to install if already present if (add.length) { - if (!this.npm.flatOptions.yes) { + if (!this.npm.config.get('yes')) { // set -n to always say no - if (this.npm.flatOptions.yes === false) - throw 'canceled' + if (this.npm.config.get('yes') === false) + throw new Error('canceled') if (!process.stdin.isTTY || ciDetect()) { this.npm.log.warn('exec', `The following package${ @@ -184,7 +209,7 @@ class Exec extends BaseCommand { }Ok to proceed? ` const confirm = await read({ prompt, default: 'y' }) if (confirm.trim().toLowerCase().charAt(0) !== 'y') - throw 'canceled' + throw new Error('canceled') } } await arb.reify({ ...this.npm.flatOptions, add }) @@ -192,16 +217,24 @@ class Exec extends BaseCommand { pathArr.unshift(resolve(installDir, 'node_modules/.bin')) } - return await this.run({ args, call, pathArr, shell }) + return await this.run({ + args, + call, + locationMsg, + path, + pathArr, + runPath, + shell, + }) } - async run ({ args, call, pathArr, shell }) { + async run ({ args, call, locationMsg, path, pathArr, runPath, shell }) { // turn list of args into command string const script = call || args.shift() || shell // do the fakey runScript dance // still should work if no package.json in cwd - const realPkg = await readPackageJson(`${this.npm.localPrefix}/package.json`) + const realPkg = await readPackageJson(`${path}/package.json`) .catch(() => ({})) const pkg = { ...realPkg, @@ -217,7 +250,19 @@ class Exec extends BaseCommand { if (process.stdin.isTTY) { if (ciDetect()) return this.npm.log.warn('exec', 'Interactive mode disabled in CI environment') - this.npm.output(`\nEntering npm script environment\nType 'exit' or ^D when finished\n`) + + const color = this.npm.config.get('color') + const colorize = color ? chalk : nocolor + + locationMsg = locationMsg || ` at location:\n${colorize.dim(runPath)}` + + this.npm.output(`${ + colorize.reset('\nEntering npm script environment') + }${ + colorize.reset(locationMsg) + }${ + colorize.bold('\nType \'exit\' or ^D when finished\n') + }`) } } return await runScript({ @@ -225,7 +270,7 @@ class Exec extends BaseCommand { pkg, banner: false, // we always run in cwd, not --prefix - path: process.cwd(), + path: runPath, stdioString: true, event: 'npx', args, @@ -285,5 +330,28 @@ class Exec extends BaseCommand { .digest('hex') .slice(0, 16) } + + async workspaces (filters) { + return getWorkspaces(filters, { path: this.npm.localPrefix }) + } + + async _execWorkspaces (args, filters) { + const workspaces = await this.workspaces(filters) + const getLocationMsg = async path => { + const color = this.npm.config.get('color') + const colorize = color ? chalk : nocolor + const { _id } = await readPackageJson(`${path}/package.json`) + return ` in workspace ${colorize.green(_id)} at location:\n${colorize.dim(path)}` + } + + for (const workspacePath of workspaces.values()) { + const locationMsg = await getLocationMsg(workspacePath) + await this._exec(args, { + locationMsg, + path: workspacePath, + runPath: workspacePath, + }) + } + } } module.exports = Exec diff --git a/deps/npm/lib/explain.js b/deps/npm/lib/explain.js index 6af7611867..4c2908df68 100644 --- a/deps/npm/lib/explain.js +++ b/deps/npm/lib/explain.js @@ -8,6 +8,10 @@ const validName = require('validate-npm-package-name') const BaseCommand = require('./base-command.js') class Explain extends BaseCommand { + static get description () { + return 'Explain installed packages' + } + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'explain' diff --git a/deps/npm/lib/explore.js b/deps/npm/lib/explore.js index 34f6d10793..5f9820c216 100644 --- a/deps/npm/lib/explore.js +++ b/deps/npm/lib/explore.js @@ -8,6 +8,10 @@ const completion = require('./utils/completion/installed-shallow.js') const BaseCommand = require('./base-command.js') class Explore extends BaseCommand { + static get description () { + return 'Browse an installed package' + } + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'explore' diff --git a/deps/npm/lib/find-dupes.js b/deps/npm/lib/find-dupes.js index ecb945f47b..8037876f5b 100644 --- a/deps/npm/lib/find-dupes.js +++ b/deps/npm/lib/find-dupes.js @@ -3,6 +3,11 @@ const BaseCommand = require('./base-command.js') class FindDupes extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Find duplication in the package tree' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'find-dupes' } diff --git a/deps/npm/lib/fund.js b/deps/npm/lib/fund.js index a723c62d2c..25d3462f63 100644 --- a/deps/npm/lib/fund.js +++ b/deps/npm/lib/fund.js @@ -23,13 +23,28 @@ const BaseCommand = require('./base-command.js') class Fund extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Retrieve funding information' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'fund' } /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get params () { + return [ + 'json', + 'browser', + 'unicode', + 'which', + ] + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get usage () { - return ['[--json] [--browser] [--unicode] [[<@scope>/]<pkg> [--which=<fundingSourceNumber>]'] + return ['[[<@scope>/]<pkg>]'] } /* istanbul ignore next - see test/lib/load-all-commands.js */ @@ -42,14 +57,13 @@ class Fund extends BaseCommand { } async fund (args) { - const opts = this.npm.flatOptions const spec = args[0] - const numberArg = opts.which + const numberArg = this.npm.config.get('which') const fundingSourceNumber = numberArg && parseInt(numberArg, 10) const badFundingSourceNumber = - numberArg !== undefined && + numberArg !== null && (String(fundingSourceNumber) !== numberArg || fundingSourceNumber < 1) if (badFundingSourceNumber) { @@ -58,14 +72,14 @@ class Fund extends BaseCommand { throw err } - if (opts.global) { + if (this.npm.config.get('global')) { const err = new Error('`npm fund` does not support global packages') err.code = 'EFUNDGLOBAL' throw err } const where = this.npm.prefix - const arb = new Arborist({ ...opts, path: where }) + const arb = new Arborist({ ...this.npm.flatOptions, path: where }) const tree = await arb.loadActual() if (spec) { @@ -78,23 +92,19 @@ class Fund extends BaseCommand { return } - const print = opts.json - ? this.printJSON - : this.printHuman - - this.npm.output( - print( - getFundingInfo(tree), - opts - ) - ) + if (this.npm.config.get('json')) + this.npm.output(this.printJSON(getFundingInfo(tree))) + else + this.npm.output(this.printHuman(getFundingInfo(tree))) } printJSON (fundingInfo) { return JSON.stringify(fundingInfo, null, 2) } - printHuman (fundingInfo, { color, unicode }) { + printHuman (fundingInfo) { + const color = !!this.npm.color + const unicode = this.npm.config.get('unicode') const seenUrls = new Map() const tree = obj => diff --git a/deps/npm/lib/get.js b/deps/npm/lib/get.js index a5d58accc8..8cfb259a81 100644 --- a/deps/npm/lib/get.js +++ b/deps/npm/lib/get.js @@ -2,6 +2,11 @@ const BaseCommand = require('./base-command.js') class Get extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Get a value from the npm configuration' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'get' } diff --git a/deps/npm/lib/help-search.js b/deps/npm/lib/help-search.js index 4e727c3e72..c1ceae4414 100644 --- a/deps/npm/lib/help-search.js +++ b/deps/npm/lib/help-search.js @@ -1,15 +1,16 @@ const fs = require('fs') const path = require('path') const color = require('ansicolors') -const npmUsage = require('./utils/npm-usage.js') const { promisify } = require('util') const glob = promisify(require('glob')) const readFile = promisify(fs.readFile) -const didYouMean = require('./utils/did-you-mean.js') -const { cmdList } = require('./utils/cmd-list.js') const BaseCommand = require('./base-command.js') class HelpSearch extends BaseCommand { + static get description () { + return 'Search npm help documentation' + } + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'help-search' @@ -26,28 +27,17 @@ class HelpSearch extends BaseCommand { async helpSearch (args) { if (!args.length) - throw this.usage + return this.npm.output(this.usage) const docPath = path.resolve(__dirname, '..', 'docs/content') - const files = await glob(`${docPath}/*/*.md`) const data = await this.readFiles(files) const results = await this.searchFiles(args, data, files) - // if only one result, then just show that help section. - if (results.length === 1) { - return this.npm.commands.help([path.basename(results[0].file, '.md')], er => { - if (er) - throw er - }) - } - const formatted = this.formatResults(args, results) if (!formatted.trim()) - npmUsage(this.npm, false) - else { + this.npm.output(`No matches in help for: ${args.join(' ')}\n`) + else this.npm.output(formatted) - this.npm.output(didYouMean(args[0], cmdList)) - } } async readFiles (files) { @@ -166,7 +156,7 @@ class HelpSearch extends BaseCommand { out.push(' '.repeat((Math.max(1, cols - out.join(' ').length - r.length - 1)))) out.push(r) - if (!this.npm.flatOptions.long) + if (!this.npm.config.get('long')) return out.join('') out.unshift('\n\n') @@ -198,7 +188,7 @@ class HelpSearch extends BaseCommand { return out.join('') }).join('\n') - const finalOut = results.length && !this.npm.flatOptions.long + const finalOut = results.length && !this.npm.config.get('long') ? 'Top hits for ' + (args.map(JSON.stringify).join(' ')) + '\n' + '—'.repeat(cols - 1) + '\n' + out + '\n' + diff --git a/deps/npm/lib/help.js b/deps/npm/lib/help.js index 93abf878ba..b9ff1c9576 100644 --- a/deps/npm/lib/help.js +++ b/deps/npm/lib/help.js @@ -1,14 +1,23 @@ -const npmUsage = require('./utils/npm-usage.js') const { spawn } = require('child_process') const path = require('path') -const log = require('npmlog') const openUrl = require('./utils/open-url.js') -const glob = require('glob') +const { promisify } = require('util') +const glob = promisify(require('glob')) const BaseCommand = require('./base-command.js') +// Strips out the number from foo.7 or foo.7. or foo.7.tgz +// We don't currently compress our man pages but if we ever did this would +// seemlessly continue supporting it +const manNumberRegex = /\.(\d+)(\..*)?$/ + class Help extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Get help on npm' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'help' } @@ -22,13 +31,7 @@ class Help extends BaseCommand { if (opts.conf.argv.remain.length > 2) return [] const g = path.resolve(__dirname, '../man/man[0-9]/*.[0-9]') - const files = await new Promise((resolve, reject) => { - glob(g, function (er, files) { - if (er) - return reject(er) - resolve(files) - }) - }) + const files = await glob(g) return Object.keys(files.reduce(function (acc, file) { file = path.basename(file).replace(/\.[0-9]+$/, '') @@ -43,81 +46,45 @@ class Help extends BaseCommand { } async help (args) { - const argv = this.npm.config.parsedArgv.cooked + // By default we search all of our man subdirectories, but if the user has + // asked for a specific one we limit the search to just there + let manSearch = 'man*' + if (/^\d+$/.test(args[0])) + manSearch = `man${args.shift()}` - let argnum = 0 - if (args.length === 2 && ~~args[0]) - argnum = ~~args.shift() + if (!args.length) + return this.npm.output(this.npm.usage) // npm help foo bar baz: search topics - if (args.length > 1 && args[0]) + if (args.length > 1) return this.helpSearch(args) - const affordances = { - 'find-dupes': 'dedupe', - } - let section = affordances[args[0]] || this.npm.deref(args[0]) || args[0] - - // npm help <noargs>: show basic usage - if (!section) { - npmUsage(this.npm, argv[0] === 'help') - return - } - - // npm <command> -h: show command usage - if (this.npm.config.get('usage') && - this.npm.commands[section] && - this.npm.commands[section].usage) { - this.npm.config.set('loglevel', 'silent') - log.level = 'silent' - this.npm.output(this.npm.commands[section].usage) - return - } + let section = this.npm.deref(args[0]) || args[0] - let pref = [1, 5, 7] - if (argnum) - pref = [argnum].concat(pref.filter(n => n !== argnum)) + // support `npm help package.json` + section = section.replace('.json', '-json') - // npm help <section>: Try to find the path const manroot = path.resolve(__dirname, '..', 'man') + // find either section.n or npm-section.n + const f = `${manroot}/${manSearch}/?(npm-)${section}.[0-9]*` + let mans = await glob(f) + mans = mans.sort((a, b) => { + // Because of the glob we know the manNumberRegex will pass + const aManNumber = a.match(manNumberRegex)[1] + const bManNumber = b.match(manNumberRegex)[1] - // legacy - if (section === 'global') - section = 'folders' - else if (section.match(/.*json/)) - section = section.replace('.json', '-json') - - // find either /section.n or /npm-section.n - // The glob is used in the glob. The regexp is used much - // further down. Globs and regexps are different - const compextglob = '.+(gz|bz2|lzma|[FYzZ]|xz)' - const compextre = '\\.(gz|bz2|lzma|[FYzZ]|xz)$' - const f = '+(npm-' + section + '|' + section + ').[0-9]?(' + compextglob + ')' - return new Promise((resolve, reject) => { - glob(manroot + '/*/' + f, async (er, mans) => { - if (er) - return reject(er) - - if (!mans.length) { - this.helpSearch(args).then(resolve).catch(reject) - return - } - - mans = mans.map((man) => { - const ext = path.extname(man) - if (man.match(new RegExp(compextre))) - man = path.basename(man, ext) - - return man - }) - - this.viewMan(this.pickMan(mans, pref), (err) => { - if (err) - return reject(err) - return resolve() - }) - }) + // man number sort first so that 1 aka commands are preferred + if (aManNumber !== bManNumber) + return aManNumber - bManNumber + + return a.localeCompare(b) }) + const man = mans[0] + + if (man) + await this.viewMan(man) + else + return this.helpSearch(args) } helpSearch (args) { @@ -133,32 +100,11 @@ class Help extends BaseCommand { }) } - pickMan (mans, pref_) { - const nre = /([0-9]+)$/ - const pref = {} - pref_.forEach((sect, i) => pref[sect] = i) - mans = mans.sort((a, b) => { - const an = a.match(nre)[1] - const bn = b.match(nre)[1] - return an === bn ? (a > b ? -1 : 1) - : pref[an] < pref[bn] ? -1 - : 1 - }) - return mans[0] - } - - viewMan (man, cb) { - const nre = /([0-9]+)$/ - const num = man.match(nre)[1] - const section = path.basename(man, '.' + num) - - // at this point, we know that the specified man page exists - const manpath = path.join(__dirname, '..', 'man') + async viewMan (man) { const env = {} Object.keys(process.env).forEach(function (i) { env[i] = process.env[i] }) - env.MANPATH = manpath const viewer = this.npm.config.get('viewer') const opts = { @@ -175,48 +121,39 @@ class Help extends BaseCommand { break case 'browser': - bin = false - try { - const url = this.htmlMan(man) - openUrl(this.npm, url, 'help available at the following URL').then( - () => cb() - ).catch(cb) - } catch (err) { - cb(err) - } - break + await openUrl(this.npm, this.htmlMan(man), 'help available at the following URL') + return default: - args.push(num, section) + args.push(man) break } - if (bin) { - const proc = spawn(bin, args, opts) + const proc = spawn(bin, args, opts) + return new Promise((resolve, reject) => { proc.on('exit', (code) => { if (code) - return cb(new Error(`help process exited with code: ${code}`)) + return reject(new Error(`help process exited with code: ${code}`)) - return cb() + return resolve() }) - } + }) } + // Returns the path to the html version of the man page htmlMan (man) { - let sect = +man.match(/([0-9]+)$/)[1] - const f = path.basename(man).replace(/[.]([0-9]+)$/, '') + let sect = man.match(manNumberRegex)[1] + const f = path.basename(man).replace(manNumberRegex, '') switch (sect) { - case 1: + case '1': sect = 'commands' break - case 5: + case '5': sect = 'configuring-npm' break - case 7: + case '7': sect = 'using-npm' break - default: - throw new Error('invalid man section: ' + sect) } return 'file://' + path.resolve(__dirname, '..', 'docs', 'output', sect, f + '.html') } diff --git a/deps/npm/lib/hook.js b/deps/npm/lib/hook.js index 6cda3504f4..64b1201cbd 100644 --- a/deps/npm/lib/hook.js +++ b/deps/npm/lib/hook.js @@ -5,6 +5,10 @@ const Table = require('cli-table3') const BaseCommand = require('./base-command.js') class Hook extends BaseCommand { + static get description () { + return 'Manage registry hooks' + } + static get name () { return 'hook' } diff --git a/deps/npm/lib/init.js b/deps/npm/lib/init.js index 42b02dfdc6..81c6733885 100644 --- a/deps/npm/lib/init.js +++ b/deps/npm/lib/init.js @@ -5,6 +5,11 @@ const BaseCommand = require('./base-command.js') class Init extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Create a package.json file' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'init' } @@ -59,7 +64,7 @@ class Init extends BaseCommand { this.npm.log.pause() this.npm.log.disableProgress() const initFile = this.npm.config.get('init-module') - if (!this.npm.flatOptions.yes && !this.npm.flatOptions.force) { + if (!this.npm.config.get('yes') && !this.npm.config.get('force')) { this.npm.output([ 'This utility will walk you through creating a package.json file.', 'It only covers the most common items, and tries to guess sensible defaults.', diff --git a/deps/npm/lib/install-ci-test.js b/deps/npm/lib/install-ci-test.js index c52b5c9e80..871f24b2f3 100644 --- a/deps/npm/lib/install-ci-test.js +++ b/deps/npm/lib/install-ci-test.js @@ -4,6 +4,10 @@ const CI = require('./ci.js') class InstallCITest extends CI { + static get description () { + return 'Install a project with a clean slate and run tests' + } + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'install-ci-test' diff --git a/deps/npm/lib/install-test.js b/deps/npm/lib/install-test.js index 76c6f367dd..d5664119df 100644 --- a/deps/npm/lib/install-test.js +++ b/deps/npm/lib/install-test.js @@ -4,6 +4,10 @@ const Install = require('./install.js') class InstallTest extends Install { + static get description () { + return 'Install package(s) and run tests' + } + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'install-test' diff --git a/deps/npm/lib/install.js b/deps/npm/lib/install.js index 8df63a219e..54ea6d8251 100644 --- a/deps/npm/lib/install.js +++ b/deps/npm/lib/install.js @@ -12,11 +12,24 @@ const runScript = require('@npmcli/run-script') const BaseCommand = require('./base-command.js') class Install extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Install a package' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'install' } /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get params () { + return [ + 'save', + 'save-exact', + ] + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get usage () { return [ '[<@scope>/]<pkg>', @@ -28,7 +41,7 @@ class Install extends BaseCommand { '<tarball file>', '<tarball url>', '<git:// url>', - '<github username>/<github project> [--save-prod|--save-dev|--save-optional|--save-peer] [--save-exact] [--no-save]', + '<github username>/<github project>', ] } @@ -98,7 +111,8 @@ class Install extends BaseCommand { async install (args) { // the /path/to/node_modules/.. const globalTop = resolve(this.npm.globalDir, '..') - const { ignoreScripts, global: isGlobalInstall } = this.npm.flatOptions + const ignoreScripts = this.npm.config.get('ignore-scripts') + const isGlobalInstall = this.npm.config.get('global') const where = isGlobalInstall ? globalTop : this.npm.prefix // don't try to install the prefix into itself @@ -122,7 +136,7 @@ class Install extends BaseCommand { add: args, }) if (!args.length && !isGlobalInstall && !ignoreScripts) { - const { scriptShell } = this.npm.flatOptions + const scriptShell = this.npm.config.get('script-shell') || undefined const scripts = [ 'preinstall', 'install', diff --git a/deps/npm/lib/link.js b/deps/npm/lib/link.js index 66f83d9f5b..fe9cfd3a6b 100644 --- a/deps/npm/lib/link.js +++ b/deps/npm/lib/link.js @@ -13,6 +13,11 @@ const reifyFinish = require('./utils/reify-finish.js') const BaseCommand = require('./base-command.js') class Link extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Symlink a package folder' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'link' } @@ -96,7 +101,13 @@ class Link extends BaseCommand { // npm link should not save=true by default unless you're // using any of --save-dev or other types const save = - Boolean(this.npm.config.find('save') !== 'default' || this.npm.flatOptions.saveType) + Boolean( + this.npm.config.find('save') !== 'default' || + this.npm.config.get('save-optional') || + this.npm.config.get('save-peer') || + this.npm.config.get('save-dev') || + this.npm.config.get('save-prod') + ) // create a new arborist instance for the local prefix and // reify all the pending names as symlinks there diff --git a/deps/npm/lib/logout.js b/deps/npm/lib/logout.js index b3f64f671d..adc19a923a 100644 --- a/deps/npm/lib/logout.js +++ b/deps/npm/lib/logout.js @@ -5,13 +5,21 @@ const BaseCommand = require('./base-command.js') class Logout extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Log out of the registry' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'logout' } /* istanbul ignore next - see test/lib/load-all-commands.js */ - static get usage () { - return ['[--registry=<url>] [--scope=<@scope>]'] + static get params () { + return [ + 'registry', + 'scope', + ] } exec (args, cb) { @@ -19,9 +27,10 @@ class Logout extends BaseCommand { } async logout (args) { - const { registry, scope } = this.npm.flatOptions + const registry = this.npm.config.get('registry') + const scope = this.npm.config.get('scope') const regRef = scope ? `${scope}:registry` : 'registry' - const reg = this.npm.flatOptions[regRef] || registry + const reg = this.npm.config.get(regRef) || registry const auth = getAuth(reg, this.npm.flatOptions) diff --git a/deps/npm/lib/ls.js b/deps/npm/lib/ls.js index 9ff2761c2f..65b3ddfe76 100644 --- a/deps/npm/lib/ls.js +++ b/deps/npm/lib/ls.js @@ -24,6 +24,11 @@ const BaseCommand = require('./base-command.js') class LS extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'List installed packages' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'ls' } @@ -43,24 +48,22 @@ class LS extends BaseCommand { } async ls (args) { - const { - all, - color, - depth, - json, - long, - global, - parseable, - prefix, - unicode, - } = this.npm.flatOptions - const path = global ? resolve(this.npm.globalDir, '..') : prefix + const all = this.npm.config.get('all') + const color = !!this.npm.color + const depth = this.npm.config.get('depth') const dev = this.npm.config.get('dev') const development = this.npm.config.get('development') + const global = this.npm.config.get('global') + const json = this.npm.config.get('json') const link = this.npm.config.get('link') + const long = this.npm.config.get('long') const only = this.npm.config.get('only') + const parseable = this.npm.config.get('parseable') const prod = this.npm.config.get('prod') const production = this.npm.config.get('production') + const unicode = this.npm.config.get('unicode') + + const path = global ? resolve(this.npm.globalDir, '..') : this.npm.prefix const arb = new Arborist({ global, diff --git a/deps/npm/lib/npm.js b/deps/npm/lib/npm.js index 0534e63060..42541a90ff 100644 --- a/deps/npm/lib/npm.js +++ b/deps/npm/lib/npm.js @@ -36,24 +36,19 @@ const proxyCmds = new Proxy({}, { }, }) -const { types, defaults, shorthands } = require('./utils/config.js') +const { definitions, flatten, shorthands } = require('./utils/config/index.js') const { shellouts } = require('./utils/cmd-list.js') +const usage = require('./utils/npm-usage.js') let warnedNonDashArg = false 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() require('./utils/perf.js') - this.modes = { - exec: 0o755, - file: 0o644, - umask: 0o22, - } this.started = Date.now() this.command = null this.commands = proxyCmds @@ -62,8 +57,8 @@ const npm = module.exports = new class extends EventEmitter { this.version = require('../package.json').version this.config = new Config({ npmPath: dirname(__dirname), - types, - defaults, + definitions, + flatten, shorthands, }) this[_title] = process.title @@ -105,9 +100,18 @@ const npm = module.exports = new class extends EventEmitter { }) } + const workspacesEnabled = this.config.get('workspaces') + const workspacesFilters = this.config.get('workspace') + const filterByWorkspaces = workspacesEnabled || workspacesFilters.length > 0 + if (this.config.get('usage')) { - console.log(impl.usage) + this.output(impl.usage) cb() + } else if (filterByWorkspaces) { + impl.execWorkspaces(args, this.config.get('workspace'), er => { + process.emit('timeEnd', `command:${cmd}`) + cb(er) + }) } else { impl.exec(args, er => { process.emit('timeEnd', `command:${cmd}`) @@ -140,9 +144,6 @@ const npm = module.exports = new class extends EventEmitter { if (!er && this.config.get('force')) this.log.warn('using --force', 'Recommended protections disabled.') - if (!er && !this[_flatOptions]) - this[_flatOptions] = require('./utils/flat-options.js')(this) - process.emit('timeEnd', 'npm:load') this.emit('load', er) }) @@ -162,14 +163,19 @@ const npm = module.exports = new class extends EventEmitter { } async [_load] () { + process.emit('time', 'npm:load:whichnode') const node = await which(process.argv[0]).catch(er => null) + process.emit('timeEnd', 'npm:load:whichnode') if (node && node.toUpperCase() !== process.execPath.toUpperCase()) { log.verbose('node symlink', node) process.execPath = node this.config.execPath = node } + process.emit('time', 'npm:load:configload') await this.config.load() + process.emit('timeEnd', 'npm:load:configload') + 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. @@ -177,33 +183,40 @@ const npm = module.exports = new class extends EventEmitter { // 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. + process.emit('time', 'npm:load:setTitle') const tokrev = deref(this.argv[0]) === 'token' && this.argv[1] === 'revoke' this.title = tokrev ? 'npm token revoke' + (this.argv[2] ? ' ***' : '') : ['npm', ...this.argv].join(' ') + process.emit('timeEnd', 'npm:load:setTitle') + process.emit('time', 'npm:load:setupLog') this.color = setupLog(this.config) + process.emit('timeEnd', 'npm:load:setupLog') process.env.COLOR = this.color ? '1' : '0' + process.emit('time', 'npm:load:cleanupLog') cleanUpLogFiles(this.cache, this.config.get('logs-max'), log.warn) + process.emit('timeEnd', 'npm:load:cleanupLog') log.resume() - const umask = this.config.get('umask') - this.modes = { - exec: 0o777 & (~umask), - file: 0o666 & (~umask), - umask, - } + process.emit('time', 'npm:load:configScope') const configScope = this.config.get('scope') if (configScope && !/^@/.test(configScope)) this.config.set('scope', `@${configScope}`, this.config.find('scope')) + process.emit('timeEnd', 'npm:load:configScope') + process.emit('time', 'npm:load:projectScope') this.projectScope = this.config.get('scope') || getProjectScope(this.prefix) + process.emit('timeEnd', 'npm:load:projectScope') } get flatOptions () { - return this[_flatOptions] + const { flat } = this.config + if (this.command) + flat.npmCommand = this.command + return flat } get lockfileVersion () { @@ -274,6 +287,10 @@ const npm = module.exports = new class extends EventEmitter { this[k] = r } + get usage () { + return usage(this) + } + // XXX add logging to see if we actually use this get tmp () { if (!this[_tmpFolder]) { diff --git a/deps/npm/lib/org.js b/deps/npm/lib/org.js index b9f84b060f..ddd2b03dae 100644 --- a/deps/npm/lib/org.js +++ b/deps/npm/lib/org.js @@ -4,6 +4,10 @@ const Table = require('cli-table3') const BaseCommand = require('./base-command.js') class Org extends BaseCommand { + static get description () { + return 'Manage orgs' + } + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'org' diff --git a/deps/npm/lib/outdated.js b/deps/npm/lib/outdated.js index 7225577ea4..9b656d2aee 100644 --- a/deps/npm/lib/outdated.js +++ b/deps/npm/lib/outdated.js @@ -14,6 +14,11 @@ const BaseCommand = require('./base-command.js') class Outdated extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Check for outdated packages' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'outdated' } @@ -28,15 +33,13 @@ class Outdated extends BaseCommand { } async outdated (args) { - this.opts = this.npm.flatOptions - const global = path.resolve(this.npm.globalDir, '..') - const where = this.opts.global + const where = this.npm.config.get('global') ? global : this.npm.prefix const arb = new Arborist({ - ...this.opts, + ...this.npm.flatOptions, path: where, }) @@ -51,7 +54,7 @@ class Outdated extends BaseCommand { this.getEdges(nodes, 'edgesIn') } } else { - if (this.opts.all) { + if (this.npm.config.get('all')) { // all deps in tree const nodes = this.tree.inventory.values() this.getEdges(nodes, 'edgesOut') @@ -68,13 +71,13 @@ class Outdated extends BaseCommand { const outdated = this.list.sort((a, b) => a.name.localeCompare(b.name)) // return if no outdated packages - if (outdated.length === 0 && !this.opts.json) + if (outdated.length === 0 && !this.npm.config.get('json')) return // display results - if (this.opts.json) + if (this.npm.config.get('json')) this.npm.output(this.makeJSON(outdated)) - else if (this.opts.parseable) + else if (this.npm.config.get('parseable')) this.npm.output(this.makeParseable(outdated)) else { const outList = outdated.map(x => this.makePretty(x)) @@ -86,11 +89,11 @@ class Outdated extends BaseCommand { 'Depended by', ] - if (this.opts.long) + if (this.npm.config.get('long')) outHead.push('Package Type', 'Homepage') const outTable = [outHead].concat(outList) - if (this.opts.color) + if (this.npm.color) outTable[0] = outTable[0].map(heading => styles.underline(heading)) const tableOpts = { @@ -117,7 +120,7 @@ class Outdated extends BaseCommand { } getEdgesOut (node) { - if (this.opts.global) { + if (this.npm.config.get('global')) { for (const child of node.children.values()) this.edges.add(child) } else { @@ -129,7 +132,7 @@ class Outdated extends BaseCommand { async getPackument (spec) { const packument = await pacote.packument(spec, { ...this.npm.flatOptions, - fullMetadata: this.npm.flatOptions.long, + fullMetadata: this.npm.config.get('long'), preferOnline: true, }) return packument @@ -146,7 +149,7 @@ class Outdated extends BaseCommand { : edge.dev ? 'devDependencies' : 'dependencies' - for (const omitType of this.opts.omit || []) { + for (const omitType of this.npm.config.get('omit') || []) { if (node[omitType]) return } @@ -213,12 +216,12 @@ class Outdated extends BaseCommand { const columns = [name, current, wanted, latest, location, dependent] - if (this.opts.long) { + if (this.npm.config.get('long')) { columns[6] = type columns[7] = homepage } - if (this.opts.color) { + if (this.npm.color) { columns[0] = color[current === wanted ? 'yellow' : 'red'](columns[0]) // current columns[2] = color.green(columns[2]) // wanted columns[3] = color.magenta(columns[3]) // latest @@ -248,7 +251,7 @@ class Outdated extends BaseCommand { name + '@' + latest, dependent, ] - if (this.opts.long) + if (this.npm.config.get('long')) out.push(type, homepage) return out.join(':') @@ -275,7 +278,7 @@ class Outdated extends BaseCommand { dependent, location: path, } - if (this.opts.long) { + if (this.npm.config.get('long')) { out[name].type = type out[name].homepage = homepage } diff --git a/deps/npm/lib/owner.js b/deps/npm/lib/owner.js index b62f125ac3..e537d82d01 100644 --- a/deps/npm/lib/owner.js +++ b/deps/npm/lib/owner.js @@ -8,6 +8,10 @@ const readLocalPkg = require('./utils/read-local-package.js') const BaseCommand = require('./base-command.js') class Owner extends BaseCommand { + static get description () { + return 'Manage package owners' + } + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'owner' diff --git a/deps/npm/lib/pack.js b/deps/npm/lib/pack.js index 326fcc0cd1..92a2fbd7ac 100644 --- a/deps/npm/lib/pack.js +++ b/deps/npm/lib/pack.js @@ -12,13 +12,23 @@ const BaseCommand = require('./base-command.js') class Pack extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Create a tarball from a package' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'pack' } /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get params () { + return ['dry-run'] + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get usage () { - return ['[[<@scope>/]<pkg>...] [--dry-run]'] + return ['[[<@scope>/]<pkg>...]'] } exec (args, cb) { @@ -29,12 +39,12 @@ class Pack extends BaseCommand { if (args.length === 0) args = ['.'] - const { unicode } = this.npm.flatOptions + const unicode = this.npm.config.get('unicode') // clone the opts because pacote mutates it with resolved/integrity const tarballs = await Promise.all(args.map(async (arg) => { const spec = npa(arg) - const { dryRun } = this.npm.flatOptions + const dryRun = this.npm.config.get('dry-run') const manifest = await pacote.manifest(spec, this.npm.flatOptions) const filename = `${manifest.name}-${manifest.version}.tgz` .replace(/^@/, '').replace(/\//, '-') diff --git a/deps/npm/lib/ping.js b/deps/npm/lib/ping.js index e60b1f1deb..3037937748 100644 --- a/deps/npm/lib/ping.js +++ b/deps/npm/lib/ping.js @@ -4,13 +4,18 @@ const BaseCommand = require('./base-command.js') class Ping extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ - static get name () { - return 'ping' + static get description () { + return 'Ping npm registry' } /* istanbul ignore next - see test/lib/load-all-commands.js */ - static get description () { - return 'ping registry' + static get params () { + return ['registry'] + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get name () { + return 'ping' } exec (args, cb) { @@ -18,14 +23,14 @@ class Ping extends BaseCommand { } async ping (args) { - log.notice('PING', this.npm.flatOptions.registry) + log.notice('PING', this.npm.config.get('registry')) const start = Date.now() const details = await pingUtil(this.npm.flatOptions) const time = Date.now() - start log.notice('PONG', `${time / 1000}ms`) - if (this.npm.flatOptions.json) { + if (this.npm.config.get('json')) { this.npm.output(JSON.stringify({ - registry: this.npm.flatOptions.registry, + registry: this.npm.config.get('registry'), time, details, }, null, 2)) diff --git a/deps/npm/lib/prefix.js b/deps/npm/lib/prefix.js index 5ade87f642..1298a3c5ba 100644 --- a/deps/npm/lib/prefix.js +++ b/deps/npm/lib/prefix.js @@ -2,6 +2,11 @@ const BaseCommand = require('./base-command.js') class Prefix extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Display prefix' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'prefix' } diff --git a/deps/npm/lib/profile.js b/deps/npm/lib/profile.js index 1c0df49888..9789146fde 100644 --- a/deps/npm/lib/profile.js +++ b/deps/npm/lib/profile.js @@ -38,6 +38,10 @@ const writableProfileKeys = [ const BaseCommand = require('./base-command.js') class Profile extends BaseCommand { + static get description () { + return 'Change settings on your registry profile' + } + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'profile' @@ -108,14 +112,14 @@ class Profile extends BaseCommand { async get (args) { const tfa = 'two-factor auth' - const conf = { ...this.npm.flatOptions } - - const info = await pulseTillDone.withPromise(npmProfile.get(conf)) + const info = await pulseTillDone.withPromise( + npmProfile.get(this.npm.flatOptions) + ) if (!info.cidr_whitelist) delete info.cidr_whitelist - if (conf.json) { + if (this.npm.config.get('json')) { this.npm.output(JSON.stringify(info, null, 2)) return } @@ -147,7 +151,7 @@ class Profile extends BaseCommand { .join('\t') this.npm.output(values) } else { - if (conf.parseable) { + if (this.npm.config.get('parseable')) { for (const key of Object.keys(info)) { if (key === 'tfa') this.npm.output(`${key}\t${cleaned[tfa]}`) @@ -165,7 +169,7 @@ class Profile extends BaseCommand { } async set (args) { - const conf = { ...this.npm.flatOptions } + const conf = this.npm.flatOptions const prop = (args[0] || '').toLowerCase().trim() let value = args.length > 1 ? args.slice(1).join(' ') : null @@ -214,9 +218,9 @@ class Profile extends BaseCommand { const result = await otplease(conf, conf => npmProfile.set(newUser, conf)) - if (conf.json) + if (this.npm.config.get('json')) this.npm.output(JSON.stringify({ [prop]: result[prop] }, null, 2)) - else if (conf.parseable) + else if (this.npm.config.get('parseable')) this.npm.output(prop + '\t' + result[prop]) else if (result[prop] != null) this.npm.output('Set', prop, 'to', result[prop]) @@ -239,11 +243,10 @@ class Profile extends BaseCommand { ) } - const conf = { ...this.npm.flatOptions } - if (conf.json || conf.parseable) { + if (this.npm.config.get('json') || this.npm.config.get('parseable')) { throw new Error( 'Enabling two-factor authentication is an interactive operation and ' + - (conf.json ? 'JSON' : 'parseable') + ' output mode is not available' + (this.npm.config.get('json') ? 'JSON' : 'parseable') + ' output mode is not available' ) } @@ -255,7 +258,7 @@ class Profile extends BaseCommand { // if they're using legacy auth currently then we have to // update them to a bearer token before continuing. - const creds = this.npm.config.getCredentialsByURI(conf.registry) + const creds = this.npm.config.getCredentialsByURI(this.npm.config.get('registry')) const auth = {} if (creds.token) @@ -267,32 +270,29 @@ class Profile extends BaseCommand { auth.basic = { username: basic[0], password: basic[1] } } - if (conf.otp) - auth.otp = conf.otp - if (!auth.basic && !auth.token) { throw new Error( 'You need to be logged in to registry ' + - `${conf.registry} in order to enable 2fa` + `${this.npm.config.get('registry')} in order to enable 2fa` ) } if (auth.basic) { log.info('profile', 'Updating authentication to bearer token') const result = await npmProfile.createToken( - auth.basic.password, false, [], conf + auth.basic.password, false, [], this.npm.flatOptions ) if (!result.token) { throw new Error( - `Your registry ${conf.registry} does not seem to ` + + `Your registry ${this.npm.config.get('registry')} does not seem to ` + 'support bearer tokens. Bearer tokens are required for ' + 'two-factor authentication' ) } this.npm.config.setCredentialsByURI( - conf.registry, + this.npm.config.get('registry'), { token: result.token } ) await this.npm.config.save('user') @@ -303,21 +303,21 @@ class Profile extends BaseCommand { info.tfa.password = password log.info('profile', 'Determine if tfa is pending') - const userInfo = await pulseTillDone.withPromise(npmProfile.get(conf)) + const userInfo = await pulseTillDone.withPromise( + npmProfile.get(this.npm.flatOptions) + ) + const conf = { ...this.npm.flatOptions } if (userInfo && userInfo.tfa && userInfo.tfa.pending) { log.info('profile', 'Resetting two-factor authentication') await pulseTillDone.withPromise( npmProfile.set({ tfa: { password, mode: 'disable' } }, conf) ) } else if (userInfo && userInfo.tfa) { - if (conf.otp) - conf.otp = conf.otp - else { - const otp = await readUserInfo.otp( + if (!conf.otp) { + conf.otp = await readUserInfo.otp( 'Enter one-time password from your authenticator app: ' ) - conf.otp = otp } } @@ -390,9 +390,9 @@ class Profile extends BaseCommand { tfa: { password: password, mode: 'disable' }, }, conf)) - if (conf.json) + if (this.npm.config.get('json')) this.npm.output(JSON.stringify({ tfa: false }, null, 2)) - else if (conf.parseable) + else if (this.npm.config.get('parseable')) this.npm.output('tfa\tfalse') else this.npm.output('Two factor authentication disabled.') diff --git a/deps/npm/lib/prune.js b/deps/npm/lib/prune.js index c2cddb1a22..1da86a3e82 100644 --- a/deps/npm/lib/prune.js +++ b/deps/npm/lib/prune.js @@ -5,13 +5,23 @@ const reifyFinish = require('./utils/reify-finish.js') const BaseCommand = require('./base-command.js') class Prune extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Remove extraneous packages' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'prune' } /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get params () { + return ['production'] + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get usage () { - return ['[[<@scope>/]<pkg>...] [--production]'] + return ['[[<@scope>/]<pkg>...]'] } exec (args, cb) { diff --git a/deps/npm/lib/publish.js b/deps/npm/lib/publish.js index f8e0eafe11..b121cb3d36 100644 --- a/deps/npm/lib/publish.js +++ b/deps/npm/lib/publish.js @@ -8,7 +8,7 @@ const pacote = require('pacote') const npa = require('npm-package-arg') const npmFetch = require('npm-registry-fetch') -const { flatten } = require('./utils/flat-options.js') +const flatten = require('./utils/config/flatten.js') const otplease = require('./utils/otplease.js') const { getContents, logTar } = require('./utils/tar.js') @@ -19,15 +19,24 @@ const readJson = util.promisify(require('read-package-json')) const BaseCommand = require('./base-command.js') class Publish extends BaseCommand { + static get description () { + return 'Publish a package' + } + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'publish' } /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get params () { + return ['tag', 'access', 'dry-run'] + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get usage () { return [ - '[<folder>] [--tag <tag>] [--access <public|restricted>] [--dry-run]', + '[<folder>]', ] } @@ -43,12 +52,16 @@ class Publish extends BaseCommand { log.verbose('publish', args) - const opts = { ...this.npm.flatOptions } - const { unicode, dryRun, json, defaultTag } = opts + const unicode = this.npm.config.get('unicode') + const dryRun = this.npm.config.get('dry-run') + const json = this.npm.config.get('json') + const defaultTag = this.npm.config.get('tag') if (semver.validRange(defaultTag)) throw new Error('Tag name must not be a valid SemVer range: ' + defaultTag.trim()) + const opts = { ...this.npm.flatOptions } + // you can publish name@version, ./foo.tgz, etc. // even though the default is the 'file:.' cwd. const spec = npa(args[0]) @@ -137,7 +150,8 @@ class Publish extends BaseCommand { publishConfigToOpts (publishConfig) { // create a new object that inherits from the config stack // then squash the css-case into camelCase opts, like we do - return flatten({...this.npm.config.list[0], ...publishConfig}) + // this is Object.assign()'ed onto the base npm.flatOptions + return flatten(publishConfig, {}) } } module.exports = Publish diff --git a/deps/npm/lib/rebuild.js b/deps/npm/lib/rebuild.js index 74f5ae5f6e..5910ab3d17 100644 --- a/deps/npm/lib/rebuild.js +++ b/deps/npm/lib/rebuild.js @@ -7,6 +7,11 @@ const completion = require('./utils/completion/installed-deep.js') const BaseCommand = require('./base-command.js') class Rebuild extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Rebuild a package' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'rebuild' } @@ -27,7 +32,7 @@ class Rebuild extends BaseCommand { async rebuild (args) { const globalTop = resolve(this.npm.globalDir, '..') - const where = this.npm.flatOptions.global ? globalTop : this.npm.prefix + const where = this.npm.config.get('global') ? globalTop : this.npm.prefix const arb = new Arborist({ ...this.npm.flatOptions, path: where, diff --git a/deps/npm/lib/repo.js b/deps/npm/lib/repo.js index aa07e07a81..5ab136abd7 100644 --- a/deps/npm/lib/repo.js +++ b/deps/npm/lib/repo.js @@ -8,6 +8,11 @@ const openUrl = require('./utils/open-url.js') const BaseCommand = require('./base-command.js') class Repo extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Open package repository page in the browser' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'repo' } diff --git a/deps/npm/lib/restart.js b/deps/npm/lib/restart.js index 1f3eb5af94..840eb20673 100644 --- a/deps/npm/lib/restart.js +++ b/deps/npm/lib/restart.js @@ -3,6 +3,11 @@ const LifecycleCmd = require('./utils/lifecycle-cmd.js') // This ends up calling run-script(['restart', ...args]) class Restart extends LifecycleCmd { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Restart a package' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'restart' } diff --git a/deps/npm/lib/root.js b/deps/npm/lib/root.js index 1fe82c6fad..635a68e256 100644 --- a/deps/npm/lib/root.js +++ b/deps/npm/lib/root.js @@ -1,13 +1,18 @@ const BaseCommand = require('./base-command.js') class Root extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Display npm root' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'root' } /* istanbul ignore next - see test/lib/load-all-commands.js */ - static get usage () { - return ['[-g]'] + static get params () { + return ['global'] } exec (args, cb) { diff --git a/deps/npm/lib/run-script.js b/deps/npm/lib/run-script.js index 3ea85b79ff..054f0ae4a5 100644 --- a/deps/npm/lib/run-script.js +++ b/deps/npm/lib/run-script.js @@ -1,10 +1,12 @@ +const { resolve } = require('path') +const chalk = require('chalk') const runScript = require('@npmcli/run-script') const { isServerPackage } = runScript -const readJson = require('read-package-json-fast') -const { resolve } = require('path') +const rpj = require('read-package-json-fast') const log = require('npmlog') const didYouMean = require('./utils/did-you-mean.js') const isWindowsShell = require('./utils/is-windows-shell.js') +const getWorkspaces = require('./workspaces/get-workspaces.js') const cmdList = [ 'publish', @@ -17,9 +19,22 @@ const cmdList = [ 'version', ].reduce((l, p) => l.concat(['pre' + p, p, 'post' + p]), []) +const nocolor = { + reset: s => s, + bold: s => s, + dim: s => s, + blue: s => s, + green: s => s, +} + const BaseCommand = require('./base-command.js') class RunScript extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Run arbitrary package scripts' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'run-script' } @@ -34,7 +49,7 @@ class RunScript extends BaseCommand { if (argv.length === 2) { // find the script name const json = resolve(this.npm.localPrefix, 'package.json') - const { scripts = {} } = await readJson(json).catch(er => ({})) + const { scripts = {} } = await rpj(json).catch(er => ({})) return Object.keys(scripts) } } @@ -46,12 +61,19 @@ class RunScript extends BaseCommand { this.list(args).then(() => cb()).catch(cb) } - async run (args) { - const path = this.npm.localPrefix - const event = args.shift() - const { scriptShell } = this.npm.flatOptions + execWorkspaces (args, filters, cb) { + if (args.length) + this.runWorkspaces(args, filters).then(() => cb()).catch(cb) + else + this.listWorkspaces(args, filters).then(() => cb()).catch(cb) + } + + async run ([event, ...args], { path = this.npm.localPrefix, pkg } = {}) { + // this || undefined is because runScript will be unhappy with the default + // null value + const scriptShell = this.npm.config.get('script-shell') || undefined - const pkg = await readJson(`${path}/package.json`) + pkg = pkg || (await rpj(`${path}/package.json`)) const { scripts = {} } = pkg if (event === 'restart' && !scripts.restart) @@ -68,14 +90,13 @@ class RunScript extends BaseCommand { if (this.npm.config.get('if-present')) return - const suggestions = didYouMean(event, Object.keys(scripts)) - throw new Error(`missing script: ${event}${ - suggestions ? `\n${suggestions}` : ''}`) + const suggestions = await didYouMean(this.npm, path, event) + throw new Error(`Missing script: "${event}"${suggestions}\n\nTo see a list of scripts, run:\n npm run`) } // positional args only added to the main event, not pre/post const events = [[event, args]] - if (!this.npm.flatOptions.ignoreScripts) { + if (!this.npm.config.get('ignore-scripts')) { if (scripts[`pre${event}`]) events.unshift([`pre${event}`, []]) @@ -102,9 +123,11 @@ class RunScript extends BaseCommand { } } - async list () { - const path = this.npm.localPrefix - const { scripts, name } = await readJson(`${path}/package.json`) + async list (args, path) { + path = path || this.npm.localPrefix + const { scripts, name, _id } = await rpj(`${path}/package.json`) + const pkgid = _id || name + const color = !!this.npm.color if (!scripts) return [] @@ -113,12 +136,12 @@ class RunScript extends BaseCommand { if (log.level === 'silent') return allScripts - if (this.npm.flatOptions.json) { + if (this.npm.config.get('json')) { this.npm.output(JSON.stringify(scripts, null, 2)) return allScripts } - if (this.npm.flatOptions.parseable) { + if (this.npm.config.get('parseable')) { for (const [script, cmd] of Object.entries(scripts)) this.npm.output(`${script}:${cmd}`) @@ -133,22 +156,96 @@ class RunScript extends BaseCommand { const list = cmdList.includes(script) ? cmds : runScripts list.push(script) } + const colorize = color ? chalk : nocolor - if (cmds.length) - this.npm.output(`Lifecycle scripts included in ${name}:`) + if (cmds.length) { + this.npm.output(`${ + colorize.reset(colorize.bold('Lifecycle scripts'))} included in ${ + colorize.green(pkgid)}:`) + } for (const script of cmds) - this.npm.output(prefix + script + indent + scripts[script]) + this.npm.output(prefix + script + indent + colorize.dim(scripts[script])) - if (!cmds.length && runScripts.length) - this.npm.output(`Scripts available in ${name} via \`npm run-script\`:`) - else if (runScripts.length) - this.npm.output('\navailable via `npm run-script`:') + if (!cmds.length && runScripts.length) { + this.npm.output(`${ + colorize.bold('Scripts') + } available in ${colorize.green(pkgid)} via \`${ + colorize.blue('npm run-script')}\`:`) + } else if (runScripts.length) + this.npm.output(`\navailable via \`${colorize.blue('npm run-script')}\`:`) for (const script of runScripts) - this.npm.output(prefix + script + indent + scripts[script]) + this.npm.output(prefix + script + indent + colorize.dim(scripts[script])) + this.npm.output('') return allScripts } + + async workspaces (filters) { + return getWorkspaces(filters, { path: this.npm.localPrefix }) + } + + async runWorkspaces (args, filters) { + const res = [] + const workspaces = await this.workspaces(filters) + + for (const workspacePath of workspaces.values()) { + const pkg = await rpj(`${workspacePath}/package.json`) + const runResult = await this.run(args, { + path: workspacePath, + pkg, + }).catch(err => { + log.error(`Lifecycle script \`${args[0]}\` failed with error:`) + log.error(err) + log.error(` in workspace: ${pkg._id || pkg.name}`) + log.error(` at location: ${workspacePath}`) + + const scriptMissing = err.message.startsWith('Missing script') + + // avoids exiting with error code in case there's scripts missing + // in some workspaces since other scripts might have succeeded + if (!scriptMissing) + process.exitCode = 1 + + return scriptMissing + }) + res.push(runResult) + } + + // in case **all** tests are missing, then it should exit with error code + if (res.every(Boolean)) + throw new Error(`Missing script: ${args[0]}`) + } + + async listWorkspaces (args, filters) { + const workspaces = await this.workspaces(filters) + + if (log.level === 'silent') + return + + if (this.npm.config.get('json')) { + const res = {} + for (const workspacePath of workspaces.values()) { + const { scripts, name } = await rpj(`${workspacePath}/package.json`) + res[name] = { ...scripts } + } + this.npm.output(JSON.stringify(res, null, 2)) + return + } + + if (this.npm.config.get('parseable')) { + for (const workspacePath of workspaces.values()) { + const { scripts, name } = await rpj(`${workspacePath}/package.json`) + for (const [script, cmd] of Object.entries(scripts || {})) + this.npm.output(`${name}:${script}:${cmd}`) + } + return + } + + for (const workspacePath of workspaces.values()) + await this.list(args, workspacePath) + } } + module.exports = RunScript diff --git a/deps/npm/lib/search.js b/deps/npm/lib/search.js index c24000156f..bdd374ab6e 100644 --- a/deps/npm/lib/search.js +++ b/deps/npm/lib/search.js @@ -27,13 +27,28 @@ function prepareExcludes (searchexclude) { const BaseCommand = require('./base-command.js') class Search extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Search for pacakges' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'search' } /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get params () { + return [ + 'long', + 'json', + 'parseable', + 'description', + ] + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get usage () { - return ['[-l|--long] [--json] [--parseable] [--no-description] [search terms ...]'] + return ['[search terms ...]'] } exec (args, cb) { @@ -84,7 +99,7 @@ class Search extends BaseCommand { }) await p.promise() - if (!anyOutput && !opts.json && !opts.parseable) + if (!anyOutput && !this.npm.config.get('json') && !this.npm.config.get('parseable')) this.npm.output('No matches found for ' + (args.map(JSON.stringify).join(' '))) log.silly('search', 'search completed') diff --git a/deps/npm/lib/set-script.js b/deps/npm/lib/set-script.js index 6241981323..df101a0acb 100644 --- a/deps/npm/lib/set-script.js +++ b/deps/npm/lib/set-script.js @@ -6,6 +6,11 @@ const rpj = require('read-package-json-fast') const BaseCommand = require('./base-command.js') class SetScript extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Set tasks in the scripts section of package.json' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'set-script' } diff --git a/deps/npm/lib/set.js b/deps/npm/lib/set.js index 787a8012c0..74a002cd63 100644 --- a/deps/npm/lib/set.js +++ b/deps/npm/lib/set.js @@ -1,6 +1,10 @@ const BaseCommand = require('./base-command.js') class Set extends BaseCommand { + static get description () { + return 'Set a value in the npm configuration' + } + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'set' diff --git a/deps/npm/lib/shrinkwrap.js b/deps/npm/lib/shrinkwrap.js index b52cf41957..5d4a1ada98 100644 --- a/deps/npm/lib/shrinkwrap.js +++ b/deps/npm/lib/shrinkwrap.js @@ -8,6 +8,11 @@ const log = require('npmlog') const BaseCommand = require('./base-command.js') class Shrinkwrap extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Lock down dependency versions for publication' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'shrinkwrap' } @@ -24,7 +29,7 @@ class Shrinkwrap extends BaseCommand { // // loadVirtual, fall back to loadActual // rename shrinkwrap file type, and tree.meta.save() - if (this.npm.flatOptions.global) { + if (this.npm.config.get('global')) { const er = new Error('`npm shrinkwrap` does not work for global packages') er.code = 'ESHRINKWRAPGLOBAL' throw er diff --git a/deps/npm/lib/star.js b/deps/npm/lib/star.js index 27a3041906..4c5cf4900c 100644 --- a/deps/npm/lib/star.js +++ b/deps/npm/lib/star.js @@ -6,6 +6,10 @@ const getIdentity = require('./utils/get-identity') const BaseCommand = require('./base-command.js') class Star extends BaseCommand { + static get description () { + return 'Mark your favorite packages' + } + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'star' @@ -26,7 +30,7 @@ class Star extends BaseCommand { // if we're unstarring, then show an empty star image // otherwise, show the full star image - const { unicode } = this.npm.flatOptions + const unicode = this.npm.config.get('unicode') const unstar = this.npm.config.get('star.unstar') const full = unicode ? '\u2605 ' : '(*)' const empty = unicode ? '\u2606 ' : '( )' diff --git a/deps/npm/lib/stars.js b/deps/npm/lib/stars.js index 758a3130d4..db93d7b196 100644 --- a/deps/npm/lib/stars.js +++ b/deps/npm/lib/stars.js @@ -6,6 +6,11 @@ const getIdentity = require('./utils/get-identity.js') const BaseCommand = require('./base-command.js') class Stars extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'View packages marked as favorites' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'stars' } diff --git a/deps/npm/lib/start.js b/deps/npm/lib/start.js index 8987bc2931..099b6e61b3 100644 --- a/deps/npm/lib/start.js +++ b/deps/npm/lib/start.js @@ -3,6 +3,11 @@ const LifecycleCmd = require('./utils/lifecycle-cmd.js') // This ends up calling run-script(['start', ...args]) class Start extends LifecycleCmd { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Start a package' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'start' } diff --git a/deps/npm/lib/stop.js b/deps/npm/lib/stop.js index a3857ab136..766d9c0181 100644 --- a/deps/npm/lib/stop.js +++ b/deps/npm/lib/stop.js @@ -3,6 +3,11 @@ const LifecycleCmd = require('./utils/lifecycle-cmd.js') // This ends up calling run-script(['stop', ...args]) class Stop extends LifecycleCmd { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Stop a package' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'stop' } diff --git a/deps/npm/lib/team.js b/deps/npm/lib/team.js index f84660af4d..5298bb3b25 100644 --- a/deps/npm/lib/team.js +++ b/deps/npm/lib/team.js @@ -5,6 +5,10 @@ const otplease = require('./utils/otplease.js') const BaseCommand = require('./base-command.js') class Team extends BaseCommand { + static get description () { + return 'Manage organization teams and team memberships' + } + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'team' diff --git a/deps/npm/lib/test.js b/deps/npm/lib/test.js index 991d1c873c..2be2b54af7 100644 --- a/deps/npm/lib/test.js +++ b/deps/npm/lib/test.js @@ -3,6 +3,11 @@ const LifecycleCmd = require('./utils/lifecycle-cmd.js') // This ends up calling run-script(['test', ...args]) class Test extends LifecycleCmd { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Test a package' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'test' } diff --git a/deps/npm/lib/token.js b/deps/npm/lib/token.js index 3d7952ccfc..a80988531e 100644 --- a/deps/npm/lib/token.js +++ b/deps/npm/lib/token.js @@ -10,6 +10,10 @@ const readUserInfo = require('./utils/read-user-info.js') const BaseCommand = require('./base-command.js') class Token extends BaseCommand { + static get description () { + return 'Manage your authentication tokens' + } + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'token' diff --git a/deps/npm/lib/uninstall.js b/deps/npm/lib/uninstall.js index ee0f338e9f..11e65533a8 100644 --- a/deps/npm/lib/uninstall.js +++ b/deps/npm/lib/uninstall.js @@ -7,14 +7,23 @@ const completion = require('./utils/completion/installed-shallow.js') const BaseCommand = require('./base-command.js') class Uninstall extends BaseCommand { + static get description () { + return 'Remove a package' + } + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'uninstall' } /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get params () { + return ['save'] + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get usage () { - return ['[<@scope>/]<pkg>[@<version>]... [-S|--save|--no-save]'] + return ['[<@scope>/]<pkg>...'] } /* istanbul ignore next - see test/lib/load-all-commands.js */ @@ -28,7 +37,8 @@ class Uninstall extends BaseCommand { async uninstall (args) { // the /path/to/node_modules/.. - const { global, prefix } = this.npm.flatOptions + const global = this.npm.config.get('global') + const prefix = this.npm.config.get('prefix') const path = global ? resolve(this.npm.globalDir, '..') : prefix if (!args.length) { diff --git a/deps/npm/lib/unpublish.js b/deps/npm/lib/unpublish.js index 68a9a0ae64..d49bb7ba4e 100644 --- a/deps/npm/lib/unpublish.js +++ b/deps/npm/lib/unpublish.js @@ -12,6 +12,10 @@ const getIdentity = require('./utils/get-identity.js') const BaseCommand = require('./base-command.js') class Unpublish extends BaseCommand { + static get description () { + return 'Remove a package from the registry' + } + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'unpublish' @@ -63,8 +67,9 @@ class Unpublish extends BaseCommand { throw new Error(this.usage) const spec = args.length && npa(args[0]) - const opts = this.npm.flatOptions - const { force, silent, loglevel } = opts + const force = this.npm.config.get('force') + const silent = this.npm.config.get('silent') + const loglevel = this.npm.config.get('loglevel') let pkgName let pkgVersion @@ -79,6 +84,7 @@ class Unpublish extends BaseCommand { ) } + const opts = this.npm.flatOptions if (!spec || path.resolve(spec.name) === this.npm.localPrefix) { // if there's a package.json in the current folder, then // read the package name and version out of that. diff --git a/deps/npm/lib/unstar.js b/deps/npm/lib/unstar.js index 5786cfce60..bc32ba617b 100644 --- a/deps/npm/lib/unstar.js +++ b/deps/npm/lib/unstar.js @@ -2,6 +2,11 @@ const Star = require('./star.js') class Unstar extends Star { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Remove an item from your favorite packages' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'unstar' } diff --git a/deps/npm/lib/update.js b/deps/npm/lib/update.js index 87540b96e0..6a87dd9ecd 100644 --- a/deps/npm/lib/update.js +++ b/deps/npm/lib/update.js @@ -9,13 +9,23 @@ const completion = require('./utils/completion/installed-deep.js') const BaseCommand = require('./base-command.js') class Update extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'Update packages' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'update' } /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get params () { + return ['global'] + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get usage () { - return ['[-g] [<pkg>...]'] + return ['[<pkg>...]'] } /* istanbul ignore next - see test/lib/load-all-commands.js */ @@ -30,11 +40,11 @@ class Update extends BaseCommand { async update (args) { const update = args.length === 0 ? true : args const global = path.resolve(this.npm.globalDir, '..') - const where = this.npm.flatOptions.global + const where = this.npm.config.get('global') ? global : this.npm.prefix - if (this.npm.flatOptions.depth) { + if (this.npm.config.get('depth')) { log.warn('update', 'The --depth option no longer has any effect. See RFC0019.\n' + 'https://github.com/npm/rfcs/blob/latest/implemented/0019-remove-update-depth-option.md') } diff --git a/deps/npm/lib/utils/config.js b/deps/npm/lib/utils/config.js deleted file mode 100644 index 3ca9766132..0000000000 --- a/deps/npm/lib/utils/config.js +++ /dev/null @@ -1,394 +0,0 @@ -// defaults, types, and shorthands - -const { - typeDefs: { - semver: { type: semver }, - Umask: { type: Umask }, - url: { type: url }, - path: { type: path }, - }, -} = require('@npmcli/config') - -const { version: npmVersion } = require('../../package.json') - -const ciDetect = require('@npmcli/ci-detect') -const ciName = ciDetect() - -const isWindows = require('./is-windows.js') - -const editor = process.env.EDITOR || - process.env.VISUAL || - (isWindows ? 'notepad.exe' : 'vi') - -const shell = isWindows ? process.env.ComSpec || 'cmd' - : process.env.SHELL || 'sh' - -const { tmpdir, networkInterfaces } = require('os') -const getLocalAddresses = () => { - try { - return Object.values(networkInterfaces()).map( - int => int.map(({ address }) => address) - ).reduce((set, addrs) => set.concat(addrs), [undefined]) - } catch (e) { - return [undefined] - } -} - -const unicode = /UTF-?8$/i.test( - process.env.LC_ALL || process.env.LC_CTYPE || process.env.LANG -) - -// use LOCALAPPDATA on Windows, if set -// https://github.com/npm/cli/pull/899 -const cacheRoot = (isWindows && process.env.LOCALAPPDATA) || '~' -const cacheExtra = isWindows ? 'npm-cache' : '.npm' -const cache = `${cacheRoot}/${cacheExtra}` - -const defaults = { - access: null, - all: false, - 'allow-same-version': false, - also: null, - 'always-auth': false, - audit: true, - 'audit-level': null, - _auth: null, - 'auth-type': 'legacy', - before: null, - 'bin-links': true, - browser: null, - ca: null, - cache, - 'cache-lock-retries': 10, - 'cache-lock-stale': 60000, - 'cache-lock-wait': 10000, - 'cache-max': Infinity, - 'cache-min': 10, - cafile: null, - call: '', - cert: null, - 'ci-name': ciName || null, - cidr: null, - color: process.env.NO_COLOR == null, - 'commit-hooks': true, - depth: null, - description: true, - dev: false, - diff: [], - 'diff-unified': null, - 'diff-ignore-all-space': false, - 'diff-name-only': false, - 'diff-no-prefix': false, - 'diff-src-prefix': '', - 'diff-dst-prefix': '', - 'diff-text': false, - 'dry-run': false, - editor, - 'engine-strict': false, - 'fetch-retries': 2, - 'fetch-retry-factor': 10, - 'fetch-retry-maxtimeout': 60000, - 'fetch-retry-mintimeout': 10000, - 'fetch-timeout': 5 * 60 * 1000, - force: false, - 'foreground-script': false, - 'format-package-lock': true, - fund: true, - git: 'git', - 'git-tag-version': true, - global: false, - 'global-style': false, - // `globalconfig` has its default defined outside of this module - heading: 'npm', - 'https-proxy': null, - 'if-present': false, - 'ignore-prepublish': false, - 'ignore-scripts': false, - include: [], - 'include-staged': false, - 'init-author-email': '', - 'init-author-name': '', - 'init-author-url': '', - 'init-license': 'ISC', - 'init-module': '~/.npm-init.js', - 'init-version': '1.0.0', - 'init.author.email': '', - 'init.author.name': '', - 'init.author.url': '', - 'init.license': 'ISC', - 'init.module': '~/.npm-init.js', - 'init.version': '1.0.0', - json: false, - key: null, - 'legacy-bundling': false, - 'legacy-peer-deps': false, - link: false, - 'local-address': undefined, - loglevel: 'notice', - 'logs-max': 10, - long: false, - maxsockets: 50, - message: '%s', - 'node-options': null, - 'node-version': process.version, - noproxy: null, - 'npm-version': npmVersion, - offline: false, - omit: [], - only: null, - optional: true, - otp: null, - package: [], - 'package-lock': true, - 'package-lock-only': false, - parseable: false, - 'prefer-offline': false, - 'prefer-online': false, - // `prefix` has its default defined outside of this module - preid: '', - production: process.env.NODE_ENV === 'production', - progress: !ciName, - proxy: null, - 'read-only': false, - 'rebuild-bundle': true, - registry: 'https://registry.npmjs.org/', - rollback: true, - save: true, - 'save-bundle': false, - 'save-dev': false, - 'save-exact': false, - 'save-optional': false, - 'save-prefix': '^', - 'save-prod': false, - scope: '', - 'script-shell': null, - 'scripts-prepend-node-path': 'warn-only', - searchexclude: null, - searchlimit: 20, - searchopts: '', - searchstaleness: 15 * 60, - shell, - shrinkwrap: true, - 'sign-git-commit': false, - 'sign-git-tag': false, - 'sso-poll-frequency': 500, - 'sso-type': 'oauth', - 'strict-peer-deps': false, - 'strict-ssl': true, - tag: 'latest', - 'tag-version-prefix': 'v', - timing: false, - tmp: tmpdir(), - umask: 0, - unicode, - 'update-notifier': true, - usage: false, - 'user-agent': 'npm/{npm-version} ' + - 'node/{node-version} ' + - '{platform} ' + - '{arch} ' + - '{ci}', - userconfig: '~/.npmrc', - version: false, - versions: false, - viewer: isWindows ? 'browser' : 'man', -} - -const types = { - access: [null, 'restricted', 'public'], - 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], - 'auth-type': ['legacy', 'sso', 'saml', 'oauth'], - before: [null, Date], - 'bin-links': Boolean, - browser: [null, Boolean, String], - ca: [null, String, Array], - cache: path, - 'cache-lock-retries': Number, - 'cache-lock-stale': Number, - 'cache-lock-wait': Number, - 'cache-max': Number, - 'cache-min': Number, - cafile: path, - call: String, - cert: [null, String], - 'ci-name': [null, String], - cidr: [null, String, Array], - color: ['always', Boolean], - 'commit-hooks': Boolean, - depth: [null, Number], - description: Boolean, - dev: Boolean, - diff: [String, Array], - 'diff-unified': [null, Number], - 'diff-ignore-all-space': Boolean, - 'diff-name-only': Boolean, - 'diff-no-prefix': Boolean, - 'diff-src-prefix': String, - 'diff-dst-prefix': String, - 'diff-text': Boolean, - 'dry-run': Boolean, - editor: String, - 'engine-strict': Boolean, - 'fetch-retries': Number, - 'fetch-retry-factor': Number, - 'fetch-retry-maxtimeout': Number, - 'fetch-retry-mintimeout': Number, - 'fetch-timeout': Number, - force: Boolean, - 'foreground-script': Boolean, - 'format-package-lock': Boolean, - fund: Boolean, - git: String, - 'git-tag-version': Boolean, - global: Boolean, - 'global-style': Boolean, - globalconfig: path, - heading: String, - 'https-proxy': [null, url], - 'if-present': Boolean, - 'ignore-prepublish': Boolean, - 'ignore-scripts': Boolean, - include: [Array, 'prod', 'dev', 'optional', 'peer'], - 'include-staged': Boolean, - 'init-author-email': String, - 'init-author-name': String, - 'init-author-url': ['', url], - 'init-license': String, - 'init-module': path, - 'init-version': semver, - 'init.author.email': String, - 'init.author.name': String, - 'init.author.url': ['', url], - 'init.license': String, - 'init.module': path, - 'init.version': semver, - json: Boolean, - key: [null, String], - 'legacy-bundling': Boolean, - 'legacy-peer-deps': Boolean, - link: Boolean, - 'local-address': getLocalAddresses(), - loglevel: [ - 'silent', - 'error', - 'warn', - 'notice', - 'http', - 'timing', - 'info', - 'verbose', - 'silly', - ], - 'logs-max': Number, - long: Boolean, - maxsockets: Number, - message: String, - 'node-options': [null, String], - 'node-version': [null, semver], - noproxy: [null, String, Array], - 'npm-version': semver, - offline: Boolean, - omit: [Array, 'dev', 'optional', 'peer'], - only: [null, 'dev', 'development', 'prod', 'production'], - optional: Boolean, - otp: [null, String], - package: [String, Array], - 'package-lock': Boolean, - 'package-lock-only': Boolean, - parseable: Boolean, - 'prefer-offline': Boolean, - 'prefer-online': Boolean, - prefix: path, - preid: String, - production: Boolean, - progress: Boolean, - proxy: [null, false, url], // allow proxy to be disabled explicitly - 'read-only': Boolean, - 'rebuild-bundle': Boolean, - registry: [null, url], - rollback: Boolean, - save: Boolean, - 'save-bundle': Boolean, - 'save-dev': Boolean, - 'save-exact': Boolean, - 'save-optional': Boolean, - 'save-prefix': String, - 'save-prod': Boolean, - scope: String, - 'script-shell': [null, String], - 'scripts-prepend-node-path': [Boolean, 'auto', 'warn-only'], - searchexclude: [null, String], - searchlimit: Number, - searchopts: String, - searchstaleness: Number, - shell: String, - shrinkwrap: Boolean, - 'sign-git-commit': Boolean, - 'sign-git-tag': Boolean, - 'sso-poll-frequency': Number, - 'sso-type': [null, 'oauth', 'saml'], - 'strict-peer-deps': Boolean, - 'strict-ssl': Boolean, - tag: String, - 'tag-version-prefix': String, - timing: Boolean, - tmp: path, - umask: Umask, - unicode: Boolean, - 'update-notifier': Boolean, - usage: Boolean, - 'user-agent': String, - userconfig: path, - version: Boolean, - versions: Boolean, - viewer: String, -} - -const shorthands = { - '?': ['--usage'], - a: ['--all'], - B: ['--save-bundle'], - C: ['--prefix'], - c: ['--call'], - D: ['--save-dev'], - d: ['--loglevel', 'info'], - dd: ['--loglevel', 'verbose'], - ddd: ['--loglevel', 'silly'], - desc: ['--description'], - E: ['--save-exact'], - 'enjoy-by': ['--before'], - f: ['--force'], - g: ['--global'], - H: ['--usage'], - h: ['--usage'], - help: ['--usage'], - l: ['--long'], - local: ['--no-global'], - m: ['--message'], - n: ['--no-yes'], - 'no-desc': ['--no-description'], - 'no-reg': ['--no-registry'], - noreg: ['--no-registry'], - O: ['--save-optional'], - P: ['--save-prod'], - p: ['--parseable'], - porcelain: ['--parseable'], - q: ['--loglevel', 'warn'], - quiet: ['--loglevel', 'warn'], - readonly: ['--read-only'], - reg: ['--registry'], - S: ['--save'], - s: ['--loglevel', 'silent'], - silent: ['--loglevel', 'silent'], - v: ['--version'], - verbose: ['--loglevel', 'verbose'], - y: ['--yes'], -} - -module.exports = { defaults, types, shorthands } diff --git a/deps/npm/lib/utils/config/definition.js b/deps/npm/lib/utils/config/definition.js new file mode 100644 index 0000000000..cb4eb78210 --- /dev/null +++ b/deps/npm/lib/utils/config/definition.js @@ -0,0 +1,185 @@ +// class that describes a config key we know about +// this keeps us from defining a config key and not +// providing a default, description, etc. +// +// TODO: some kind of categorization system, so we can +// say "these are for registry access", "these are for +// version resolution" etc. + +const required = [ + 'type', + 'description', + 'default', + 'key', +] + +const allowed = [ + 'default', + 'defaultDescription', + 'deprecated', + 'description', + 'flatten', + 'hint', + 'key', + 'short', + 'type', + 'typeDescription', + 'usage', +] + +const { + typeDefs: { + semver: { type: semver }, + Umask: { type: Umask }, + url: { type: url }, + path: { type: path }, + }, +} = require('@npmcli/config') + +class Definition { + constructor (key, def) { + this.key = key + Object.assign(this, def) + this.validate() + if (!this.defaultDescription) + this.defaultDescription = describeValue(this.default) + if (!this.typeDescription) + this.typeDescription = describeType(this.type) + if (!this.hint) + this.hint = `<${this.key}>` + if (!this.usage) + this.usage = describeUsage(this) + } + + validate () { + for (const req of required) { + if (!Object.prototype.hasOwnProperty.call(this, req)) + throw new Error(`config lacks ${req}: ${this.key}`) + } + if (!this.key) + throw new Error(`config lacks key: ${this.key}`) + for (const field of Object.keys(this)) { + if (!allowed.includes(field)) + throw new Error(`config defines unknown field ${field}: ${this.key}`) + } + } + + // a textual description of this config, suitable for help output + describe () { + const description = unindent(this.description) + const deprecated = !this.deprecated ? '' + : `* DEPRECATED: ${unindent(this.deprecated)}\n` + return wrapAll(`#### \`${this.key}\` + +* Default: ${unindent(this.defaultDescription)} +* Type: ${unindent(this.typeDescription)} +${deprecated} +${description} +`) + } +} + +// Usage for a single param, abstracted because we have arrays of types in +// config definition +const paramUsage = (type, def) => { + let key = `--${def.key}` + if (def.short && typeof def.short === 'string') + key = `-${def.short}|${key}` + if (type === Boolean) + return `${key}` + else + return `${key} ${def.hint}` +} + +const describeUsage = (def) => { + if (Array.isArray(def.type)) { + if (!def.type.some(d => d !== null && typeof d !== 'string')) + return `--${def.key} <${def.type.filter(d => d).join('|')}>` + else + return def.type.filter(d => d).map((t) => paramUsage(t, def)).join('|') + } + return paramUsage(def.type, def) +} + +const describeType = type => { + if (Array.isArray(type)) { + const descriptions = type + .filter(t => t !== Array) + .map(t => describeType(t)) + + // [a] => "a" + // [a, b] => "a or b" + // [a, b, c] => "a, b, or c" + // [a, Array] => "a (can be set multiple times)" + // [a, Array, b] => "a or b (can be set multiple times)" + const last = descriptions.length > 1 ? [descriptions.pop()] : [] + const oxford = descriptions.length > 1 ? ', or ' : ' or ' + const words = [descriptions.join(', ')].concat(last).join(oxford) + const multiple = type.includes(Array) ? ' (can be set multiple times)' + : '' + return `${words}${multiple}` + } + + // Note: these are not quite the same as the description printed + // when validation fails. In that case, we want to give the user + // a bit more information to help them figure out what's wrong. + switch (type) { + case String: + return 'String' + case Number: + return 'Number' + case Umask: + return 'Octal numeric string in range 0000..0777 (0..511)' + case Boolean: + return 'Boolean' + case Date: + return 'Date' + case path: + return 'Path' + case semver: + return 'SemVer string' + case url: + return 'URL' + default: + return describeValue(type) + } +} + +// if it's a string, quote it. otherwise, just cast to string. +const describeValue = val => + typeof val === 'string' ? JSON.stringify(val) : String(val) + +const unindent = s => { + // get the first \n followed by a bunch of spaces, and pluck off + // that many spaces from the start of every line. + const match = s.match(/\n +/) + return !match ? s.trim() : s.split(match[0]).join('\n').trim() +} + +const wrap = (s) => { + const cols = Math.min(Math.max(20, process.stdout.columns) || 80, 80) - 5 + return unindent(s).split(/[ \n]+/).reduce((left, right) => { + const last = left.split('\n').pop() + const join = last.length && last.length + right.length > cols ? '\n' : ' ' + return left + join + right + }) +} + +const wrapAll = s => { + let inCodeBlock = false + return s.split('\n\n').map(block => { + if (inCodeBlock || block.startsWith('```')) { + inCodeBlock = !block.endsWith('```') + return block + } + + if (block.charAt(0) === '*') { + return '* ' + block.substr(1).trim().split('\n* ').map(li => { + return wrap(li).replace(/\n/g, '\n ') + }).join('\n* ') + } else + return wrap(block) + }).join('\n\n') +} + +module.exports = Definition diff --git a/deps/npm/lib/utils/config/definitions.js b/deps/npm/lib/utils/config/definitions.js new file mode 100644 index 0000000000..a6ecbcd0c4 --- /dev/null +++ b/deps/npm/lib/utils/config/definitions.js @@ -0,0 +1,2054 @@ +const definitions = {} +module.exports = definitions + +const Definition = require('./definition.js') + +const { version: npmVersion } = require('../../../package.json') +const ciDetect = require('@npmcli/ci-detect') +const ciName = ciDetect() +const querystring = require('querystring') +const isWindows = require('../is-windows.js') +const { join } = require('path') + +// used by cafile flattening to flatOptions.ca +const fs = require('fs') +const maybeReadFile = file => { + try { + return fs.readFileSync(file, 'utf8') + } catch (er) { + if (er.code !== 'ENOENT') + throw er + return null + } +} + +const editor = process.env.EDITOR || + process.env.VISUAL || + (isWindows ? 'notepad.exe' : 'vi') + +const shell = isWindows ? process.env.ComSpec || 'cmd' + : process.env.SHELL || 'sh' + +const { tmpdir, networkInterfaces } = require('os') +const getLocalAddresses = () => { + try { + return Object.values(networkInterfaces()).map( + int => int.map(({ address }) => address) + ).reduce((set, addrs) => set.concat(addrs), [null]) + } catch (e) { + return [null] + } +} + +const unicode = /UTF-?8$/i.test( + process.env.LC_ALL || + process.env.LC_CTYPE || + process.env.LANG +) + +// use LOCALAPPDATA on Windows, if set +// https://github.com/npm/cli/pull/899 +const cacheRoot = (isWindows && process.env.LOCALAPPDATA) || '~' +const cacheExtra = isWindows ? 'npm-cache' : '.npm' +const cache = `${cacheRoot}/${cacheExtra}` + +const Config = require('@npmcli/config') + +// TODO: refactor these type definitions so that they are less +// weird to pull out of the config module. +// TODO: use better type definition/validation API, nopt's is so weird. +const { + typeDefs: { + semver: { type: semver }, + Umask: { type: Umask }, + url: { type: url }, + path: { type: path }, + }, +} = Config + +const define = (key, def) => { + /* istanbul ignore if - this should never happen, prevents mistakes below */ + if (definitions[key]) + throw new Error(`defining key more than once: ${key}`) + definitions[key] = new Definition(key, def) +} + +// basic flattening function, just copy it over camelCase +const flatten = (key, obj, flatOptions) => { + const camel = key.replace(/-([a-z])/g, (_0, _1) => _1.toUpperCase()) + flatOptions[camel] = obj[key] +} + +// TODO: +// Instead of having each definition provide a flatten method, +// provide the (?list of?) flat option field(s?) that it impacts. +// When that config is set, we mark the relevant flatOption fields +// dirty. Then, a getter for that field defines how we actually +// set it. +// +// So, `save-dev`, `save-optional`, `save-prod`, et al would indicate +// that they affect the `saveType` flat option. Then the config.flat +// object has a `get saveType () { ... }` that looks at the "real" +// config settings from files etc and returns the appropriate value. +// +// Getters will also (maybe?) give us a hook to audit flat option +// usage, so we can document and group these more appropriately. +// +// This will be a problem with cases where we currently do: +// const opts = { ...npm.flatOptions, foo: 'bar' }, but we can maybe +// instead do `npm.config.set('foo', 'bar')` prior to passing the +// config object down where it needs to go. +// +// This way, when we go hunting for "where does saveType come from anyway!?" +// while fixing some Arborist bug, we won't have to hunt through too +// many places. + +// Define all config keys we know about + +define('_auth', { + default: null, + type: [null, String], + description: ` + A basic-auth string to use when authenticating against the npm registry. + + Warning: This should generally not be set via a command-line option. It + is safer to use a registry-provided authentication bearer token stored in + the ~/.npmrc file by running \`npm login\`. + `, +}) + +define('access', { + default: null, + defaultDescription: ` + 'restricted' for scoped packages, 'public' for unscoped packages + `, + type: [null, 'restricted', 'public'], + description: ` + When publishing scoped packages, the access level defaults to + \`restricted\`. If you want your scoped package to be publicly viewable + (and installable) set \`--access=public\`. The only valid values for + \`access\` are \`public\` and \`restricted\`. Unscoped packages _always_ + have an access level of \`public\`. + `, + flatten, +}) + +define('all', { + default: false, + type: Boolean, + short: 'a', + description: ` + When running \`npm outdated\` and \`npm ls\`, setting \`--all\` will show + all outdated or installed packages, rather than only those directly + depended upon by the current project. + `, + flatten, +}) + +define('allow-same-version', { + default: false, + type: Boolean, + description: ` + Prevents throwing an error when \`npm version\` is used to set the new + version to the same value as the current version. + `, + flatten, +}) + +define('also', { + default: null, + type: [null, 'dev', 'development'], + description: ` + When set to \`dev\` or \`development\`, this is an alias for + \`--include=dev\`. + `, + deprecated: 'Please use --include=dev instead.', + flatten (key, obj, flatOptions) { + if (!/^dev(elopment)?$/.test(obj.also)) + return + + // add to include, and call the omit flattener + obj.include = obj.include || [] + obj.include.push('dev') + definitions.omit.flatten('omit', obj, flatOptions) + }, +}) + +define('always-auth', { + default: false, + type: Boolean, + description: ` + Force npm to always require authentication when accessing the registry, + even for \`GET\` requests. + `, + flatten, +}) + +define('audit', { + default: true, + type: Boolean, + description: ` + When "true" submit audit reports alongside \`npm install\` runs to the + default registry and all registries configured for scopes. See the + documentation for [\`npm audit\`](/commands/npm-audit) for details on + what is submitted. + `, + flatten, +}) + +define('audit-level', { + default: null, + type: ['low', 'moderate', 'high', 'critical', 'none', null], + description: ` + The minimum level of vulnerability for \`npm audit\` to exit with + a non-zero exit code. + `, + flatten, +}) + +define('auth-type', { + default: 'legacy', + type: ['legacy', 'sso', 'saml', 'oauth'], + deprecated: ` + This method of SSO/SAML/OAuth is deprecated and will be removed in + a future version of npm in favor of web-based login. + `, + description: ` + What authentication strategy to use with \`adduser\`/\`login\`. + `, + flatten, +}) + +define('before', { + default: null, + type: [null, Date], + description: ` + If passed to \`npm install\`, will rebuild the npm tree such that only + versions that were available **on or before** the \`--before\` time get + installed. If there's no versions available for the current set of + direct dependencies, the command will error. + + If the requested version is a \`dist-tag\` and the given tag does not + pass the \`--before\` filter, the most recent version less than or equal + to that tag will be used. For example, \`foo@latest\` might install + \`foo@1.2\` even though \`latest\` is \`2.0\`. + `, + flatten, +}) + +define('bin-links', { + default: true, + type: Boolean, + description: ` + Tells npm to create symlinks (or \`.cmd\` shims on Windows) for package + executables. + + Set to false to have it not do this. This can be used to work around the + fact that some file systems don't support symlinks, even on ostensibly + Unix systems. + `, + flatten, +}) + +define('browser', { + default: null, + defaultDescription: ` + OS X: \`"open"\`, Windows: \`"start"\`, Others: \`"xdg-open"\` + `, + type: [null, Boolean, String], + description: ` + The browser that is called by npm commands to open websites. + + Set to \`false\` to suppress browser behavior and instead print urls to + terminal. + + Set to \`true\` to use default system URL opener. + `, + flatten, +}) + +define('ca', { + default: null, + type: [null, String, Array], + description: ` + The Certificate Authority signing certificate that is trusted for SSL + connections to the registry. Values should be in PEM format (Windows + calls it "Base-64 encoded X.509 (.CER)") with newlines replaced by the + string "\\n". For example: + + \`\`\`ini + ca="-----BEGIN CERTIFICATE-----\\nXXXX\\nXXXX\\n-----END CERTIFICATE-----" + \`\`\` + + Set to \`null\` to only allow "known" registrars, or to a specific CA + cert to trust only that specific signing authority. + + Multiple CAs can be trusted by specifying an array of certificates: + + \`\`\`ini + ca[]="..." + ca[]="..." + \`\`\` + + See also the \`strict-ssl\` config. + `, + flatten, +}) + +define('cache', { + default: cache, + defaultDescription: ` + Windows: \`%LocalAppData%\\npm-cache\`, Posix: \`~/.npm\` + `, + type: path, + description: ` + The location of npm's cache directory. See [\`npm + cache\`](/commands/npm-cache) + `, + flatten (key, obj, flatOptions) { + flatOptions.cache = join(obj.cache, '_cacache') + }, +}) + +define('cache-max', { + default: Infinity, + type: Number, + description: ` + \`--cache-max=0\` is an alias for \`--prefer-online\` + `, + deprecated: ` + This option has been deprecated in favor of \`--prefer-online\` + `, + flatten (key, obj, flatOptions) { + if (obj[key] <= 0) + flatOptions.preferOnline = true + }, +}) + +define('cache-min', { + default: 0, + type: Number, + description: ` + \`--cache-min=9999 (or bigger)\` is an alias for \`--prefer-offline\`. + `, + deprecated: ` + This option has been deprecated in favor of \`--prefer-offline\`. + `, + flatten (key, obj, flatOptions) { + if (obj[key] >= 9999) + flatOptions.preferOffline = true + }, +}) + +define('cafile', { + default: null, + type: path, + description: ` + A path to a file containing one or multiple Certificate Authority signing + certificates. Similar to the \`ca\` setting, but allows for multiple + CA's, as well as for the CA information to be stored in a file on disk. + `, + flatten (key, obj, flatOptions) { + // always set to null in defaults + if (!obj.cafile) + return + + const raw = maybeReadFile(obj.cafile) + if (!raw) + return + + const delim = '-----END CERTIFICATE-----' + flatOptions.ca = raw.replace(/\r\n/g, '\n').split(delim) + .filter(section => section.trim()) + .map(section => section.trimLeft() + delim) + }, +}) + +define('call', { + default: '', + type: String, + short: 'c', + description: ` + Optional companion option for \`npm exec\`, \`npx\` that allows for + specifying a custom command to be run along with the installed packages. + + \`\`\`bash + npm exec --package yo --package generator-node --call "yo node" + \`\`\` + `, + flatten, +}) + +define('cert', { + default: null, + type: [null, String], + description: ` + A client certificate to pass when accessing the registry. Values should + be in PEM format (Windows calls it "Base-64 encoded X.509 (.CER)") with + newlines replaced by the string "\\n". For example: + + \`\`\`ini + cert="-----BEGIN CERTIFICATE-----\\nXXXX\\nXXXX\\n-----END CERTIFICATE-----" + \`\`\` + + It is _not_ the path to a certificate file (and there is no "certfile" + option). + `, + flatten, +}) + +define('ci-name', { + default: ciName || null, + defaultDescription: ` + The name of the current CI system, or \`null\` when not on a known CI + platform. + `, + type: [null, String], + description: ` + The name of a continuous integration system. If not set explicitly, npm + will detect the current CI environment using the + [\`@npmcli/ci-detect\`](http://npm.im/@npmcli/ci-detect) module. + `, + flatten, +}) + +define('cidr', { + default: null, + type: [null, String, Array], + description: ` + This is a list of CIDR address to be used when configuring limited access + tokens with the \`npm token create\` command. + `, + flatten, +}) + +define('color', { + default: !process.env.NO_COLOR || process.env.NO_COLOR === '0', + defaultDescription: ` + true unless the NO_COLOR environ is set to something other than '0' + `, + type: ['always', Boolean], + description: ` + If false, never shows colors. If \`"always"\` then always shows colors. + If true, then only prints color codes for tty file descriptors. + `, + flatten (key, obj, flatOptions) { + flatOptions.color = !obj.color ? false + : obj.color === 'always' ? true + : process.stdout.isTTY + }, +}) + +define('commit-hooks', { + default: true, + type: Boolean, + description: ` + Run git commit hooks when using the \`npm version\` command. + `, + flatten, +}) + +define('depth', { + default: null, + defaultDescription: ` + \`Infinity\` if \`--all\` is set, otherwise \`1\` + `, + type: [null, Number], + description: ` + The depth to go when recursing packages for \`npm ls\`. + + If not set, \`npm ls\` will show only the immediate dependencies of the + root project. If \`--all\` is set, then npm will show all dependencies + by default. + `, + flatten, +}) + +define('description', { + default: true, + type: Boolean, + usage: '--no-description', + description: ` + Show the description in \`npm search\` + `, + flatten (key, obj, flatOptions) { + flatOptions.search = flatOptions.search || { limit: 20 } + flatOptions.search[key] = obj[key] + }, +}) + +define('diff', { + default: [], + type: [String, Array], + description: ` + Define arguments to compare in \`npm diff\`. + `, + flatten, +}) + +define('diff-ignore-all-space', { + default: false, + type: Boolean, + description: ` + Ignore whitespace when comparing lines in \`npm diff\`. + `, + flatten, +}) + +define('diff-name-only', { + default: false, + type: Boolean, + description: ` + Prints only filenames when using \`npm diff\`. + `, + flatten, +}) + +define('diff-no-prefix', { + default: false, + type: Boolean, + description: ` + Do not show any source or destination prefix in \`npm diff\` output. + + Note: this causes \`npm diff\` to ignore the \`--diff-src-prefix\` and + \`--diff-dst-prefix\` configs. + `, + flatten, +}) + +define('diff-dst-prefix', { + default: 'b/', + type: String, + description: ` + Destination prefix to be used in \`npm diff\` output. + `, + flatten, +}) + +define('diff-src-prefix', { + default: 'a/', + type: String, + description: ` + Source prefix to be used in \`npm diff\` output. + `, + flatten, +}) + +define('diff-text', { + default: false, + type: Boolean, + description: ` + Treat all files as text in \`npm diff\`. + `, + flatten, +}) + +define('diff-unified', { + default: 3, + type: Number, + description: ` + The number of lines of context to print in \`npm diff\`. + `, + flatten, +}) + +define('dry-run', { + default: false, + type: Boolean, + description: ` + Indicates that you don't want npm to make any changes and that it should + only report what it would have done. This can be passed into any of the + commands that modify your local installation, eg, \`install\`, + \`update\`, \`dedupe\`, \`uninstall\`, as well as \`pack\` and + \`publish\`. + + Note: This is NOT honored by other network related commands, eg + \`dist-tags\`, \`owner\`, etc. + `, + flatten, +}) + +define('editor', { + default: editor, + defaultDescription: ` + The EDITOR or VISUAL environment variables, or 'notepad.exe' on Windows, + or 'vim' on Unix systems + `, + type: String, + description: ` + The command to run for \`npm edit\` and \`npm config edit\`. + `, + flatten, +}) + +define('engine-strict', { + default: false, + type: Boolean, + description: ` + If set to true, then npm will stubbornly refuse to install (or even + consider installing) any package that claims to not be compatible with + the current Node.js version. + + This can be overridden by setting the \`--force\` flag. + `, + flatten, +}) + +define('fetch-retries', { + default: 2, + type: Number, + description: ` + The "retries" config for the \`retry\` module to use when fetching + packages from the registry. + + npm will retry idempotent read requests to the registry in the case + of network failures or 5xx HTTP errors. + `, + flatten (key, obj, flatOptions) { + flatOptions.retry = flatOptions.retry || {} + flatOptions.retry.retries = obj[key] + }, +}) + +define('fetch-retry-factor', { + default: 10, + type: Number, + description: ` + The "factor" config for the \`retry\` module to use when fetching + packages. + `, + flatten (key, obj, flatOptions) { + flatOptions.retry = flatOptions.retry || {} + flatOptions.retry.factor = obj[key] + }, +}) + +define('fetch-retry-maxtimeout', { + default: 60000, + defaultDescription: '60000 (1 minute)', + type: Number, + description: ` + The "maxTimeout" config for the \`retry\` module to use when fetching + packages. + `, + flatten (key, obj, flatOptions) { + flatOptions.retry = flatOptions.retry || {} + flatOptions.retry.maxTimeout = obj[key] + }, +}) + +define('fetch-retry-mintimeout', { + default: 10000, + defaultDescription: '10000 (10 seconds)', + type: Number, + description: ` + The "minTimeout" config for the \`retry\` module to use when fetching + packages. + `, + flatten (key, obj, flatOptions) { + flatOptions.retry = flatOptions.retry || {} + flatOptions.retry.minTimeout = obj[key] + }, +}) + +define('fetch-timeout', { + default: 5 * 60 * 1000, + defaultDescription: `${5 * 60 * 1000} (5 minutes)`, + type: Number, + description: ` + The maximum amount of time to wait for HTTP requests to complete. + `, + flatten (key, obj, flatOptions) { + flatOptions.timeout = obj[key] + }, +}) + +define('force', { + default: false, + type: Boolean, + short: 'f', + description: ` + Removes various protections against unfortunate side effects, common + mistakes, unnecessary performance degradation, and malicious input. + + * Allow clobbering non-npm files in global installs. + * Allow the \`npm version\` command to work on an unclean git repository. + * Allow deleting the cache folder with \`npm cache clean\`. + * Allow installing packages that have an \`engines\` declaration + requiring a different version of npm. + * Allow installing packages that have an \`engines\` declaration + requiring a different version of \`node\`, even if \`--engine-strict\` + is enabled. + * Allow \`npm audit fix\` to install modules outside your stated + dependency range (including SemVer-major changes). + * Allow unpublishing all versions of a published package. + * Allow conflicting peerDependencies to be installed in the root project. + + If you don't have a clear idea of what you want to do, it is strongly + recommended that you do not use this option! + `, + flatten, +}) + +define('foreground-scripts', { + default: false, + type: Boolean, + description: ` + Run all build scripts (ie, \`preinstall\`, \`install\`, and + \`postinstall\`) scripts for installed packages in the foreground + process, sharing standard input, output, and error with the main npm + process. + + Note that this will generally make installs run slower, and be much + noisier, but can be useful for debugging. + `, + flatten, +}) + +define('format-package-lock', { + default: true, + type: Boolean, + description: ` + Format \`package-lock.json\` or \`npm-shrinkwrap.json\` as a human + readable file. + `, + flatten, +}) + +define('fund', { + default: true, + type: Boolean, + description: ` + When "true" displays the message at the end of each \`npm install\` + acknowledging the number of dependencies looking for funding. + See [\`npm fund\`](/commands/npm-fund) for details. + `, + flatten, +}) + +define('git', { + default: 'git', + type: String, + description: ` + The command to use for git commands. If git is installed on the + computer, but is not in the \`PATH\`, then set this to the full path to + the git binary. + `, + flatten, +}) + +define('git-tag-version', { + default: true, + type: Boolean, + description: ` + Tag the commit when using the \`npm version\` command. + `, + flatten, +}) + +define('global', { + default: false, + type: Boolean, + short: 'g', + description: ` + Operates in "global" mode, so that packages are installed into the + \`prefix\` folder instead of the current working directory. See + [folders](/configuring-npm/folders) for more on the differences in + behavior. + + * packages are installed into the \`{prefix}/lib/node_modules\` folder, + instead of the current working directory. + * bin files are linked to \`{prefix}/bin\` + * man pages are linked to \`{prefix}/share/man\` + `, + flatten, +}) + +define('global-style', { + default: false, + type: Boolean, + description: ` + Causes npm to install the package into your local \`node_modules\` folder + with the same layout it uses with the global \`node_modules\` folder. + Only your direct dependencies will show in \`node_modules\` and + everything they depend on will be flattened in their \`node_modules\` + folders. This obviously will eliminate some deduping. If used with + \`legacy-bundling\`, \`legacy-bundling\` will be preferred. + `, + flatten, +}) + +// the globalconfig has its default defined outside of this module +define('globalconfig', { + type: path, + default: '', + defaultDescription: ` + The global --prefix setting plus 'etc/npmrc'. For example, + '/usr/local/etc/npmrc' + `, + description: ` + The config file to read for global config options. + `, + flatten, +}) + +define('heading', { + default: 'npm', + type: String, + description: ` + The string that starts all the debugging log output. + `, + flatten, +}) + +define('https-proxy', { + default: null, + type: [null, url], + description: ` + A proxy to use for outgoing https requests. If the \`HTTPS_PROXY\` or + \`https_proxy\` or \`HTTP_PROXY\` or \`http_proxy\` environment variables + are set, proxy settings will be honored by the underlying + \`make-fetch-happen\` library. + `, + flatten, +}) + +define('if-present', { + default: false, + type: Boolean, + description: ` + If true, npm will not exit with an error code when \`run-script\` is + invoked for a script that isn't defined in the \`scripts\` section of + \`package.json\`. This option can be used when it's desirable to + optionally run a script when it's present and fail if the script fails. + This is useful, for example, when running scripts that may only apply for + some builds in an otherwise generic CI setup. + `, + flatten, +}) + +define('ignore-scripts', { + default: false, + type: Boolean, + description: ` + If true, npm does not run scripts specified in package.json files. + `, + flatten, +}) + +define('include', { + default: [], + type: [Array, 'prod', 'dev', 'optional', 'peer'], + description: ` + Option that allows for defining which types of dependencies to install. + + This is the inverse of \`--omit=<type>\`. + + Dependency types specified in \`--include\` will not be omitted, + regardless of the order in which omit/include are specified on the + command-line. + `, + flatten (key, obj, flatOptions) { + // just call the omit flattener, it reads from obj.include + definitions.omit.flatten('omit', obj, flatOptions) + }, +}) + +define('include-staged', { + default: false, + type: Boolean, + description: ` + Allow installing "staged" published packages, as defined by [npm RFC PR + #92](https://github.com/npm/rfcs/pull/92). + + This is experimental, and not implemented by the npm public registry. + `, + flatten, +}) + +define('init-author-email', { + default: '', + type: String, + description: ` + The value \`npm init\` should use by default for the package author's + email. + `, +}) + +define('init-author-name', { + default: '', + type: String, + description: ` + The value \`npm init\` should use by default for the package author's name. + `, +}) + +define('init-author-url', { + default: '', + type: ['', url], + description: ` + The value \`npm init\` should use by default for the package author's homepage. + `, +}) + +define('init-license', { + default: 'ISC', + type: String, + description: ` + The value \`npm init\` should use by default for the package license. + `, +}) + +define('init-module', { + default: '~/.npm-init.js', + type: path, + description: ` + A module that will be loaded by the \`npm init\` command. See the + documentation for the + [init-package-json](https://github.com/npm/init-package-json) module for + more information, or [npm init](/commands/npm-init). + `, +}) + +define('init-version', { + default: '1.0.0', + type: semver, + description: ` + The value that \`npm init\` should use by default for the package + version number, if not already set in package.json. + `, +}) + +// these "aliases" are historically supported in .npmrc files, unfortunately +// They should be removed in a future npm version. +define('init.author.email', { + default: '', + type: String, + deprecated: ` + Use \`--init-author-email\` instead.`, + description: ` + Alias for \`--init-author-email\` + `, +}) + +define('init.author.name', { + default: '', + type: String, + deprecated: ` + Use \`--init-author-name\` instead. + `, + description: ` + Alias for \`--init-author-name\` + `, +}) + +define('init.author.url', { + default: '', + type: ['', url], + deprecated: ` + Use \`--init-author-url\` instead. + `, + description: ` + Alias for \`--init-author-url\` + `, +}) + +define('init.license', { + default: 'ISC', + type: String, + deprecated: ` + Use \`--init-license\` instead. + `, + description: ` + Alias for \`--init-license\` + `, +}) + +define('init.module', { + default: '~/.npm-init.js', + type: path, + deprecated: ` + Use \`--init-module\` instead. + `, + description: ` + Alias for \`--init-module\` + `, +}) + +define('init.version', { + default: '1.0.0', + type: semver, + deprecated: ` + Use \`--init-version\` instead. + `, + description: ` + Alias for \`--init-version\` + `, +}) + +define('json', { + default: false, + type: Boolean, + description: ` + Whether or not to output JSON data, rather than the normal output. + + This feature is currently experimental, and the output data structures + for many commands is either not implemented in JSON yet, or subject to + change. Only the output from \`npm ls --json\` and \`npm search --json\` + are currently valid. + `, + flatten, +}) + +define('key', { + default: null, + type: [null, String], + description: ` + A client key to pass when accessing the registry. Values should be in + PEM format with newlines replaced by the string "\\n". For example: + + \`\`\`ini + key="-----BEGIN PRIVATE KEY-----\\nXXXX\\nXXXX\\n-----END PRIVATE KEY-----" + \`\`\` + + It is _not_ the path to a key file (and there is no "keyfile" option). + `, + flatten, +}) + +define('legacy-bundling', { + default: false, + type: Boolean, + description: ` + Causes npm to install the package such that versions of npm prior to 1.4, + such as the one included with node 0.8, can install the package. This + eliminates all automatic deduping. If used with \`global-style\` this + option will be preferred. + `, + flatten, +}) + +define('legacy-peer-deps', { + default: false, + type: Boolean, + description: ` + Causes npm to completely ignore \`peerDependencies\` when building a + package tree, as in npm versions 3 through 6. + + If a package cannot be installed because of overly strict + \`peerDependencies\` that collide, it provides a way to move forward + resolving the situation. + + This differs from \`--omit=peer\`, in that \`--omit=peer\` will avoid + unpacking \`peerDependencies\` on disk, but will still design a tree such + that \`peerDependencies\` _could_ be unpacked in a correct place. + + Use of \`legacy-peer-deps\` is not recommended, as it will not enforce + the \`peerDependencies\` contract that meta-dependencies may rely on. + `, + flatten, +}) + +define('link', { + default: false, + type: Boolean, + description: ` + If true, then local installs will link if there is a suitable globally + installed package. + + Note that this means that local installs can cause things to be installed + into the global space at the same time. The link is only done if one of + the two conditions are met: + + * The package is not already installed globally, or + * the globally installed version is identical to the version that is + being installed locally. + `, +}) + +define('local-address', { + default: null, + type: getLocalAddresses(), + typeDescription: 'IP Address', + description: ` + The IP address of the local interface to use when making connections to + the npm registry. Must be IPv4 in versions of Node prior to 0.12. + `, + flatten, +}) + +define('loglevel', { + default: 'notice', + type: [ + 'silent', + 'error', + 'warn', + 'notice', + 'http', + 'timing', + 'info', + 'verbose', + 'silly', + ], + description: ` + What level of logs to report. On failure, *all* logs are written to + \`npm-debug.log\` in the current working directory. + + Any logs of a higher level than the setting are shown. The default is + "notice". + `, +}) + +define('logs-max', { + default: 10, + type: Number, + description: ` + The maximum number of log files to store. + `, +}) + +define('long', { + default: false, + type: Boolean, + short: 'l', + description: ` + Show extended information in \`npm ls\` and \`npm search\`. + `, +}) + +define('maxsockets', { + default: Infinity, + type: Number, + description: ` + The maximum number of connections to use per origin (protocol/host/port + combination). + `, + flatten (key, obj, flatOptions) { + flatOptions.maxSockets = obj[key] + }, +}) + +define('message', { + default: '%s', + type: String, + short: 'm', + description: ` + Commit message which is used by \`npm version\` when creating version commit. + + Any "%s" in the message will be replaced with the version number. + `, + flatten, +}) + +define('node-options', { + default: null, + type: [null, String], + description: ` + Options to pass through to Node.js via the \`NODE_OPTIONS\` environment + variable. This does not impact how npm itself is executed but it does + impact how lifecycle scripts are called. + `, +}) + +define('node-version', { + default: process.version, + defaultDescription: 'Node.js `process.version` value', + type: semver, + description: ` + The node version to use when checking a package's \`engines\` setting. + `, + flatten, +}) + +define('noproxy', { + default: '', + defaultDescription: ` + The value of the NO_PROXY environment variable + `, + type: [String, Array], + description: ` + Domain extensions that should bypass any proxies. + + Also accepts a comma-delimited string. + `, + flatten (key, obj, flatOptions) { + flatOptions.noProxy = obj[key].join(',') + }, +}) + +define('npm-version', { + default: npmVersion, + defaultDescription: 'Output of `npm --version`', + type: semver, + description: ` + The npm version to use when checking a package's \`engines\` setting. + `, + flatten, +}) + +define('offline', { + default: false, + type: Boolean, + description: ` + Force offline mode: no network requests will be done during install. To allow + the CLI to fill in missing cache data, see \`--prefer-offline\`. + `, + flatten, +}) + +define('omit', { + default: process.env.NODE_ENV === 'production' ? ['dev'] : [], + defaultDescription: ` + 'dev' if the NODE_ENV environment variable is set to 'production', + otherwise empty. + `, + type: [Array, 'dev', 'optional', 'peer'], + description: ` + Dependency types to omit from the installation tree on disk. + + Note that these dependencies _are_ still resolved and added to the + \`package-lock.json\` or \`npm-shrinkwrap.json\` file. They are just + not physically installed on disk. + + If a package type appears in both the \`--include\` and \`--omit\` + lists, then it will be included. + + If the resulting omit list includes \`'dev'\`, then the \`NODE_ENV\` + environment variable will be set to \`'production'\` for all lifecycle + scripts. + `, + flatten (key, obj, flatOptions) { + const include = obj.include || [] + const omit = flatOptions.omit || [] + flatOptions.omit = omit.concat(obj[key]) + .filter(type => type && !include.includes(type)) + }, +}) + +define('only', { + default: null, + type: [null, 'prod', 'production'], + deprecated: ` + Use \`--omit=dev\` to omit dev dependencies from the install. + `, + description: ` + When set to \`prod\` or \`production\`, this is an alias for + \`--omit=dev\`. + `, + flatten (key, obj, flatOptions) { + const value = obj[key] + if (!/^prod(uction)?$/.test(value)) + return + + obj.omit = obj.omit || [] + obj.omit.push('dev') + definitions.omit.flatten('omit', obj, flatOptions) + }, +}) + +define('optional', { + default: null, + type: [null, Boolean], + deprecated: ` + Use \`--omit=optional\` to exclude optional dependencies, or + \`--include=optional\` to include them. + + Default value does install optional deps unless otherwise omitted. + `, + description: ` + Alias for --include=optional or --omit=optional + `, + flatten (key, obj, flatOptions) { + const value = obj[key] + if (value === null) + return + else if (value === true) { + obj.include = obj.include || [] + obj.include.push('optional') + } else { + obj.omit = obj.omit || [] + obj.omit.push('optional') + } + definitions.omit.flatten('omit', obj, flatOptions) + }, +}) + +define('otp', { + default: null, + type: [null, String], + description: ` + This is a one-time password from a two-factor authenticator. It's needed + when publishing or changing package permissions with \`npm access\`. + + If not set, and a registry response fails with a challenge for a one-time + password, npm will prompt on the command line for one. + `, + flatten, +}) + +define('package', { + default: [], + hint: '<pkg>[@<version>]', + type: [String, Array], + description: ` + The package to install for [\`npm exec\`](/commands/npm-exec) + `, + flatten, +}) + +define('package-lock', { + default: true, + type: Boolean, + description: ` + If set to false, then ignore \`package-lock.json\` files when installing. + This will also prevent _writing_ \`package-lock.json\` if \`save\` is + true. + + When package package-locks are disabled, automatic pruning of extraneous + modules will also be disabled. To remove extraneous modules with + package-locks disabled use \`npm prune\`. + `, + flatten, +}) + +define('package-lock-only', { + default: false, + type: Boolean, + description: ` + If set to true, it will update only the \`package-lock.json\`, instead of + checking \`node_modules\` and downloading dependencies. + `, + flatten, +}) + +define('parseable', { + default: false, + type: Boolean, + short: 'p', + description: ` + Output parseable results from commands that write to standard output. For + \`npm search\`, this will be tab-separated table format. + `, + flatten, +}) + +define('prefer-offline', { + default: false, + type: Boolean, + description: ` + If true, staleness checks for cached data will be bypassed, but missing + data will be requested from the server. To force full offline mode, use + \`--offline\`. + `, + flatten, +}) + +define('prefer-online', { + default: false, + type: Boolean, + description: ` + If true, staleness checks for cached data will be forced, making the CLI + look for updates immediately even for fresh package data. + `, + flatten, +}) + +// `prefix` has its default defined outside of this module +define('prefix', { + type: path, + short: 'C', + default: '', + defaultDescription: ` + In global mode, the folder where the node executable is installed. In + local mode, the nearest parent folder containing either a package.json + file or a node_modules folder. + `, + description: ` + The location to install global items. If set on the command line, then + it forces non-global commands to run in the specified folder. + `, +}) + +define('preid', { + default: '', + type: String, + description: ` + The "prerelease identifier" to use as a prefix for the "prerelease" part + of a semver. Like the \`rc\` in \`1.2.0-rc.8\`. + `, + flatten, +}) + +define('production', { + default: false, + type: Boolean, + deprecated: 'Use `--omit=dev` instead.', + description: 'Alias for `--omit=dev`', + flatten (key, obj, flatOptions) { + const value = obj[key] + if (!value) + return + + obj.omit = obj.omit || [] + obj.omit.push('dev') + definitions.omit.flatten('omit', obj, flatOptions) + }, +}) + +define('progress', { + default: !ciName, + defaultDescription: ` + \`true\` unless running in a known CI system + `, + type: Boolean, + description: ` + When set to \`true\`, npm will display a progress bar during time + intensive operations, if \`process.stderr\` is a TTY. + + Set to \`false\` to suppress the progress bar. + `, +}) + +define('proxy', { + default: null, + type: [null, false, url], // allow proxy to be disabled explicitly + description: ` + A proxy to use for outgoing http requests. If the \`HTTP_PROXY\` or + \`http_proxy\` environment variables are set, proxy settings will be + honored by the underlying \`request\` library. + `, + flatten, +}) + +define('read-only', { + default: false, + type: Boolean, + description: ` + This is used to mark a token as unable to publish when configuring + limited access tokens with the \`npm token create\` command. + `, + flatten, +}) + +define('rebuild-bundle', { + default: true, + type: Boolean, + description: ` + Rebuild bundled dependencies after installation. + `, + flatten, +}) + +define('registry', { + default: 'https://registry.npmjs.org/', + type: url, + description: ` + The base URL of the npm registry. + `, + flatten, +}) + +define('save', { + default: true, + usage: '-S|--save|--no-save|--save-prod|--save-dev|--save-optional|--save-peer', + type: Boolean, + short: 'S', + description: ` + Save installed packages to a package.json file as dependencies. + + When used with the \`npm rm\` command, removes the dependency from + package.json. + `, + flatten, +}) + +define('save-bundle', { + default: false, + type: Boolean, + short: 'B', + description: ` + If a package would be saved at install time by the use of \`--save\`, + \`--save-dev\`, or \`--save-optional\`, then also put it in the + \`bundleDependencies\` list. + + Ignore if \`--save-peer\` is set, since peerDependencies cannot be bundled. + `, + flatten (key, obj, flatOptions) { + // XXX update arborist to just ignore it if resulting saveType is peer + // otherwise this won't have the expected effect: + // + // npm config set save-peer true + // npm i foo --save-bundle --save-prod <-- should bundle + flatOptions.saveBundle = obj['save-bundle'] && !obj['save-peer'] + }, +}) + +// XXX: We should really deprecate all these `--save-blah` switches +// in favor of a single `--save-type` option. The unfortunate shortcut +// we took for `--save-peer --save-optional` being `--save-type=peerOptional` +// makes this tricky, and likely a breaking change. + +define('save-dev', { + default: false, + type: Boolean, + short: 'D', + description: ` + Save installed packages to a package.json file as \`devDependencies\`. + `, + flatten (key, obj, flatOptions) { + if (!obj[key]) { + if (flatOptions.saveType === 'dev') + delete flatOptions.saveType + return + } + + flatOptions.saveType = 'dev' + }, +}) + +define('save-exact', { + default: false, + type: Boolean, + short: 'E', + description: ` + Dependencies saved to package.json will be configured with an exact + version rather than using npm's default semver range operator. + `, + flatten, +}) + +define('save-optional', { + default: false, + type: Boolean, + short: 'O', + description: ` + Save installed packages to a package.json file as + \`optionalDependencies\`. + `, + flatten (key, obj, flatOptions) { + if (!obj[key]) { + if (flatOptions.saveType === 'optional') + delete flatOptions.saveType + else if (flatOptions.saveType === 'peerOptional') + flatOptions.saveType = 'peer' + return + } + + if (flatOptions.saveType === 'peerOptional') + return + + if (flatOptions.saveType === 'peer') + flatOptions.saveType = 'peerOptional' + else + flatOptions.saveType = 'optional' + }, +}) + +define('save-peer', { + default: false, + type: Boolean, + description: ` + Save installed packages. to a package.json file as \`peerDependencies\` + `, + flatten (key, obj, flatOptions) { + if (!obj[key]) { + if (flatOptions.saveType === 'peer') + delete flatOptions.saveType + else if (flatOptions.saveType === 'peerOptional') + flatOptions.saveType = 'optional' + return + } + + if (flatOptions.saveType === 'peerOptional') + return + + if (flatOptions.saveType === 'optional') + flatOptions.saveType = 'peerOptional' + else + flatOptions.saveType = 'peer' + }, +}) + +define('save-prefix', { + default: '^', + type: String, + description: ` + Configure how versions of packages installed to a package.json file via + \`--save\` or \`--save-dev\` get prefixed. + + For example if a package has version \`1.2.3\`, by default its version is + set to \`^1.2.3\` which allows minor upgrades for that package, but after + \`npm config set save-prefix='~'\` it would be set to \`~1.2.3\` which + only allows patch upgrades. + `, + flatten, +}) + +define('save-prod', { + default: false, + type: Boolean, + short: 'P', + description: ` + Save installed packages into \`dependencies\` specifically. This is + useful if a package already exists in \`devDependencies\` or + \`optionalDependencies\`, but you want to move it to be a non-optional + production dependency. + + This is the default behavior if \`--save\` is true, and neither + \`--save-dev\` or \`--save-optional\` are true. + `, + flatten (key, obj, flatOptions) { + if (!obj[key]) { + if (flatOptions.saveType === 'prod') + delete flatOptions.saveType + return + } + + flatOptions.saveType = 'prod' + }, +}) + +define('scope', { + default: '', + defaultDescription: ` + the scope of the current project, if any, or "" + `, + type: String, + hint: '<@scope>', + description: ` + Associate an operation with a scope for a scoped registry. + + Useful when logging in to a private registry for the first time: + + \`\`\`bash + npm login --scope=@mycorp --registry=https://registry.mycorp.com + \`\`\` + + This will cause \`@mycorp\` to be mapped to the registry for future + installation of packages specified according to the pattern + \`@mycorp/package\`. + `, + flatten (key, obj, flatOptions) { + const value = obj[key] + flatOptions.projectScope = value && !/^@/.test(value) ? `@${value}` : value + }, +}) + +define('script-shell', { + default: null, + defaultDescription: ` + '/bin/sh' on POSIX systems, 'cmd.exe' on Windows + `, + type: [null, String], + description: ` + The shell to use for scripts run with the \`npm run\` command. + `, + flatten (key, obj, flatOptions) { + flatOptions.scriptShell = obj[key] || undefined + }, +}) + +define('searchexclude', { + default: '', + type: String, + description: ` + Space-separated options that limit the results from search. + `, + flatten (key, obj, flatOptions) { + flatOptions.search = flatOptions.search || { limit: 20 } + flatOptions.search.exclude = obj[key] + }, +}) + +define('searchlimit', { + default: 20, + type: Number, + description: ` + Number of items to limit search results to. Will not apply at all to + legacy searches. + `, + flatten (key, obj, flatOptions) { + flatOptions.search = flatOptions.search || {} + flatOptions.search.limit = obj[key] + }, +}) + +define('searchopts', { + default: '', + type: String, + description: ` + Space-separated options that are always passed to search. + `, + flatten (key, obj, flatOptions) { + flatOptions.search = flatOptions.search || { limit: 20 } + flatOptions.search.opts = querystring.parse(obj[key]) + }, +}) + +define('searchstaleness', { + default: 15 * 60, + type: Number, + description: ` + The age of the cache, in seconds, before another registry request is made + if using legacy search endpoint. + `, + flatten (key, obj, flatOptions) { + flatOptions.search = flatOptions.search || { limit: 20 } + flatOptions.search.staleness = obj[key] + }, +}) + +define('shell', { + default: shell, + defaultDescription: ` + SHELL environment variable, or "bash" on Posix, or "cmd.exe" on Windows + `, + type: String, + description: ` + The shell to run for the \`npm explore\` command. + `, + flatten, +}) + +define('shrinkwrap', { + default: true, + type: Boolean, + deprecated: ` + Use the --package-lock setting instead. + `, + description: ` + Alias for --package-lock + `, + flatten (key, obj, flatOptions) { + obj['package-lock'] = obj.shrinkwrap + definitions['package-lock'].flatten('package-lock', obj, flatOptions) + }, +}) + +define('sign-git-commit', { + default: false, + type: Boolean, + description: ` + If set to true, then the \`npm version\` command will commit the new + package version using \`-S\` to add a signature. + + Note that git requires you to have set up GPG keys in your git configs + for this to work properly. + `, + flatten, +}) + +define('sign-git-tag', { + default: false, + type: Boolean, + description: ` + If set to true, then the \`npm version\` command will tag the version + using \`-s\` to add a signature. + + Note that git requires you to have set up GPG keys in your git configs + for this to work properly. + `, + flatten, +}) + +define('sso-poll-frequency', { + default: 500, + type: Number, + deprecated: ` + The --auth-type method of SSO/SAML/OAuth will be removed in a future + version of npm in favor of web-based login. + `, + description: ` + When used with SSO-enabled \`auth-type\`s, configures how regularly the + registry should be polled while the user is completing authentication. + `, + flatten, +}) + +define('sso-type', { + default: 'oauth', + type: [null, 'oauth', 'saml'], + deprecated: ` + The --auth-type method of SSO/SAML/OAuth will be removed in a future + version of npm in favor of web-based login. + `, + description: ` + If \`--auth-type=sso\`, the type of SSO type to use. + `, + flatten, +}) + +define('strict-peer-deps', { + default: false, + type: Boolean, + description: ` + If set to \`true\`, and \`--legacy-peer-deps\` is not set, then _any_ + conflicting \`peerDependencies\` will be treated as an install failure, + even if npm could reasonably guess the appropriate resolution based on + non-peer dependency relationships. + + By default, conflicting \`peerDependencies\` deep in the dependency graph + will be resolved using the nearest non-peer dependency specification, + even if doing so will result in some packages receiving a peer dependency + outside the range set in their package's \`peerDependencies\` object. + + When such and override is performed, a warning is printed, explaining the + conflict and the packages involved. If \`--strict-peer-deps\` is set, + then this warning is treated as a failure. + `, + flatten, +}) + +define('strict-ssl', { + default: true, + type: Boolean, + description: ` + Whether or not to do SSL key validation when making requests to the + registry via https. + + See also the \`ca\` config. + `, + flatten (key, obj, flatOptions) { + flatOptions.strictSSL = obj[key] + }, +}) + +define('tag', { + default: 'latest', + type: String, + description: ` + If you ask npm to install a package and don't tell it a specific version, + then it will install the specified tag. + + Also the tag that is added to the package@version specified by the \`npm + tag\` command, if no explicit tag is given. + `, + flatten (key, obj, flatOptions) { + flatOptions.defaultTag = obj[key] + }, +}) + +define('tag-version-prefix', { + default: 'v', + type: String, + description: ` + If set, alters the prefix used when tagging a new version when performing + a version increment using \`npm-version\`. To remove the prefix + altogether, set it to the empty string: \`""\`. + + Because other tools may rely on the convention that npm version tags look + like \`v1.0.0\`, _only use this property if it is absolutely necessary_. + In particular, use care when overriding this setting for public packages. + `, + flatten, +}) + +define('timing', { + default: false, + type: Boolean, + description: ` + If true, writes an \`npm-debug\` log to \`_logs\` and timing information + to \`_timing.json\`, both in your cache, even if the command completes + successfully. \`_timing.json\` is a newline delimited list of JSON + objects. + + You can quickly view it with this [json](https://npm.im/json) command + line: \`npm exec -- json -g < ~/.npm/_timing.json\`. + `, +}) + +define('tmp', { + default: tmpdir(), + defaultDescription: ` + The value returned by the Node.js \`os.tmpdir()\` method + <https://nodejs.org/api/os.html#os_os_tmpdir> + `, + type: path, + deprecated: ` + This setting is no longer used. npm stores temporary files in a special + location in the cache, and they are managed by + [\`cacache\`](http://npm.im/cacache). + `, + description: ` + Historically, the location where temporary files were stored. No longer + relevant. + `, +}) + +define('umask', { + default: 0, + type: Umask, + description: ` + The "umask" value to use when setting the file creation mode on files and + folders. + + Folders and executables are given a mode which is \`0o777\` masked + against this value. Other files are given a mode which is \`0o666\` + masked against this value. + + Note that the underlying system will _also_ apply its own umask value to + files and folders that are created, and npm does not circumvent this, but + rather adds the \`--umask\` config to it. + + Thus, the effective default umask value on most POSIX systems is 0o22, + meaning that folders and executables are created with a mode of 0o755 and + other files are created with a mode of 0o644. + `, + flatten, +}) + +define('unicode', { + default: unicode, + defaultDescription: ` + false on windows, true on mac/unix systems with a unicode locale, as + defined by the LC_ALL, LC_CTYPE, or LANG environment variables. + `, + type: Boolean, + description: ` + When set to true, npm uses unicode characters in the tree output. When + false, it uses ascii characters instead of unicode glyphs. + `, +}) + +define('update-notifier', { + default: true, + type: Boolean, + description: ` + Set to false to suppress the update notification when using an older + version of npm than the latest. + `, +}) + +define('usage', { + default: false, + type: Boolean, + short: ['?', 'H', 'h'], + description: ` + Show short usage output about the command specified. + `, +}) + +define('user-agent', { + default: 'npm/{npm-version} ' + + 'node/{node-version} ' + + '{platform} ' + + '{arch} ' + + '{ci}', + type: String, + description: ` + Sets the User-Agent request header. The following fields are replaced + with their actual counterparts: + + * \`{npm-version}\` - The npm version in use + * \`{node-version}\` - The Node.js version in use + * \`{platform}\` - The value of \`process.platform\` + * \`{arch}\` - The value of \`process.arch\` + * \`{ci}\` - The value of the \`ci-name\` config, if set, prefixed with + \`ci/\`, or an empty string if \`ci-name\` is empty. + `, + flatten (key, obj, flatOptions) { + const value = obj[key] + const ciName = obj['ci-name'] + flatOptions.userAgent = + value.replace(/\{node-version\}/gi, obj['node-version']) + .replace(/\{npm-version\}/gi, obj['npm-version']) + .replace(/\{platform\}/gi, process.platform) + .replace(/\{arch\}/gi, process.arch) + .replace(/\{ci\}/gi, ciName ? `ci/${ciName}` : '') + .trim() + }, +}) + +define('userconfig', { + default: '~/.npmrc', + type: path, + description: ` + The location of user-level configuration settings. + + This may be overridden by the \`npm_config_userconfig\` environment + variable or the \`--userconfig\` command line option, but may _not_ + be overridden by settings in the \`globalconfig\` file. + `, +}) + +define('version', { + default: false, + type: Boolean, + short: 'v', + description: ` + If true, output the npm version and exit successfully. + + Only relevant when specified explicitly on the command line. + `, +}) + +define('versions', { + default: false, + type: Boolean, + description: ` + If true, output the npm version as well as node's \`process.versions\` + map and the version in the current working directory's \`package.json\` + file if one exists, and exit successfully. + + Only relevant when specified explicitly on the command line. + `, +}) + +define('viewer', { + default: isWindows ? 'browser' : 'man', + defaultDescription: ` + "man" on Posix, "browser" on Windows + `, + type: String, + description: ` + The program to use to view help content. + + Set to \`"browser"\` to view html help content in the default web browser. + `, +}) + +define('which', { + default: null, + hint: '<fundingSourceNumber>', + type: [null, Number], + description: ` + If there are multiple funding sources, which 1-indexed source URL to open. + `, +}) + +define('workspace', { + default: [], + type: [String, Array], + short: 'w', + description: ` + Enable running a command in the context of the configured workspaces of the + current project while filtering by running only the workspaces defined by + this configuration option. + + Valid values for the \`workspace\` config are either: + - Workspace names + - Path to a workspace directory + - Path to a parent workspace directory (will result to selecting all of the + nested workspaces) + `, +}) + +define('workspaces', { + default: false, + type: Boolean, + short: 'ws', + description: ` + Enable running a command in the context of **all** the configured + workspaces. + `, +}) + +define('yes', { + default: null, + type: [null, Boolean], + short: 'y', + description: ` + Automatically answer "yes" to any prompts that npm might print on + the command line. + `, +}) diff --git a/deps/npm/lib/utils/config/describe-all.js b/deps/npm/lib/utils/config/describe-all.js new file mode 100644 index 0000000000..ab3f3a63ea --- /dev/null +++ b/deps/npm/lib/utils/config/describe-all.js @@ -0,0 +1,16 @@ +const definitions = require('./definitions.js') +const describeAll = () => { + // sort not-deprecated ones to the top + /* istanbul ignore next - typically already sorted in the definitions file, + * but this is here so that our help doc will stay consistent if we decide + * to move them around. */ + const sort = ([keya, {deprecated: depa}], [keyb, {deprecated: depb}]) => { + return depa && !depb ? 1 + : !depa && depb ? -1 + : keya.localeCompare(keyb) + } + return Object.entries(definitions).sort(sort) + .map(([key, def]) => def.describe()) + .join('\n\n') +} +module.exports = describeAll diff --git a/deps/npm/lib/utils/config/flatten.js b/deps/npm/lib/utils/config/flatten.js new file mode 100644 index 0000000000..f6d6124bdd --- /dev/null +++ b/deps/npm/lib/utils/config/flatten.js @@ -0,0 +1,32 @@ +// use the defined flattening function, and copy over any scoped +// registries and registry-specific "nerfdart" configs verbatim +// +// TODO: make these getters so that we only have to make dirty +// the thing that changed, and then flatten the fields that +// could have changed when a config.set is called. +// +// TODO: move nerfdart auth stuff into a nested object that +// is only passed along to paths that end up calling npm-registry-fetch. +const definitions = require('./definitions.js') +const flatten = (obj, flat = {}) => { + for (const [key, val] of Object.entries(obj)) { + const def = definitions[key] + if (def && def.flatten) + def.flatten(key, obj, flat) + else if (/@.*:registry$/i.test(key) || /^\/\//.test(key)) + flat[key] = val + } + + // XXX make this the bin/npm-cli.js file explicitly instead + // otherwise using npm programmatically is a bit of a pain. + flat.npmBin = require.main ? require.main.filename + : /* istanbul ignore next - not configurable property */ undefined + flat.nodeBin = process.env.NODE || process.execPath + + // XXX should this be sha512? is it even relevant? + flat.hashAlgorithm = 'sha1' + + return flat +} + +module.exports = flatten diff --git a/deps/npm/lib/utils/config/index.js b/deps/npm/lib/utils/config/index.js new file mode 100644 index 0000000000..a24f586524 --- /dev/null +++ b/deps/npm/lib/utils/config/index.js @@ -0,0 +1,52 @@ +const flatten = require('./flatten.js') +const definitions = require('./definitions.js') +const describeAll = require('./describe-all.js') + +// aliases where they get expanded into a completely different thing +// these are NOT supported in the environment or npmrc files, only +// expanded on the CLI. +// TODO: when we switch off of nopt, use an arg parser that supports +// more reasonable aliasing and short opts right in the definitions set. +const shorthands = { + 'enjoy-by': ['--before'], + d: ['--loglevel', 'info'], + dd: ['--loglevel', 'verbose'], + ddd: ['--loglevel', 'silly'], + quiet: ['--loglevel', 'warn'], + q: ['--loglevel', 'warn'], + s: ['--loglevel', 'silent'], + silent: ['--loglevel', 'silent'], + verbose: ['--loglevel', 'verbose'], + desc: ['--description'], + help: ['--usage'], + local: ['--no-global'], + n: ['--no-yes'], + no: ['--no-yes'], + porcelain: ['--parseable'], + readonly: ['--read-only'], + reg: ['--registry'], +} + +for (const [key, {short}] of Object.entries(definitions)) { + if (!short) + continue + // can be either an array or string + for (const s of [].concat(short)) + shorthands[s] = [`--${key}`] +} + +module.exports = { + get defaults () { + // NB: 'default' is a reserved word + return Object.entries(definitions).map(([key, { default: def }]) => { + return [key, def] + }).reduce((defaults, [key, def]) => { + defaults[key] = def + return defaults + }, {}) + }, + definitions, + flatten, + shorthands, + describeAll, +} diff --git a/deps/npm/lib/utils/did-you-mean.js b/deps/npm/lib/utils/did-you-mean.js index c2bdf159dd..98133196e3 100644 --- a/deps/npm/lib/utils/did-you-mean.js +++ b/deps/npm/lib/utils/did-you-mean.js @@ -1,12 +1,33 @@ const leven = require('leven') +const readJson = require('read-package-json-fast') +const { cmdList } = require('./cmd-list.js') -const didYouMean = (scmd, commands) => { - const best = commands +const didYouMean = async (npm, path, scmd) => { + const bestCmd = cmdList + .filter(cmd => leven(scmd, cmd) < scmd.length * 0.4 && scmd !== cmd) + .map(str => ` npm ${str} # ${npm.commands[str].description}`) + + const pkg = await readJson(`${path}/package.json`) + const { scripts } = pkg + // We would already be suggesting this in `npm x` so omit them here + const runScripts = ['stop', 'start', 'test', 'restart'] + const bestRun = Object.keys(scripts || {}) + .filter(cmd => leven(scmd, cmd) < scmd.length * 0.4 && + !runScripts.includes(cmd)) + .map(str => ` npm run ${str} # run the "${str}" package script`) + + const { bin } = pkg + const bestBin = Object.keys(bin || {}) .filter(cmd => leven(scmd, cmd) < scmd.length * 0.4) - .map(str => ` ${str}`) - return best.length === 0 ? '' - : best.length === 1 ? `\nDid you mean this?\n${best[0]}` - : `\nDid you mean one of these?\n${best.slice(0, 3).join('\n')}` -} + .map(str => ` npm exec ${str} # run the "${str}" command from either this or a remote npm package`) + const best = [...bestCmd, ...bestRun, ...bestBin] + + if (best.length === 0) + return '' + + const suggestion = best.length === 1 ? `\n\nDid you mean this?\n${best[0]}` + : `\n\nDid you mean one of these?\n${best.slice(0, 3).join('\n')}` + return suggestion +} module.exports = didYouMean diff --git a/deps/npm/lib/utils/flat-options.js b/deps/npm/lib/utils/flat-options.js deleted file mode 100644 index c082e4137a..0000000000 --- a/deps/npm/lib/utils/flat-options.js +++ /dev/null @@ -1,254 +0,0 @@ -// return a flattened config object with canonical names suitable for -// passing to dependencies like arborist, pacote, npm-registry-fetch, etc. - -const log = require('npmlog') -const crypto = require('crypto') -const querystring = require('querystring') -const npmSession = crypto.randomBytes(8).toString('hex') -log.verbose('npm-session', npmSession) -const { join } = require('path') - -const buildOmitList = obj => { - const include = obj.include || [] - const omit = new Set((obj.omit || []) - .filter(type => !include.includes(type))) - const only = obj.only - - if (/^prod(uction)?$/.test(only) || obj.production) - omit.add('dev') - - if (/dev/.test(obj.also)) - omit.delete('dev') - - if (obj.dev) - omit.delete('dev') - - if (obj.optional === false) - omit.add('optional') - - obj.omit = [...omit] - - // it would perhaps make more sense to put this in @npmcli/config, but - // since we can set dev to be omitted in multiple various legacy ways, - // it's better to set it here once it's all resolved. - if (obj.omit.includes('dev')) - process.env.NODE_ENV = 'production' - - return [...omit] -} - -// turn an object with npm-config style keys into an options object -// with camelCase values. This doesn't account for the stuff that is -// not pulled from the config keys, that's all handled only for the -// main function which acts on the npm object itself. Used by the -// flatOptions generator, and by the publishConfig handling logic. -const flatten = obj => ({ - includeStaged: obj['include-staged'], - preferDedupe: obj['prefer-dedupe'], - ignoreScripts: obj['ignore-scripts'], - nodeVersion: obj['node-version'], - cache: join(obj.cache, '_cacache'), - global: obj.global, - - registry: obj.registry, - scope: obj.scope, - access: obj.access, - 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'], - before: obj.before, - browser: obj.browser, - ca: obj.ca, - cafile: obj.cafile, - cert: obj.cert, - key: obj.key, - - // token creation options - cidr: obj.cidr, - readOnly: obj['read-only'], - - // npm version options - preid: obj.preid, - tagVersionPrefix: obj['tag-version-prefix'], - allowSameVersion: obj['allow-same-version'], - - // npm version git options - message: obj.message, - commitHooks: obj['commit-hooks'], - gitTagVersion: obj['git-tag-version'], - signGitCommit: obj['sign-git-commit'], - signGitTag: obj['sign-git-tag'], - - // only used for npm ls in v7, not update - depth: obj.depth, - all: obj.all, - - // Output configs - unicode: obj.unicode, - json: obj.json, - long: obj.long, - parseable: obj.parseable, - - // options for npm search - search: { - description: obj.description, - exclude: obj.searchexclude, - limit: obj.searchlimit || 20, - opts: querystring.parse(obj.searchopts), - staleness: obj.searchstaleness, - }, - - diff: obj.diff, - diffUnified: obj['diff-unified'], - diffIgnoreAllSpace: obj['diff-ignore-all-space'], - diffNameOnly: obj['diff-name-only'], - diffNoPrefix: obj['diff-no-prefix'], - diffSrcPrefix: obj['diff-src-prefix'], - diffDstPrefix: obj['diff-dst-prefix'], - diffText: obj['diff-text'], - - dryRun: obj['dry-run'], - engineStrict: obj['engine-strict'], - - retry: { - retries: obj['fetch-retries'], - factor: obj['fetch-retry-factor'], - maxTimeout: obj['fetch-retry-maxtimeout'], - minTimeout: obj['fetch-retry-mintimeout'], - }, - - timeout: obj['fetch-timeout'], - - force: obj.force, - - formatPackageLock: obj['format-package-lock'], - fund: obj.fund, - - // binary locators - git: obj.git, - viewer: obj.viewer, - editor: obj.editor, - - // configs that affect how we build trees - binLinks: obj['bin-links'], - rebuildBundle: obj['rebuild-bundle'], - // --no-shrinkwrap is the same as --no-package-lock - packageLock: !(obj['package-lock'] === false || - obj.shrinkwrap === false), - packageLockOnly: obj['package-lock-only'], - globalStyle: obj['global-style'], - legacyBundling: obj['legacy-bundling'], - foregroundScripts: !!obj['foreground-scripts'], - scriptShell: obj['script-shell'] || undefined, - shell: obj.shell, - omit: buildOmitList(obj), - legacyPeerDeps: obj['legacy-peer-deps'], - strictPeerDeps: obj['strict-peer-deps'], - - // npx stuff - call: obj.call, - package: obj.package, - - // used to build up the appropriate {add:{...}} options to Arborist.reify - save: obj.save, - saveBundle: obj['save-bundle'] && !obj['save-peer'], - saveType: obj['save-optional'] && obj['save-peer'] - ? 'peerOptional' - : obj['save-optional'] ? 'optional' - : obj['save-dev'] ? 'dev' - : obj['save-peer'] ? 'peer' - : obj['save-prod'] ? 'prod' - : null, - savePrefix: obj['save-exact'] ? '' - : obj['save-prefix'], - - // configs for npm-registry-fetch - otp: obj.otp, - offline: obj.offline, - preferOffline: getPreferOffline(obj), - preferOnline: getPreferOnline(obj), - strictSSL: obj['strict-ssl'], - defaultTag: obj.tag, - userAgent: obj['user-agent'], - - // yes, it's fine, just do it, jeez, stop asking - yes: obj.yes, - - ...getScopesAndAuths(obj), - - // npm fund exclusive option to select an item from a funding list - which: obj.which, - - // socks proxy can be configured in https-proxy or proxy field - // note that the various (HTTPS_|HTTP_|]PROXY environs will be - // respected if this is not set. - proxy: obj['https-proxy'] || obj.proxy, - noProxy: obj.noproxy, -}) - -const flatOptions = npm => npm.flatOptions || Object.freeze({ - // flatten the config object - ...flatten(npm.config.list[0]), - - // Note that many of these do not come from configs or cli flags - // per se, though they may be implied or defined by them. - log, - npmSession, - dmode: npm.modes.exec, - fmode: npm.modes.file, - umask: npm.modes.umask, - hashAlgorithm: 'sha1', // XXX should this be sha512? - color: !!npm.color, - projectScope: npm.projectScope, - npmVersion: npm.version, - - // npm.command is not set until AFTER flatOptions are defined - // so we need to make this a getter. - get npmCommand () { - return npm.command - }, - - tmp: npm.tmp, - prefix: npm.prefix, - globalPrefix: npm.globalPrefix, - localPrefix: npm.localPrefix, - npmBin: require.main && require.main.filename, - nodeBin: process.env.NODE || process.execPath, - get tag () { - return npm.config.get('tag') - }, -}) - -const getPreferOnline = obj => { - const po = obj['prefer-online'] - if (po !== undefined) - return po - - return obj['cache-max'] <= 0 -} - -const getPreferOffline = obj => { - const po = obj['prefer-offline'] - if (po !== undefined) - return po - - return obj['cache-min'] >= 9999 -} - -// pull out all the @scope:<key> and //host:key config fields -// these are used by npm-registry-fetch for authing against registries -const getScopesAndAuths = obj => { - const scopesAndAuths = {} - // pull out all the @scope:... configs into a flat object. - for (const key in obj) { - if (/@.*:registry$/i.test(key) || /^\/\//.test(key)) - scopesAndAuths[key] = obj[key] - } - return scopesAndAuths -} - -module.exports = Object.assign(flatOptions, { flatten }) diff --git a/deps/npm/lib/utils/lifecycle-cmd.js b/deps/npm/lib/utils/lifecycle-cmd.js index 1917bef367..2c5b89dfcd 100644 --- a/deps/npm/lib/utils/lifecycle-cmd.js +++ b/deps/npm/lib/utils/lifecycle-cmd.js @@ -10,5 +10,9 @@ class LifecycleCmd extends BaseCommand { exec (args, cb) { this.npm.commands['run-script']([this.constructor.name, ...args], cb) } + + execWorkspaces (args, filters, cb) { + this.npm.commands['run-script']([this.constructor.name, ...args], cb) + } } module.exports = LifecycleCmd diff --git a/deps/npm/lib/utils/npm-usage.js b/deps/npm/lib/utils/npm-usage.js index b77bca7bec..bc397cb4d9 100644 --- a/deps/npm/lib/utils/npm-usage.js +++ b/deps/npm/lib/utils/npm-usage.js @@ -1,14 +1,12 @@ -const didYouMean = require('./did-you-mean.js') const { dirname } = require('path') const { cmdList } = require('./cmd-list') -module.exports = (npm, valid = true) => { - npm.config.set('loglevel', 'silent') +module.exports = (npm) => { const usesBrowser = npm.config.get('viewer') === 'browser' ? ' (in a browser)' : '' - npm.log.level = 'silent' - npm.output(` -Usage: npm <command> + return `npm <command> + +Usage: npm install install all the dependencies in your project npm install <foo> add the <foo> dependency to your project @@ -20,7 +18,7 @@ npm help <term> search for help on <term>${usesBrowser} npm help npm more involved overview${usesBrowser} All commands: -${npm.config.get('long') ? usages(npm) : ('\n ' + wrap(cmdList))} +${allCommands(npm)} Specify configs in the ini-formatted file: ${npm.config.get('userconfig')} @@ -29,14 +27,13 @@ or on the command line via: npm <command> --key=value More configuration info: npm help config Configuration fields: npm help 7 config -npm@${npm.version} ${dirname(dirname(__dirname))} -`) - - if (npm.argv.length >= 1) - npm.output(didYouMean(npm.argv[0], cmdList)) +npm@${npm.version} ${dirname(dirname(__dirname))}` +} - if (!valid) - process.exitCode = 1 +const allCommands = (npm) => { + if (npm.config.get('long')) + return usages(npm) + return ('\n ' + wrap(cmdList)) } const wrap = (arr) => { diff --git a/deps/npm/lib/utils/ping.js b/deps/npm/lib/utils/ping.js index f5f7fcc6a6..00956d0c16 100644 --- a/deps/npm/lib/utils/ping.js +++ b/deps/npm/lib/utils/ping.js @@ -1,7 +1,7 @@ // ping the npm registry // used by the ping and doctor commands const fetch = require('npm-registry-fetch') -module.exports = async (opts) => { - const res = await fetch('/-/ping?write=true', opts) +module.exports = async (flatOptions) => { + const res = await fetch('/-/ping?write=true', flatOptions) return res.json().catch(() => ({})) } diff --git a/deps/npm/lib/utils/read-local-package.js b/deps/npm/lib/utils/read-local-package.js index c31bca9947..21506ca180 100644 --- a/deps/npm/lib/utils/read-local-package.js +++ b/deps/npm/lib/utils/read-local-package.js @@ -1,11 +1,12 @@ const { resolve } = require('path') const readJson = require('read-package-json-fast') async function readLocalPackageName (npm) { - if (npm.flatOptions.global) + if (npm.config.get('global')) return - const filepath = resolve(npm.flatOptions.prefix, 'package.json') - return (await readJson(filepath)).name + const filepath = resolve(npm.prefix, 'package.json') + const json = await readJson(filepath) + return json.name } module.exports = readLocalPackageName diff --git a/deps/npm/lib/version.js b/deps/npm/lib/version.js index 2eda9d11b7..18b7d7d6c5 100644 --- a/deps/npm/lib/version.js +++ b/deps/npm/lib/version.js @@ -2,6 +2,10 @@ const libversion = require('libnpmversion') const BaseCommand = require('./base-command.js') class Version extends BaseCommand { + static get description () { + return 'Bump a package version' + } + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'version' @@ -45,7 +49,7 @@ class Version extends BaseCommand { } async change (args) { - const prefix = this.npm.flatOptions.tagVersionPrefix + const prefix = this.npm.config.get('tag-version-prefix') const version = await libversion(args[0], { ...this.npm.flatOptions, path: this.npm.prefix, @@ -71,7 +75,7 @@ class Version extends BaseCommand { for (const [key, version] of Object.entries(process.versions)) results[key] = version - if (this.npm.flatOptions.json) + if (this.npm.config.get('json')) this.npm.output(JSON.stringify(results, null, 2)) else this.npm.output(results) diff --git a/deps/npm/lib/view.js b/deps/npm/lib/view.js index 0a6688fc2b..e0df1e231f 100644 --- a/deps/npm/lib/view.js +++ b/deps/npm/lib/view.js @@ -20,6 +20,11 @@ const readJson = async file => jsonParse(await readFile(file, 'utf8')) const BaseCommand = require('./base-command.js') class View extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get description () { + return 'View registry info' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ static get name () { return 'view' } @@ -41,9 +46,9 @@ class View extends BaseCommand { fullMetadata: true, preferOnline: true, } - const { defaultTag } = config const spec = npa(opts.conf.argv.remain[2]) const pckmnt = await packument(spec, config) + const defaultTag = this.npm.config.get('tag') const dv = pckmnt.versions[pckmnt['dist-tags'][defaultTag]] pckmnt.versions = Object.keys(pckmnt.versions).sort(semver.compareLoose) @@ -99,7 +104,7 @@ class View extends BaseCommand { const name = nv.name const local = (name === '.' || !name) - if (opts.global && local) + if (this.npm.config.get('global') && local) throw new Error('Cannot use view command in global mode.') if (local) { @@ -114,7 +119,7 @@ class View extends BaseCommand { } // get the data about this package - let version = nv.rawSpec || this.npm.flatOptions.defaultTag + let version = nv.rawSpec || this.npm.config.get('tag') const pckmnt = await packument(nv, opts) @@ -159,42 +164,43 @@ class View extends BaseCommand { } if ( - !opts.json && + !this.npm.config.get('json') && args.length === 1 && args[0] === '' ) { // general view pckmnt.version = version await Promise.all( - results.map((v) => this.prettyView(pckmnt, v[Object.keys(v)[0]][''], opts)) + results.map((v) => this.prettyView(pckmnt, v[Object.keys(v)[0]][''])) ) return retval } else { // view by field name - await this.printData(retval, pckmnt._id, opts) + await this.printData(retval, pckmnt._id) return retval } } - async printData (data, name, opts) { + async printData (data, name) { const versions = Object.keys(data) let msg = '' let msgJson = [] const includeVersions = versions.length > 1 let includeFields + const json = this.npm.config.get('json') versions.forEach((v) => { const fields = Object.keys(data[v]) includeFields = includeFields || (fields.length > 1) - if (opts.json) + if (json) msgJson.push({}) fields.forEach((f) => { let d = cleanup(data[v][f]) - if (fields.length === 1 && opts.json) + if (fields.length === 1 && json) msgJson[msgJson.length - 1][f] = d if (includeVersions || includeFields || typeof d !== 'string') { - if (opts.json) + if (json) msgJson[msgJson.length - 1][f] = d else { d = inspect(d, { @@ -204,10 +210,10 @@ class View extends BaseCommand { maxArrayLength: null, }) } - } else if (typeof d === 'string' && opts.json) + } else if (typeof d === 'string' && json) d = JSON.stringify(d) - if (!opts.json) { + if (!json) { if (f && includeFields) f += ' = ' msg += (includeVersions ? name + '@' + v + ' ' : '') + @@ -216,7 +222,7 @@ class View extends BaseCommand { }) }) - if (opts.json) { + if (json) { if (msgJson.length && Object.keys(msgJson[0]).length === 1) { const k = Object.keys(msgJson[0])[0] msgJson = msgJson.map(m => m[k]) @@ -236,9 +242,9 @@ class View extends BaseCommand { console.log(msg.trim()) } - async prettyView (packument, manifest, opts) { + async prettyView (packument, manifest) { // More modern, pretty printing of default view - const unicode = opts.unicode + const unicode = this.npm.config.get('unicode') const tags = [] Object.keys(packument['dist-tags']).forEach((t) => { diff --git a/deps/npm/lib/whoami.js b/deps/npm/lib/whoami.js index 2322c5fd80..82c4520d9e 100644 --- a/deps/npm/lib/whoami.js +++ b/deps/npm/lib/whoami.js @@ -3,18 +3,18 @@ const getIdentity = require('./utils/get-identity.js') const BaseCommand = require('./base-command.js') class Whoami extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ - static get name () { - return 'whoami' + static get description () { + return 'Display npm username' } /* istanbul ignore next - see test/lib/load-all-commands.js */ - static get description () { - return 'prints username according to given registry' + static get name () { + return 'whoami' } /* istanbul ignore next - see test/lib/load-all-commands.js */ - static get usage () { - return ['[--registry <registry>]'] + static get params () { + return ['registry'] } exec (args, cb) { @@ -22,9 +22,10 @@ class Whoami extends BaseCommand { } async whoami (args) { - const opts = this.npm.flatOptions - const username = await getIdentity(this.npm, opts) - this.npm.output(opts.json ? JSON.stringify(username) : username) + const username = await getIdentity(this.npm, this.npm.flatOptions) + this.npm.output( + this.npm.config.get('json') ? JSON.stringify(username) : username + ) } } module.exports = Whoami diff --git a/deps/npm/lib/workspaces/get-workspaces.js b/deps/npm/lib/workspaces/get-workspaces.js new file mode 100644 index 0000000000..64812d5403 --- /dev/null +++ b/deps/npm/lib/workspaces/get-workspaces.js @@ -0,0 +1,33 @@ +const { resolve } = require('path') +const mapWorkspaces = require('@npmcli/map-workspaces') +const minimatch = require('minimatch') +const rpj = require('read-package-json-fast') + +const getWorkspaces = async (filters, { path }) => { + const pkg = await rpj(resolve(path, 'package.json')) + const workspaces = await mapWorkspaces({ cwd: path, pkg }) + const res = filters.length ? new Map() : workspaces + + for (const filterArg of filters) { + for (const [workspaceName, workspacePath] of workspaces.entries()) { + if (filterArg === workspaceName + || resolve(path, filterArg) === workspacePath + || minimatch(workspacePath, `${resolve(path, filterArg)}/*`)) + res.set(workspaceName, workspacePath) + } + } + + if (!res.size) { + let msg = '!' + if (filters.length) { + msg = `:\n ${filters.reduce( + (res, filterArg) => `${res} --workspace=${filterArg}`, '')}` + } + + throw new Error(`No workspaces found${msg}`) + } + + return res +} + +module.exports = getWorkspaces diff --git a/deps/npm/man/man1/npm-adduser.1 b/deps/npm/man/man1/npm-adduser.1 index f690c1f53d..0701a16aeb 100644 --- a/deps/npm/man/man1/npm-adduser.1 +++ b/deps/npm/man/man1/npm-adduser.1 @@ -10,6 +10,8 @@ npm adduser [\-\-registry=url] [\-\-scope=@orgname] [\-\-always\-auth] [\-\-auth aliases: login, add\-user .fi .RE +.P +Note: This command is unaware of workspaces\. .SS Description .P Create or verify a user named \fB<username>\fP in the specified registry, and diff --git a/deps/npm/man/man1/npm-bin.1 b/deps/npm/man/man1/npm-bin.1 index cf1692e894..d8dfc0542c 100644 --- a/deps/npm/man/man1/npm-bin.1 +++ b/deps/npm/man/man1/npm-bin.1 @@ -8,6 +8,8 @@ npm bin [\-g|\-\-global] .fi .RE +.P +Note: This command is unaware of workspaces\. .SS Description .P Print the folder where npm will install executables\. diff --git a/deps/npm/man/man1/npm-cache.1 b/deps/npm/man/man1/npm-cache.1 index 4f0b0f19fc..852c24a13d 100644 --- a/deps/npm/man/man1/npm-cache.1 +++ b/deps/npm/man/man1/npm-cache.1 @@ -16,6 +16,8 @@ aliases: npm cache clear, npm cache rm npm cache verify .fi .RE +.P +Note: This command is unaware of workspaces\. .SS Description .P Used to add, list, or clean the npm cache folder\. diff --git a/deps/npm/man/man1/npm-completion.1 b/deps/npm/man/man1/npm-completion.1 index bc206f5242..5be583ea68 100644 --- a/deps/npm/man/man1/npm-completion.1 +++ b/deps/npm/man/man1/npm-completion.1 @@ -8,6 +8,8 @@ source <(npm completion) .fi .RE +.P +Note: This command is unaware of workspaces\. .SS Description .P Enables tab\-completion in all npm commands\. diff --git a/deps/npm/man/man1/npm-config.1 b/deps/npm/man/man1/npm-config.1 index 3e29c71f50..f47947aff1 100644 --- a/deps/npm/man/man1/npm-config.1 +++ b/deps/npm/man/man1/npm-config.1 @@ -16,6 +16,8 @@ npm get [<key> [<key> \.\.\.]] alias: c .fi .RE +.P +Note: This command is unaware of workspaces\. .SS Description .P npm gets its config settings from the command line, environment diff --git a/deps/npm/man/man1/npm-dedupe.1 b/deps/npm/man/man1/npm-dedupe.1 index 70267ff45e..915b7b110c 100644 --- a/deps/npm/man/man1/npm-dedupe.1 +++ b/deps/npm/man/man1/npm-dedupe.1 @@ -1,6 +1,6 @@ .TH "NPM\-DEDUPE" "1" "March 2021" "" "" .SH "NAME" -\fBnpm-dedupe\fR \- Reduce duplication +\fBnpm-dedupe\fR \- Reduce duplication in the package tree .SS Synopsis .P .RS 2 @@ -8,7 +8,7 @@ npm dedupe npm ddp -aliases: find\-dupes, ddp +aliases: ddp .fi .RE .SS Description @@ -78,6 +78,8 @@ Using \fBnpm find\-dupes\fP will run the command in \fB\-\-dry\-run\fP mode\. .SS See Also .RS 0 .IP \(bu 2 +npm find\-dupes \fI/cli\-commands/find\-dupes\fR +.IP \(bu 2 npm ls \fI/cli\-commands/ls\fR .IP \(bu 2 npm update \fI/cli\-commands/update\fR diff --git a/deps/npm/man/man1/npm-deprecate.1 b/deps/npm/man/man1/npm-deprecate.1 index fa95af0a85..3d8876662f 100644 --- a/deps/npm/man/man1/npm-deprecate.1 +++ b/deps/npm/man/man1/npm-deprecate.1 @@ -8,6 +8,8 @@ npm deprecate <pkg>[@<version range>] <message> .fi .RE +.P +Note: This command is unaware of workspaces\. .SS Description .P This command will update the npm registry entry for a package, providing a diff --git a/deps/npm/man/man1/npm-doctor.1 b/deps/npm/man/man1/npm-doctor.1 index c45944c2b3..c317f03fae 100644 --- a/deps/npm/man/man1/npm-doctor.1 +++ b/deps/npm/man/man1/npm-doctor.1 @@ -8,6 +8,8 @@ npm doctor .fi .RE +.P +Note: This command is unaware of workspaces\. .SS Description .P \fBnpm doctor\fP runs a set of checks to ensure that your npm installation has diff --git a/deps/npm/man/man1/npm-edit.1 b/deps/npm/man/man1/npm-edit.1 index 3c8d1ecd10..d0461afc8f 100644 --- a/deps/npm/man/man1/npm-edit.1 +++ b/deps/npm/man/man1/npm-edit.1 @@ -8,6 +8,8 @@ npm edit <pkg> .fi .RE +.P +Note: This command is unaware of workspaces\. .SS Description .P Selects a dependency in the current project and opens the package folder in diff --git a/deps/npm/man/man1/npm-exec.1 b/deps/npm/man/man1/npm-exec.1 index 9b21bfe438..a9d9708c70 100644 --- a/deps/npm/man/man1/npm-exec.1 +++ b/deps/npm/man/man1/npm-exec.1 @@ -9,6 +9,7 @@ npm exec \-\- <pkg>[@<version>] [args\.\.\.] npm exec \-\-package=<pkg>[@<version>] \-\- <cmd> [args\.\.\.] npm exec \-c '<cmd> [args\.\.\.]' npm exec \-\-package=foo \-c '<cmd> [args\.\.\.]' +npm exec [\-ws] [\-w <workspace\-name] [args\.\.\.] npx <pkg>[@<specifier>] [args\.\.\.] npx \-p <pkg>[@<specifier>] <cmd> [args\.\.\.] @@ -161,6 +162,76 @@ $ npm x \-c 'eslint && say "hooray, lint passed"' $ npx \-c 'eslint && say "hooray, lint passed"' .fi .RE +.SS Workspaces support +.P +You may use the \fBworkspace\fP or \fBworkspaces\fP configs in order to run an +arbitrary command from an npm package (either one installed locally, or fetched +remotely) in the context of the specified workspaces\. +If no positional argument or \fB\-\-call\fP option is provided, it will open an +interactive subshell in the context of each of these configured workspaces one +at a time\. +.P +Given a project with configured workspaces, e\.g: +.P +.RS 2 +.nf +\|\. ++\-\- package\.json +`\-\- packages + +\-\- a + | `\-\- package\.json + +\-\- b + | `\-\- package\.json + `\-\- c + `\-\- package\.json +.fi +.RE +.P +Assuming the workspace configuration is properly set up at the root level +\fBpackage\.json\fP file\. e\.g: +.P +.RS 2 +.nf +{ + "workspaces": [ "\./packages/*" ] +} +.fi +.RE +.P +You can execute an arbitrary command from a package in the context of each of +the configured workspaces when using the \fBworkspaces\fP configuration options, +in this example we're using \fBeslint\fR to lint any js file found within each +workspace folder: +.P +.RS 2 +.nf +npm exec \-ws \-\- eslint \./*\.js +.fi +.RE +.SS Filtering workspaces +.P +It's also possible to execute a command in a single workspace using the +\fBworkspace\fP config along with a name or directory path: +.P +.RS 2 +.nf +npm exec \-\-workspace=a \-\- eslint \./*\.js +.fi +.RE +.P +The \fBworkspace\fP config can also be specified multiple times in order to run a +specific script in the context of multiple workspaces\. When defining values for +the \fBworkspace\fP config in the command line, it also possible to use \fB\-w\fP as a +shorthand, e\.g: +.P +.RS 2 +.nf +npm exec \-w a \-w b \-\- eslint \./*\.js +.fi +.RE +.P +This last command will run the \fBeslint\fP command in both \fB\|\./packages/a\fP and +\fB\|\./packages/b\fP folders\. .SS Compatibility with Older npx Versions .P The \fBnpx\fP binary was rewritten in npm v7\.0\.0, and the standalone \fBnpx\fP @@ -218,6 +289,44 @@ requested from the server\. To force full offline mode, use \fBoffline\fP\|\. .P Forces full offline mode\. Any packages not locally cached will result in an error\. +.SS workspace +.RS 0 +.IP \(bu 2 +Alias: \fB\-w\fP +.IP \(bu 2 +Type: Array +.IP \(bu 2 +Default: \fB[]\fP + +.RE +.P +Enable running scripts in the context of workspaces while also filtering by +the provided names or paths provided\. +.P +Valid values for the \fBworkspace\fP config are either: +.RS 0 +.IP \(bu 2 +Workspace names +.IP \(bu 2 +Path to a workspace directory +.IP \(bu 2 +Path to a parent workspace directory (will result to selecting all of the +children workspaces) + +.RE +.SS workspaces +.RS 0 +.IP \(bu 2 +Alias: \fB\-ws\fP +.IP \(bu 2 +Type: Boolean +.IP \(bu 2 +Default: \fBfalse\fP + +.RE +.P +Run scripts in the context of all configured workspaces for the current +project\. .SS See Also .RS 0 .IP \(bu 2 diff --git a/deps/npm/man/man1/npm-explore.1 b/deps/npm/man/man1/npm-explore.1 index 6b04f3be33..3a0711e00c 100644 --- a/deps/npm/man/man1/npm-explore.1 +++ b/deps/npm/man/man1/npm-explore.1 @@ -8,6 +8,8 @@ npm explore <pkg> [ \-\- <command>] .fi .RE +.P +Note: This command is unaware of workspaces\. .SS Description .P Spawn a subshell in the directory of the installed package specified\. diff --git a/deps/npm/man/man1/npm-find-dupes.1 b/deps/npm/man/man1/npm-find-dupes.1 new file mode 100644 index 0000000000..6ecb4b90d5 --- /dev/null +++ b/deps/npm/man/man1/npm-find-dupes.1 @@ -0,0 +1,26 @@ +.TH "NPM\-FIND\-DUPES" "1" "March 2021" "" "" +.SH "NAME" +\fBnpm-find-dupes\fR \- Find duplication in the package tree +.SS Synopsis +.P +.RS 2 +.nf +npm find\-dupes +.fi +.RE +.SS Description +.P +Runs \fBnpm dedupe\fP in \fB\-\-dry\-run\fP mode, making npm only output the +duplications, without actually changing the package tree\. +.SS See Also +.RS 0 +.IP \(bu 2 +npm dedupe \fI/cli\-commands/dedupe\fR +.IP \(bu 2 +npm ls \fI/cli\-commands/ls\fR +.IP \(bu 2 +npm update \fI/cli\-commands/update\fR +.IP \(bu 2 +npm install \fI/cli\-commands/install\fR + +.RE diff --git a/deps/npm/man/man1/npm-help-search.1 b/deps/npm/man/man1/npm-help-search.1 index e0dc5419d3..1a33f080d6 100644 --- a/deps/npm/man/man1/npm-help-search.1 +++ b/deps/npm/man/man1/npm-help-search.1 @@ -8,6 +8,8 @@ npm help\-search <text> .fi .RE +.P +Note: This command is unaware of workspaces\. .SS Description .P This command will search the npm markdown documentation files for the terms diff --git a/deps/npm/man/man1/npm-help.1 b/deps/npm/man/man1/npm-help.1 index 6e0ad91a66..f6ca3a84a2 100644 --- a/deps/npm/man/man1/npm-help.1 +++ b/deps/npm/man/man1/npm-help.1 @@ -8,6 +8,8 @@ npm help <term> [<terms\.\.>] .fi .RE +.P +Note: This command is unaware of workspaces\. .SS Description .P If supplied a topic, then show the appropriate documentation page\. diff --git a/deps/npm/man/man1/npm-hook.1 b/deps/npm/man/man1/npm-hook.1 index f92de18130..f4f2b39762 100644 --- a/deps/npm/man/man1/npm-hook.1 +++ b/deps/npm/man/man1/npm-hook.1 @@ -11,6 +11,8 @@ npm hook update <id> <url> [secret] npm hook rm <id> .fi .RE +.P +Note: This command is unaware of workspaces\. .SS Description .P Allows you to manage npm diff --git a/deps/npm/man/man1/npm-init.1 b/deps/npm/man/man1/npm-init.1 index 05aa13f013..b67899ce80 100644 --- a/deps/npm/man/man1/npm-init.1 +++ b/deps/npm/man/man1/npm-init.1 @@ -1,6 +1,6 @@ .TH "NPM\-INIT" "1" "March 2021" "" "" .SH "NAME" -\fBnpm-init\fR \- create a package\.json file +\fBnpm-init\fR \- Create a package\.json file .SS Synopsis .P .RS 2 diff --git a/deps/npm/man/man1/npm-logout.1 b/deps/npm/man/man1/npm-logout.1 index 777467cbe2..a917137bcb 100644 --- a/deps/npm/man/man1/npm-logout.1 +++ b/deps/npm/man/man1/npm-logout.1 @@ -8,6 +8,8 @@ npm logout [\-\-registry=<url>] [\-\-scope=<@scope>] .fi .RE +.P +Note: This command is unaware of workspaces\. .SS Description .P When logged into a registry that supports token\-based authentication, tell diff --git a/deps/npm/man/man1/npm-ls.1 b/deps/npm/man/man1/npm-ls.1 index c427b6b780..84bd11f2d8 100644 --- a/deps/npm/man/man1/npm-ls.1 +++ b/deps/npm/man/man1/npm-ls.1 @@ -26,7 +26,7 @@ example, running \fBnpm ls promzard\fP in npm's source tree will show: .P .RS 2 .nf -npm@7\.6\.3 /path/to/npm +npm@7\.7\.0 /path/to/npm └─┬ init\-package\-json@0\.0\.4 └── promzard@0\.1\.5 .fi diff --git a/deps/npm/man/man1/npm-org.1 b/deps/npm/man/man1/npm-org.1 index 27f3fab580..cb65355572 100644 --- a/deps/npm/man/man1/npm-org.1 +++ b/deps/npm/man/man1/npm-org.1 @@ -10,6 +10,8 @@ npm org rm <orgname> <username> npm org ls <orgname> [<username>] .fi .RE +.P +Note: This command is unaware of workspaces\. .SS Example .P Add a new developer to an org: diff --git a/deps/npm/man/man1/npm-owner.1 b/deps/npm/man/man1/npm-owner.1 index bd0758d701..cbd61fd925 100644 --- a/deps/npm/man/man1/npm-owner.1 +++ b/deps/npm/man/man1/npm-owner.1 @@ -12,6 +12,8 @@ npm owner ls [<@scope>/]<pkg> aliases: author .fi .RE +.P +Note: This command is unaware of workspaces\. .SS Description .P Manage ownership of published packages\. diff --git a/deps/npm/man/man1/npm-ping.1 b/deps/npm/man/man1/npm-ping.1 index 9357497758..fa9a2f1ff5 100644 --- a/deps/npm/man/man1/npm-ping.1 +++ b/deps/npm/man/man1/npm-ping.1 @@ -8,6 +8,8 @@ npm ping [\-\-registry <registry>] .fi .RE +.P +Note: This command is unaware of workspaces\. .SS Description .P Ping the configured or given npm registry and verify authentication\. diff --git a/deps/npm/man/man1/npm-prefix.1 b/deps/npm/man/man1/npm-prefix.1 index 85178a2c06..c0685305ca 100644 --- a/deps/npm/man/man1/npm-prefix.1 +++ b/deps/npm/man/man1/npm-prefix.1 @@ -8,6 +8,8 @@ npm prefix [\-g] .fi .RE +.P +Note: This command is unaware of workspaces\. .SS Description .P Print the local prefix to standard output\. This is the closest parent directory diff --git a/deps/npm/man/man1/npm-profile.1 b/deps/npm/man/man1/npm-profile.1 index 470b8eaf71..f17ad46563 100644 --- a/deps/npm/man/man1/npm-profile.1 +++ b/deps/npm/man/man1/npm-profile.1 @@ -12,6 +12,8 @@ npm profile enable\-2fa [auth\-and\-writes|auth\-only] npm profile disable\-2fa .fi .RE +.P +Note: This command is unaware of workspaces\. .SS Description .P Change your profile information on the registry\. Note that this command diff --git a/deps/npm/man/man1/npm-run-script.1 b/deps/npm/man/man1/npm-run-script.1 index e19a4c08ab..b399e5d9d1 100644 --- a/deps/npm/man/man1/npm-run-script.1 +++ b/deps/npm/man/man1/npm-run-script.1 @@ -6,6 +6,8 @@ .RS 2 .nf npm run\-script <command> [\-\-if\-present] [\-\-silent] [\-\- <args>] +npm run\-script <command> [\-\-workspace=<workspace\-name>] +npm run\-script <command> [\-\-workspaces] aliases: run, rum, urn .fi @@ -81,6 +83,72 @@ found in the \fBPATH\fP\|\. If you try to run a script without having a \fBnode_modules\fP directory and it fails, you will be given a warning to run \fBnpm install\fP, just in case you've forgotten\. +.SS Workspaces support +.P +You may use the \fBworkspace\fP or \fBworkspaces\fP configs in order to run an +arbitrary command from a package's \fB"scripts"\fP object in the context of the +specified workspaces\. If no \fB"command"\fP is provided, it will list the available +scripts for each of these configured workspaces\. +.P +Given a project with configured workspaces, e\.g: +.P +.RS 2 +.nf +\|\. ++\-\- package\.json +`\-\- packages + +\-\- a + | `\-\- package\.json + +\-\- b + | `\-\- package\.json + `\-\- c + `\-\- package\.json +.fi +.RE +.P +Assuming the workspace configuration is properly set up at the root level +\fBpackage\.json\fP file\. e\.g: +.P +.RS 2 +.nf +{ + "workspaces": [ "\./packages/*" ] +} +.fi +.RE +.P +And that each of the configured workspaces has a configured \fBtest\fP script, +we can run tests in all of them using the \fBworkspaces\fP config: +.P +.RS 2 +.nf +npm test \-\-workspaces +.fi +.RE +.SS Filtering workspaces +.P +It's also possible to run a script in a single workspace using the \fBworkspace\fP +config along with a name or directory path: +.P +.RS 2 +.nf +npm test \-\-workspace=a +.fi +.RE +.P +The \fBworkspace\fP config can also be specified multiple times in order to run a +specific script in the context of multiple workspaces\. When defining values for +the \fBworkspace\fP config in the command line, it also possible to use \fB\-w\fP as a +shorthand, e\.g: +.P +.RS 2 +.nf +npm test \-w a \-w b +.fi +.RE +.P +This last command will run \fBtest\fP in both \fB\|\./packages/a\fP and \fB\|\./packages/b\fP +packages\. .SS Configuration .SS if\-present .RS 0 @@ -125,6 +193,44 @@ Default: false .RE .P You can use the \fB\-\-silent\fP flag to prevent showing \fBnpm ERR!\fP output on error\. +.SS workspace +.RS 0 +.IP \(bu 2 +Alias: \fB\-w\fP +.IP \(bu 2 +Type: Array +.IP \(bu 2 +Default: \fB[]\fP + +.RE +.P +Enable running scripts in the context of workspaces while also filtering by +the provided names or paths provided\. +.P +Valid values for the \fBworkspace\fP config are either: +.RS 0 +.IP \(bu 2 +Workspace names +.IP \(bu 2 +Path to a workspace directory +.IP \(bu 2 +Path to a parent workspace directory (will result to selecting all of the +children workspaces) + +.RE +.SS workspaces +.RS 0 +.IP \(bu 2 +Alias: \fB\-ws\fP +.IP \(bu 2 +Type: Boolean +.IP \(bu 2 +Default: \fBfalse\fP + +.RE +.P +Run scripts in the context of all configured workspaces for the current +project\. .SS See Also .RS 0 .IP \(bu 2 diff --git a/deps/npm/man/man1/npm-search.1 b/deps/npm/man/man1/npm-search.1 index 3dd493edb3..8253e86dca 100644 --- a/deps/npm/man/man1/npm-search.1 +++ b/deps/npm/man/man1/npm-search.1 @@ -10,6 +10,8 @@ npm search [\-l|\-\-long] [\-\-json] [\-\-parseable] [\-\-no\-description] [sear aliases: s, se, find .fi .RE +.P +Note: This command is unaware of workspaces\. .SS Description .P Search the registry for packages matching the search terms\. \fBnpm search\fP diff --git a/deps/npm/man/man1/npm-shrinkwrap.1 b/deps/npm/man/man1/npm-shrinkwrap.1 index 75b4d3e2f7..7800d2f53e 100644 --- a/deps/npm/man/man1/npm-shrinkwrap.1 +++ b/deps/npm/man/man1/npm-shrinkwrap.1 @@ -8,6 +8,8 @@ npm shrinkwrap .fi .RE +.P +Note: This command is unaware of workspaces\. .SS Description .P This command repurposes \fBpackage\-lock\.json\fP into a publishable diff --git a/deps/npm/man/man1/npm-star.1 b/deps/npm/man/man1/npm-star.1 index 8fdb41e9d5..5bd9d6a250 100644 --- a/deps/npm/man/man1/npm-star.1 +++ b/deps/npm/man/man1/npm-star.1 @@ -8,6 +8,8 @@ npm star [<pkg>\.\.\.] .fi .RE +.P +Note: This command is unaware of workspaces\. .SS Description .P "Starring" a package means that you have some interest in it\. It's diff --git a/deps/npm/man/man1/npm-stars.1 b/deps/npm/man/man1/npm-stars.1 index 4d0d3d5fcc..8e5f7b3b78 100644 --- a/deps/npm/man/man1/npm-stars.1 +++ b/deps/npm/man/man1/npm-stars.1 @@ -8,6 +8,8 @@ npm stars [<user>] .fi .RE +.P +Note: This command is unaware of workspaces\. .SS Description .P If you have starred a lot of neat things and want to find them again diff --git a/deps/npm/man/man1/npm-team.1 b/deps/npm/man/man1/npm-team.1 index 3331bb1b41..82f5ab3be7 100644 --- a/deps/npm/man/man1/npm-team.1 +++ b/deps/npm/man/man1/npm-team.1 @@ -14,6 +14,8 @@ npm team rm <scope:team> <user> npm team ls <scope>|<scope:team> .fi .RE +.P +Note: This command is unaware of workspaces\. .SS Description .P Used to manage teams in organizations, and change team memberships\. Does not diff --git a/deps/npm/man/man1/npm-token.1 b/deps/npm/man/man1/npm-token.1 index 1da8ce9f71..f98f37e6eb 100644 --- a/deps/npm/man/man1/npm-token.1 +++ b/deps/npm/man/man1/npm-token.1 @@ -10,6 +10,8 @@ npm token revoke <id|token> .fi .RE +.P +Note: This command is unaware of workspaces\. .SS Description .P This lets you list, create and revoke authentication tokens\. diff --git a/deps/npm/man/man1/npm-unstar.1 b/deps/npm/man/man1/npm-unstar.1 index a08ab4c5af..b3b7c698b3 100644 --- a/deps/npm/man/man1/npm-unstar.1 +++ b/deps/npm/man/man1/npm-unstar.1 @@ -8,6 +8,8 @@ npm unstar [<pkg>\.\.\.] .fi .RE +.P +Note: This command is unaware of workspaces\. .SS Description .P "Unstarring" a package is the opposite of npm help \fBstar\fP, diff --git a/deps/npm/man/man1/npm-whoami.1 b/deps/npm/man/man1/npm-whoami.1 index 6ade4045c0..3df11cb69d 100644 --- a/deps/npm/man/man1/npm-whoami.1 +++ b/deps/npm/man/man1/npm-whoami.1 @@ -8,6 +8,8 @@ npm whoami [\-\-registry <registry>] .fi .RE +.P +Note: This command is unaware of workspaces\. .SS Description .P Print the \fBusername\fP config to standard output\. diff --git a/deps/npm/man/man1/npm.1 b/deps/npm/man/man1/npm.1 index c85c4759dc..9b3b58ce87 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\.6\.3 +7\.7\.0 .SS Description .P npm is the package manager for the Node JavaScript platform\. It puts diff --git a/deps/npm/man/man5/package-json.5 b/deps/npm/man/man5/package-json.5 index a244fa7e4d..859c3de2d5 100644 --- a/deps/npm/man/man5/package-json.5 +++ b/deps/npm/man/man5/package-json.5 @@ -373,6 +373,8 @@ This should be a module relative to the root of your package folder\. .P For most modules, it makes the most sense to have a main script and often not much else\. +.P +If \fBmain\fP is not set it defaults to \fBindex\.js\fP in the packages root folder\. .SS browser .P If your module is meant to be used client\-side the browser field should be @@ -620,8 +622,7 @@ tarball or git URL\. \fBPlease do not put test harnesses or transpilers or other "development" time tools in your \fBdependencies\fP object\.\fR See \fBdevDependencies\fP, below\. .P -See semver \fI[/using\-npm/semver](https://github\.com/npm/node\-semver#versions)\fR -for more details about specifying version ranges\. +See npm help semver for more details about specifying version ranges\. .RS 0 .IP \(bu 2 \fBversion\fP Must match \fBversion\fP exactly diff --git a/deps/npm/man/man7/config.7 b/deps/npm/man/man7/config.7 index 6e826d0787..a5f3095bcb 100644 --- a/deps/npm/man/man7/config.7 +++ b/deps/npm/man/man7/config.7 @@ -56,57 +56,89 @@ internal to npm, and are defaults if nothing else is specified\. .SS Shorthands and Other CLI Niceties .P The following shorthands are parsed on the command\-line: +<!\-\- AUTOGENERATED CONFIG SHORTHANDS START \-\-> +<!\-\- automatically generated, do not edit manually \-\-> .RS 0 .IP \(bu 2 -\fB\-v\fP: \fB\-\-version\fP +\fB\-a\fP: \fB\-\-all\fP +.IP \(bu 2 +\fB\-\-enjoy\-by\fP: \fB\-\-before\fP .IP \(bu 2 -\fB\-h\fP, \fB\-?\fP, \fB\-\-help\fP, \fB\-H\fP: \fB\-\-usage\fP +\fB\-c\fP: \fB\-\-call\fP .IP \(bu 2 -\fB\-s\fP, \fB\-\-silent\fP: \fB\-\-loglevel silent\fP +\fB\-\-desc\fP: \fB\-\-description\fP .IP \(bu 2 -\fB\-q\fP, \fB\-\-quiet\fP: \fB\-\-loglevel warn\fP +\fB\-f\fP: \fB\-\-force\fP +.IP \(bu 2 +\fB\-g\fP: \fB\-\-global\fP .IP \(bu 2 \fB\-d\fP: \fB\-\-loglevel info\fP .IP \(bu 2 -\fB\-dd\fP, \fB\-\-verbose\fP: \fB\-\-loglevel verbose\fP +\fB\-s\fP: \fB\-\-loglevel silent\fP .IP \(bu 2 -\fB\-ddd\fP: \fB\-\-loglevel silly\fP +\fB\-\-silent\fP: \fB\-\-loglevel silent\fP .IP \(bu 2 -\fB\-g\fP: \fB\-\-global\fP +\fB\-\-ddd\fP: \fB\-\-loglevel silly\fP .IP \(bu 2 -\fB\-C\fP: \fB\-\-prefix\fP +\fB\-\-dd\fP: \fB\-\-loglevel verbose\fP +.IP \(bu 2 +\fB\-\-verbose\fP: \fB\-\-loglevel verbose\fP +.IP \(bu 2 +\fB\-q\fP: \fB\-\-loglevel warn\fP +.IP \(bu 2 +\fB\-\-quiet\fP: \fB\-\-loglevel warn\fP .IP \(bu 2 \fB\-l\fP: \fB\-\-long\fP .IP \(bu 2 \fB\-m\fP: \fB\-\-message\fP .IP \(bu 2 -\fB\-p\fP, \fB\-\-porcelain\fP: \fB\-\-parseable\fP +\fB\-\-local\fP: \fB\-\-no\-global\fP .IP \(bu 2 -\fB\-reg\fP: \fB\-\-registry\fP +\fB\-n\fP: \fB\-\-no\-yes\fP .IP \(bu 2 -\fB\-f\fP: \fB\-\-force\fP +\fB\-\-no\fP: \fB\-\-no\-yes\fP +.IP \(bu 2 +\fB\-p\fP: \fB\-\-parseable\fP +.IP \(bu 2 +\fB\-\-porcelain\fP: \fB\-\-parseable\fP +.IP \(bu 2 +\fB\-C\fP: \fB\-\-prefix\fP .IP \(bu 2 -\fB\-desc\fP: \fB\-\-description\fP +\fB\-\-readonly\fP: \fB\-\-read\-only\fP +.IP \(bu 2 +\fB\-\-reg\fP: \fB\-\-registry\fP .IP \(bu 2 \fB\-S\fP: \fB\-\-save\fP .IP \(bu 2 -\fB\-P\fP: \fB\-\-save\-prod\fP +\fB\-B\fP: \fB\-\-save\-bundle\fP .IP \(bu 2 \fB\-D\fP: \fB\-\-save\-dev\fP .IP \(bu 2 +\fB\-E\fP: \fB\-\-save\-exact\fP +.IP \(bu 2 \fB\-O\fP: \fB\-\-save\-optional\fP .IP \(bu 2 -\fB\-B\fP: \fB\-\-save\-bundle\fP +\fB\-P\fP: \fB\-\-save\-prod\fP .IP \(bu 2 -\fB\-E\fP: \fB\-\-save\-exact\fP +\fB\-?\fP: \fB\-\-usage\fP .IP \(bu 2 -\fB\-y\fP: \fB\-\-yes\fP +\fB\-h\fP: \fB\-\-usage\fP +.IP \(bu 2 +\fB\-H\fP: \fB\-\-usage\fP +.IP \(bu 2 +\fB\-\-help\fP: \fB\-\-usage\fP +.IP \(bu 2 +\fB\-v\fP: \fB\-\-version\fP .IP \(bu 2 -\fB\-n\fP: \fB\-\-yes false\fP +\fB\-w\fP: \fB\-\-workspace\fP .IP \(bu 2 -\fBll\fP and \fBla\fP commands: \fBls \-\-long\fP +\fB\-\-ws\fP: \fB\-\-workspaces\fP +.IP \(bu 2 +\fB\-y\fP: \fB\-\-yes\fP .RE +<!\-\- AUTOGENERATED CONFIG SHORTHANDS END \-\-> + .P If the specified configuration param resolves unambiguously to a known configuration parameter, then it is expanded to that configuration @@ -133,23 +165,39 @@ npm ls \-\-global \-\-parseable \-\-long \-\-loglevel info .fi .RE .SS Config Settings -.SS access +<!\-\- AUTOGENERATED CONFIG DESCRIPTIONS START \-\-> +<!\-\- automatically generated, do not edit manually \-\-> +.SS \fB_auth\fP .RS 0 .IP \(bu 2 -Default: \fBrestricted\fP +Default: null .IP \(bu 2 -Type: Access +Type: null or String .RE .P -When publishing scoped packages, the access level defaults to \fBrestricted\fP\|\. If -you want your scoped package to be publicly viewable (and installable) set -\fB\-\-access=public\fP\|\. The only valid values for \fBaccess\fP are \fBpublic\fP and +A basic\-auth string to use when authenticating against the npm registry\. +.P +Warning: This should generally not be set via a command\-line option\. It is +safer to use a registry\-provided authentication bearer token stored in the +~/\.npmrc file by running \fBnpm login\fP\|\. +.SS \fBaccess\fP +.RS 0 +.IP \(bu 2 +Default: 'restricted' for scoped packages, 'public' for unscoped packages +.IP \(bu 2 +Type: null, "restricted", or "public" + +.RE +.P +When publishing scoped packages, the access level defaults to \fBrestricted\fP\|\. +If you want your scoped package to be publicly viewable (and installable) +set \fB\-\-access=public\fP\|\. The only valid values for \fBaccess\fP are \fBpublic\fP and \fBrestricted\fP\|\. Unscoped packages \fIalways\fR have an access level of \fBpublic\fP\|\. -.SS all +.SS \fBall\fP .RS 0 .IP \(bu 2 -Default: \fBfalse\fP +Default: false .IP \(bu 2 Type: Boolean @@ -158,7 +206,7 @@ Type: Boolean When running \fBnpm outdated\fP and \fBnpm ls\fP, setting \fB\-\-all\fP will show all outdated or installed packages, rather than only those directly depended upon by the current project\. -.SS allow\-same\-version +.SS \fBallow\-same\-version\fP .RS 0 .IP \(bu 2 Default: false @@ -169,7 +217,7 @@ Type: Boolean .P Prevents throwing an error when \fBnpm version\fP is used to set the new version to the same value as the current version\. -.SS always\-auth +.SS \fBalways\-auth\fP .RS 0 .IP \(bu 2 Default: false @@ -178,20 +226,9 @@ Type: Boolean .RE .P -Force npm to always require authentication when accessing the registry, -even for \fBGET\fP requests\. -.SS also -.RS 0 -.IP \(bu 2 -Default: null -.IP \(bu 2 -Type: String - -.RE -.P -When "dev" or "development" and running local \fBnpm shrinkwrap\fP, -\fBnpm outdated\fP, or \fBnpm update\fP, is an alias for \fB\-\-dev\fP\|\. -.SS audit +Force npm to always require authentication when accessing the registry, even +for \fBGET\fP requests\. +.SS \fBaudit\fP .RS 0 .IP \(bu 2 Default: true @@ -201,53 +238,41 @@ Type: Boolean .RE .P When "true" submit audit reports alongside \fBnpm install\fP runs to the default -registry and all registries configured for scopes\. See the documentation -for npm help \fBaudit\fP for details on what is submitted\. -.SS audit\-level +registry and all registries configured for scopes\. See the documentation for +npm help \fBaudit\fP for details on what is submitted\. +.SS \fBaudit\-level\fP .RS 0 .IP \(bu 2 -Default: \fB"low"\fP -.IP \(bu 2 -Type: \fB\|'low'\fP, \fB\|'moderate'\fP, \fB\|'high'\fP, \fB\|'critical'\fP - -.RE -.P -The minimum level of vulnerability for \fBnpm audit\fP to exit with -a non\-zero exit code\. -.SS auth\-type -.RS 0 -.IP \(bu 2 -Default: \fB\|'legacy'\fP +Default: null .IP \(bu 2 -Type: \fB\|'legacy'\fP, \fB\|'sso'\fP, \fB\|'saml'\fP, \fB\|'oauth'\fP +Type: "low", "moderate", "high", "critical", "none", or null .RE .P -What authentication strategy to use with \fBadduser\fP/\fBlogin\fP\|\. -.SS before +The minimum level of vulnerability for \fBnpm audit\fP to exit with a non\-zero +exit code\. +.SS \fBbefore\fP .RS 0 .IP \(bu 2 -Alias: enjoy\-by -.IP \(bu 2 Default: null .IP \(bu 2 -Type: Date +Type: null or Date .RE .P -If passed to \fBnpm install\fP, will rebuild the npm tree such that only versions -that were available \fBon or before\fR the \fB\-\-before\fP time get installed\. -If there's no versions available for the current set of direct dependencies, the -command will error\. +If passed to \fBnpm install\fP, will rebuild the npm tree such that only +versions that were available \fBon or before\fR the \fB\-\-before\fP time get +installed\. If there's no versions available for the current set of direct +dependencies, the command will error\. .P If the requested version is a \fBdist\-tag\fP and the given tag does not pass the -\fB\-\-before\fP filter, the most recent version less than or equal to that tag will -be used\. For example, \fBfoo@latest\fP might install \fBfoo@1\.2\fP even though \fBlatest\fP -is \fB2\.0\fP\|\. -.SS bin\-links +\fB\-\-before\fP filter, the most recent version less than or equal to that tag +will be used\. For example, \fBfoo@latest\fP might install \fBfoo@1\.2\fP even though +\fBlatest\fP is \fB2\.0\fP\|\. +.SS \fBbin\-links\fP .RS 0 .IP \(bu 2 -Default: \fBtrue\fP +Default: true .IP \(bu 2 Type: Boolean @@ -256,15 +281,15 @@ Type: Boolean Tells npm to create symlinks (or \fB\|\.cmd\fP shims on Windows) for package executables\. .P -Set to false to have it not do this\. This can be used to work around -the fact that some file systems don't support symlinks, even on -ostensibly Unix systems\. -.SS browser +Set to false to have it not do this\. This can be used to work around the +fact that some file systems don't support symlinks, even on ostensibly Unix +systems\. +.SS \fBbrowser\fP .RS 0 .IP \(bu 2 Default: OS X: \fB"open"\fP, Windows: \fB"start"\fP, Others: \fB"xdg\-open"\fP .IP \(bu 2 -Type: String or Boolean +Type: null, Boolean, or String .RE .P @@ -274,18 +299,19 @@ Set to \fBfalse\fP to suppress browser behavior and instead print urls to terminal\. .P Set to \fBtrue\fP to use default system URL opener\. -.SS ca +.SS \fBca\fP .RS 0 .IP \(bu 2 -Default: The npm CA certificate +Default: null .IP \(bu 2 -Type: String, Array or null +Type: null or String (can be set multiple times) .RE .P The Certificate Authority signing certificate that is trusted for SSL -connections to the registry\. Values should be in PEM format (Windows calls it "Base\-64 encoded X\.509 (\.CER)") with newlines -replaced by the string "\\n"\. For example: +connections to the registry\. Values should be in PEM format (Windows calls +it "Base\-64 encoded X\.509 (\.CER)") with newlines replaced by the string +"\\n"\. For example: .P .RS 2 .nf @@ -293,8 +319,8 @@ ca="\-\-\-\-\-BEGIN CERTIFICATE\-\-\-\-\-\\nXXXX\\nXXXX\\n\-\-\-\-\-END CERTIFIC .fi .RE .P -Set to \fBnull\fP to only allow "known" registrars, or to a specific CA cert -to trust only that specific signing authority\. +Set to \fBnull\fP to only allow "known" registrars, or to a specific CA cert to +trust only that specific signing authority\. .P Multiple CAs can be trusted by specifying an array of certificates: .P @@ -306,175 +332,166 @@ ca[]="\.\.\." .RE .P See also the \fBstrict\-ssl\fP config\. -.SS cafile +.SS \fBcache\fP .RS 0 .IP \(bu 2 -Default: \fBnull\fP +Default: Windows: \fB%LocalAppData%\\npm\-cache\fP, Posix: \fB~/\.npm\fP .IP \(bu 2 -Type: path +Type: Path .RE .P -A path to a file containing one or multiple Certificate Authority signing -certificates\. Similar to the \fBca\fP setting, but allows for multiple CA's, as -well as for the CA information to be stored in a file on disk\. -.SS cache +The location of npm's cache directory\. See npm help \fBnpm +cache\fP +.SS \fBcafile\fP .RS 0 .IP \(bu 2 -Default: Windows: \fB%AppData%\\npm\-cache\fP, Posix: \fB~/\.npm\fP +Default: null .IP \(bu 2 -Type: path +Type: Path .RE .P -The location of npm's cache directory\. See npm help \fBcache\fP -.SS cache\-lock\-stale +A path to a file containing one or multiple Certificate Authority signing +certificates\. Similar to the \fBca\fP setting, but allows for multiple CA's, as +well as for the CA information to be stored in a file on disk\. +.SS \fBcall\fP .RS 0 .IP \(bu 2 -Default: 60000 (1 minute) +Default: "" .IP \(bu 2 -Type: Number +Type: String .RE .P -The number of ms before cache folder lockfiles are considered stale\. -.SS cache\-lock\-retries +Optional companion option for \fBnpm exec\fP, \fBnpx\fP that allows for specifying a +custom command to be run along with the installed packages\. +.P +.RS 2 +.nf +npm exec \-\-package yo \-\-package generator\-node \-\-call "yo node" +.fi +.RE +.SS \fBcert\fP .RS 0 .IP \(bu 2 -Default: 10 +Default: null .IP \(bu 2 -Type: Number +Type: null or String .RE .P -Number of times to retry to acquire a lock on cache folder lockfiles\. -.SS cache\-lock\-wait -.RS 0 -.IP \(bu 2 -Default: 10000 (10 seconds) -.IP \(bu 2 -Type: Number - +A client certificate to pass when accessing the registry\. Values should be +in PEM format (Windows calls it "Base\-64 encoded X\.509 (\.CER)") with +newlines replaced by the string "\\n"\. For example: +.P +.RS 2 +.nf +cert="\-\-\-\-\-BEGIN CERTIFICATE\-\-\-\-\-\\nXXXX\\nXXXX\\n\-\-\-\-\-END CERTIFICATE\-\-\-\-\-" +.fi .RE .P -Number of ms to wait for cache lock files to expire\. -.SS cache\-max +It is \fInot\fR the path to a certificate file (and there is no "certfile" +option)\. +.SS \fBci\-name\fP .RS 0 .IP \(bu 2 -Default: Infinity +Default: The name of the current CI system, or \fBnull\fP when not on a known CI +platform\. .IP \(bu 2 -Type: Number +Type: null or String .RE .P -\fBDEPRECATED\fR: This option has been deprecated in favor of \fB\-\-prefer\-online\fP\|\. -.P -\fB\-\-cache\-max=0\fP is an alias for \fB\-\-prefer\-online\fP\|\. -.SS cache\-min +The name of a continuous integration system\. If not set explicitly, npm will +detect the current CI environment using the +\fB@npmcli/ci\-detect\fP \fIhttp://npm\.im/@npmcli/ci\-detect\fR module\. +.SS \fBcidr\fP .RS 0 .IP \(bu 2 -Default: 10 +Default: null .IP \(bu 2 -Type: Number +Type: null or String (can be set multiple times) .RE .P -\fBDEPRECATED\fR: This option has been deprecated in favor of \fB\-\-prefer\-offline\fP\|\. -.P -\fB\-\-cache\-min=9999 (or bigger)\fP is an alias for \fB\-\-prefer\-offline\fP\|\. -.SS call +This is a list of CIDR address to be used when configuring limited access +tokens with the \fBnpm token create\fP command\. +.SS \fBcolor\fP .RS 0 .IP \(bu 2 -Default: "" +Default: true unless the NO_COLOR environ is set to something other than '0' .IP \(bu 2 -Type: String +Type: "always" or Boolean .RE .P -Optional companion option for \fBnpm exec\fP, \fBnpx\fP that allows for specifying a -custom command to be run along with the installed packages\. -.P -.RS 2 -.nf -npm exec \-\-package yo \-\-package generator\-node \-\-call "yo node" -.fi -.RE -.SS cert +If false, never shows colors\. If \fB"always"\fP then always shows colors\. If +true, then only prints color codes for tty file descriptors\. +.SS \fBcommit\-hooks\fP .RS 0 .IP \(bu 2 -Default: \fBnull\fP +Default: true .IP \(bu 2 -Type: String +Type: Boolean .RE .P -A client certificate to pass when accessing the registry\. Values should be in -PEM format (Windows calls it "Base\-64 encoded X\.509 (\.CER)") with newlines replaced by the string "\\n"\. For example: -.P -.RS 2 -.nf -cert="\-\-\-\-\-BEGIN CERTIFICATE\-\-\-\-\-\\nXXXX\\nXXXX\\n\-\-\-\-\-END CERTIFICATE\-\-\-\-\-" -.fi -.RE -.P -It is \fInot\fR the path to a certificate file (and there is no "certfile" option)\. -.SS cidr +Run git commit hooks when using the \fBnpm version\fP command\. +.SS \fBdepth\fP .RS 0 .IP \(bu 2 -Default: \fBnull\fP +Default: \fBInfinity\fP if \fB\-\-all\fP is set, otherwise \fB1\fP .IP \(bu 2 -Type: String, Array, null +Type: null or Number .RE .P -This is a list of CIDR address to be used when configuring limited access tokens with the \fBnpm token create\fP command\. -.SS commit\-hooks +The depth to go when recursing packages for \fBnpm ls\fP\|\. +.P +If not set, \fBnpm ls\fP will show only the immediate dependencies of the root +project\. If \fB\-\-all\fP is set, then npm will show all dependencies by default\. +.SS \fBdescription\fP .RS 0 .IP \(bu 2 -Default: \fBtrue\fP +Default: true .IP \(bu 2 Type: Boolean .RE .P -Run git commit hooks when using the \fBnpm version\fP command\. -.SS color +Show the description in \fBnpm search\fP +.SS \fBdiff\fP .RS 0 .IP \(bu 2 -Default: true +Default: .IP \(bu 2 -Type: Boolean or \fB"always"\fP +Type: String (can be set multiple times) .RE .P -If false, never shows colors\. If \fB"always"\fP then always shows colors\. -If true, then only prints color codes for tty file descriptors\. -.P -This option can also be changed using the environment: colors are -disabled when the environment variable \fBNO_COLOR\fP is set to any value\. -.SS depth +Define arguments to compare in \fBnpm diff\fP\|\. +.SS \fBdiff\-dst\-prefix\fP .RS 0 .IP \(bu 2 -Default: null +Default: "b/" .IP \(bu 2 -Type: null or Number +Type: String .RE .P -The depth to go when recursing packages for \fBnpm ls\fP\|\. -.P -To make this default to \fBInfinity\fP instead of \fBnull\fP, set \fB\-\-all\fP\|\. -.SS description +Destination prefix to be used in \fBnpm diff\fP output\. +.SS \fBdiff\-ignore\-all\-space\fP .RS 0 .IP \(bu 2 -Default: true +Default: false .IP \(bu 2 Type: Boolean .RE .P -Show the description in \fBnpm search\fP -.SS dev +Ignore whitespace when comparing lines in \fBnpm diff\fP\|\. +.SS \fBdiff\-name\-only\fP .RS 0 .IP \(bu 2 Default: false @@ -483,8 +500,8 @@ Type: Boolean .RE .P -[Deprecated] Install \fBdev\-dependencies\fP along with packages\. -.SS dry\-run +Prints only filenames when using \fBnpm diff\fP\|\. +.SS \fBdiff\-no\-prefix\fP .RS 0 .IP \(bu 2 Default: false @@ -493,22 +510,21 @@ Type: Boolean .RE .P -Indicates that you don't want npm to make any changes and that it should -only report what it would have done\. This can be passed into any of the -commands that modify your local installation, eg, \fBinstall\fP, \fBupdate\fP, -\fBdedupe\fP, \fBuninstall\fP\|\. This is NOT currently honored by some network related -commands, eg \fBdist\-tags\fP, \fBowner\fP, etc\. -.SS diff +Do not show any source or destination prefix in \fBnpm diff\fP output\. +.P +Note: this causes \fBnpm diff\fP to ignore the \fB\-\-diff\-src\-prefix\fP and +\fB\-\-diff\-dst\-prefix\fP configs\. +.SS \fBdiff\-src\-prefix\fP .RS 0 .IP \(bu 2 -Default: null +Default: "a/" .IP \(bu 2 -Type: String, Array, null +Type: String .RE .P -Define arguments to compare in \fBnpm diff\fP\|\. -.SS diff\-name\-only +Source prefix to be used in \fBnpm diff\fP output\. +.SS \fBdiff\-text\fP .RS 0 .IP \(bu 2 Default: false @@ -517,93 +533,115 @@ Type: Boolean .RE .P -Prints only filenames when using \fBnpm diff\fP\|\. -.SS diff\-unified +Treat all files as text in \fBnpm diff\fP\|\. +.SS \fBdiff\-unified\fP .RS 0 .IP \(bu 2 -Type: number +Default: 3 .IP \(bu 2 -Default: \fB3\fP +Type: Number .RE .P The number of lines of context to print in \fBnpm diff\fP\|\. -.SS diff\-ignore\-all\-space +.SS \fBdry\-run\fP .RS 0 .IP \(bu 2 -Type: Boolean -.IP \(bu 2 Default: false +.IP \(bu 2 +Type: Boolean .RE .P -Ignore whitespace when comparing lines in `npm diff\. -.SS diff\-no\-prefix +Indicates that you don't want npm to make any changes and that it should +only report what it would have done\. This can be passed into any of the +commands that modify your local installation, eg, \fBinstall\fP, \fBupdate\fP, +\fBdedupe\fP, \fBuninstall\fP, as well as \fBpack\fP and \fBpublish\fP\|\. +.P +Note: This is NOT honored by other network related commands, eg \fBdist\-tags\fP, +\fBowner\fP, etc\. +.SS \fBeditor\fP .RS 0 .IP \(bu 2 -Type: Boolean +Default: The EDITOR or VISUAL environment variables, or 'notepad\.exe' on +Windows, or 'vim' on Unix systems .IP \(bu 2 -Default: false +Type: String .RE .P -Do not show any source or destination prefix in \fBnpm diff\fP output\. -.SS diff\-src\-prefix +The command to run for \fBnpm edit\fP and \fBnpm config edit\fP\|\. +.SS \fBengine\-strict\fP .RS 0 .IP \(bu 2 -Type: String +Default: false .IP \(bu 2 -Default: \fB"a/"\fP +Type: Boolean .RE .P -Source prefix to be used in \fBnpm diff\fP output\. -.SS diff\-dst\-prefix +If set to true, then npm will stubbornly refuse to install (or even consider +installing) any package that claims to not be compatible with the current +Node\.js version\. +.P +This can be overridden by setting the \fB\-\-force\fP flag\. +.SS \fBfetch\-retries\fP .RS 0 .IP \(bu 2 -Type: String +Default: 2 .IP \(bu 2 -Default: \fB"b/"\fP +Type: Number .RE .P -Destination prefix to be used in \fBnpm diff\fP output\. -.SS diff\-text +The "retries" config for the \fBretry\fP module to use when fetching packages +from the registry\. +.P +npm will retry idempotent read requests to the registry in the case of +network failures or 5xx HTTP errors\. +.SS \fBfetch\-retry\-factor\fP .RS 0 .IP \(bu 2 -Alias: \fB\-a\fP +Default: 10 .IP \(bu 2 -Type: Boolean +Type: Number + +.RE +.P +The "factor" config for the \fBretry\fP module to use when fetching packages\. +.SS \fBfetch\-retry\-maxtimeout\fP +.RS 0 .IP \(bu 2 -Default: false +Default: 60000 (1 minute) +.IP \(bu 2 +Type: Number .RE .P -Treat all files as text in \fBnpm diff\fP\|\. -.SS editor +The "maxTimeout" config for the \fBretry\fP module to use when fetching +packages\. +.SS \fBfetch\-retry\-mintimeout\fP .RS 0 .IP \(bu 2 -Default: \fBEDITOR\fP environment variable if set, or \fB"vi"\fP on Posix, -or \fB"notepad"\fP on Windows\. +Default: 10000 (10 seconds) .IP \(bu 2 -Type: path +Type: Number .RE .P -The command to run for \fBnpm edit\fP or \fBnpm config edit\fP\|\. -.SS engine\-strict +The "minTimeout" config for the \fBretry\fP module to use when fetching +packages\. +.SS \fBfetch\-timeout\fP .RS 0 .IP \(bu 2 -Default: false +Default: 300000 (5 minutes) .IP \(bu 2 -Type: Boolean +Type: Number .RE .P -If set to true, then npm will stubbornly refuse to install (or even -consider installing) any package that claims to not be compatible with -the current Node\.js version\. -.SS force +The maximum amount of time to wait for HTTP requests to complete\. +.SS \fBforce\fP .RS 0 .IP \(bu 2 Default: false @@ -626,13 +664,11 @@ Allow installing packages that have an \fBengines\fP declaration requiring a different version of npm\. .IP \(bu 2 Allow installing packages that have an \fBengines\fP declaration requiring a -different version of \fBnode\fP, even if \fB\-\-engines\-strict\fP is enabled\. +different version of \fBnode\fP, even if \fB\-\-engine\-strict\fP is enabled\. .IP \(bu 2 Allow \fBnpm audit fix\fP to install modules outside your stated dependency range (including SemVer\-major changes)\. .IP \(bu 2 -Allow a module to be installed as a direct dependency of itself\. -.IP \(bu 2 Allow unpublishing all versions of a published package\. .IP \(bu 2 Allow conflicting peerDependencies to be installed in the root project\. @@ -641,7 +677,7 @@ Allow conflicting peerDependencies to be installed in the root project\. .P If you don't have a clear idea of what you want to do, it is strongly recommended that you do not use this option! -.SS foreground\-scripts +.SS \fBforeground\-scripts\fP .RS 0 .IP \(bu 2 Default: false @@ -654,9 +690,9 @@ Run all build scripts (ie, \fBpreinstall\fP, \fBinstall\fP, and \fBpostinstall\f scripts for installed packages in the foreground process, sharing standard input, output, and error with the main npm process\. .P -Note that this will generally make installs run slower, and be much -noisier, but can be useful for debugging\. -.SS format\-package\-lock +Note that this will generally make installs run slower, and be much noisier, +but can be useful for debugging\. +.SS \fBformat\-package\-lock\fP .RS 0 .IP \(bu 2 Default: true @@ -665,8 +701,9 @@ Type: Boolean .RE .P -Format \fBpackage\-lock\.json\fP or \fBnpm\-shrinkwrap\.json\fP as a human readable file\. -.SS fund +Format \fBpackage\-lock\.json\fP or \fBnpm\-shrinkwrap\.json\fP as a human readable +file\. +.SS \fBfund\fP .RS 0 .IP \(bu 2 Default: true @@ -676,85 +713,30 @@ Type: Boolean .RE .P When "true" displays the message at the end of each \fBnpm install\fP -acknowledging the number of dependencies looking for funding\. -See npm help \fBfund\fP for details\. -.SS fetch\-retries -.RS 0 -.IP \(bu 2 -Default: 2 -.IP \(bu 2 -Type: Number - -.RE -.P -The "retries" config for the \fBretry\fP module to use when fetching -packages from the registry\. -.SS fetch\-retry\-factor -.RS 0 -.IP \(bu 2 -Default: 10 -.IP \(bu 2 -Type: Number - -.RE -.P -The "factor" config for the \fBretry\fP module to use when fetching -packages\. -.SS fetch\-retry\-mintimeout -.RS 0 -.IP \(bu 2 -Default: 10000 (10 seconds) -.IP \(bu 2 -Type: Number - -.RE -.P -The "minTimeout" config for the \fBretry\fP module to use when fetching -packages\. -.SS fetch\-retry\-maxtimeout +acknowledging the number of dependencies looking for funding\. See npm help \fBnpm +fund\fP for details\. +.SS \fBgit\fP .RS 0 .IP \(bu 2 -Default: 60000 (1 minute) -.IP \(bu 2 -Type: Number - -.RE -.P -The "maxTimeout" config for the \fBretry\fP module to use when fetching -packages\. -.SS fetch\-timeout -.RS 0 -.IP \(bu 2 -Default: 300000 (5 minutes) -.IP \(bu 2 -Type: Number - -.RE -.P -The maximum amount of time to wait for HTTP requests to complete\. -.SS git -.RS 0 -.IP \(bu 2 -Default: \fB"git"\fP +Default: "git" .IP \(bu 2 Type: String .RE .P -The command to use for git commands\. If git is installed on the -computer, but is not in the \fBPATH\fP, then set this to the full path to -the git binary\. -.SS git\-tag\-version +The command to use for git commands\. If git is installed on the computer, +but is not in the \fBPATH\fP, then set this to the full path to the git binary\. +.SS \fBgit\-tag\-version\fP .RS 0 .IP \(bu 2 -Default: \fBtrue\fP +Default: true .IP \(bu 2 Type: Boolean .RE .P Tag the commit when using the \fBnpm version\fP command\. -.SS global +.SS \fBglobal\fP .RS 0 .IP \(bu 2 Default: false @@ -763,67 +745,69 @@ Type: Boolean .RE .P -Operates in "global" mode, so that packages are installed into the -\fBprefix\fP folder instead of the current working directory\. See +Operates in "global" mode, so that packages are installed into the \fBprefix\fP +folder instead of the current working directory\. See npm help folders for more on the differences in behavior\. .RS 0 .IP \(bu 2 -packages are installed into the \fB{prefix}/lib/node_modules\fP folder, instead of the -current working directory\. +packages are installed into the \fB{prefix}/lib/node_modules\fP folder, instead +of the current working directory\. .IP \(bu 2 bin files are linked to \fB{prefix}/bin\fP .IP \(bu 2 man pages are linked to \fB{prefix}/share/man\fP .RE -.SS globalconfig +.SS \fBglobal\-style\fP .RS 0 .IP \(bu 2 -Default: {prefix}/etc/npmrc +Default: false .IP \(bu 2 -Type: path +Type: Boolean .RE .P -The config file to read for global config options\. -.SS global\-style +Causes npm to install the package into your local \fBnode_modules\fP folder with +the same layout it uses with the global \fBnode_modules\fP folder\. Only your +direct dependencies will show in \fBnode_modules\fP and everything they depend +on will be flattened in their \fBnode_modules\fP folders\. This obviously will +eliminate some deduping\. If used with \fBlegacy\-bundling\fP, \fBlegacy\-bundling\fP +will be preferred\. +.SS \fBglobalconfig\fP .RS 0 .IP \(bu 2 -Default: false +Default: The global \-\-prefix setting plus 'etc/npmrc'\. For example, +\|'/usr/local/etc/npmrc' .IP \(bu 2 -Type: Boolean +Type: Path .RE .P -Causes npm to install the package into your local \fBnode_modules\fP folder with -the same layout it uses with the global \fBnode_modules\fP folder\. Only your -direct dependencies will show in \fBnode_modules\fP and everything they depend -on will be flattened in their \fBnode_modules\fP folders\. This obviously will -eliminate some deduping\. If used with \fBlegacy\-bundling\fP, \fBlegacy\-bundling\fP will be -preferred\. -.SS heading +The config file to read for global config options\. +.SS \fBheading\fP .RS 0 .IP \(bu 2 -Default: \fB"npm"\fP +Default: "npm" .IP \(bu 2 Type: String .RE .P The string that starts all the debugging log output\. -.SS https\-proxy +.SS \fBhttps\-proxy\fP .RS 0 .IP \(bu 2 Default: null .IP \(bu 2 -Type: url +Type: null or URL .RE .P A proxy to use for outgoing https requests\. If the \fBHTTPS_PROXY\fP or \fBhttps_proxy\fP or \fBHTTP_PROXY\fP or \fBhttp_proxy\fP environment variables are set, -proxy settings will be honored by the underlying \fBrequest\fP library\. -.SS if\-present +proxy settings will be honored by the underlying \fBmake\-fetch\-happen\fP +library\. +.SS \fBif\-present\fP .RS 0 .IP \(bu 2 Default: false @@ -832,22 +816,13 @@ Type: Boolean .RE .P -If true, npm will not exit with an error code when \fBrun\-script\fP is invoked for -a script that isn't defined in the \fBscripts\fP section of \fBpackage\.json\fP\|\. This -option can be used when it's desirable to optionally run a script when it's -present and fail if the script fails\. This is useful, for example, when running -scripts that may only apply for some builds in an otherwise generic CI setup\. -.SS ignore\-prepublish -.RS 0 -.IP \(bu 2 -Default: false -.IP \(bu 2 -Type: Boolean - -.RE -.P -If true, npm will not run \fBprepublish\fP scripts\. -.SS ignore\-scripts +If true, npm will not exit with an error code when \fBrun\-script\fP is invoked +for a script that isn't defined in the \fBscripts\fP section of \fBpackage\.json\fP\|\. +This option can be used when it's desirable to optionally run a script when +it's present and fail if the script fails\. This is useful, for example, when +running scripts that may only apply for some builds in an otherwise generic +CI setup\. +.SS \fBignore\-scripts\fP .RS 0 .IP \(bu 2 Default: false @@ -857,72 +832,68 @@ Type: Boolean .RE .P If true, npm does not run scripts specified in package\.json files\. -.SS include +.SS \fBinclude\fP .RS 0 .IP \(bu 2 -Default: \fB[prod|dev|optional|peer]\fP +Default: .IP \(bu 2 -Type: Array +Type: "prod", "dev", "optional", or "peer" (can be set multiple times) .RE .P Option that allows for defining which types of dependencies to install\. -.SS init\-module +.P +This is the inverse of \fB\-\-omit=<type>\fP\|\. +.P +Dependency types specified in \fB\-\-include\fP will not be omitted, regardless of +the order in which omit/include are specified on the command\-line\. +.SS \fBinclude\-staged\fP .RS 0 .IP \(bu 2 -Alias: \fBinit\.module\fP -.IP \(bu 2 -Default: ~/\.npm\-init\.js +Default: false .IP \(bu 2 -Type: path +Type: Boolean .RE .P -A module that will be loaded by the \fBnpm init\fP command\. See the -documentation for the -init\-package\-json \fIhttps://github\.com/npm/init\-package\-json\fR module -for more information, or npm help init\. -.SS init\-author\-name +Allow installing "staged" published packages, as defined by npm RFC PR +#92 \fIhttps://github\.com/npm/rfcs/pull/92\fR\|\. +.P +This is experimental, and not implemented by the npm public registry\. +.SS \fBinit\-author\-email\fP .RS 0 .IP \(bu 2 -Alias: \fBinit\.author\.name\fP -.IP \(bu 2 Default: "" .IP \(bu 2 Type: String .RE .P -The value \fBnpm init\fP should use by default for the package author's name\. -.SS init\-author\-email +The value \fBnpm init\fP should use by default for the package author's email\. +.SS \fBinit\-author\-name\fP .RS 0 .IP \(bu 2 -Alias: \fBinit\.author\.email\fP -.IP \(bu 2 Default: "" .IP \(bu 2 Type: String .RE .P -The value \fBnpm init\fP should use by default for the package author's email\. -.SS init\-author\-url +The value \fBnpm init\fP should use by default for the package author's name\. +.SS \fBinit\-author\-url\fP .RS 0 .IP \(bu 2 -Alias: \fBinit\.author\.url\fP -.IP \(bu 2 Default: "" .IP \(bu 2 -Type: String +Type: "" or URL .RE .P -The value \fBnpm init\fP should use by default for the package author's homepage\. -.SS init\-license +The value \fBnpm init\fP should use by default for the package author's +homepage\. +.SS \fBinit\-license\fP .RS 0 .IP \(bu 2 -Alias: \fBinit\.license\fP -.IP \(bu 2 Default: "ISC" .IP \(bu 2 Type: String @@ -930,20 +901,31 @@ Type: String .RE .P The value \fBnpm init\fP should use by default for the package license\. -.SS init\-version +.SS \fBinit\-module\fP .RS 0 .IP \(bu 2 -Alias: \fBinit\.version\fP +Default: "~/\.npm\-init\.js" +.IP \(bu 2 +Type: Path + +.RE +.P +A module that will be loaded by the \fBnpm init\fP command\. See the +documentation for the +init\-package\-json \fIhttps://github\.com/npm/init\-package\-json\fR module for +more information, or npm help init\. +.SS \fBinit\-version\fP +.RS 0 .IP \(bu 2 Default: "1\.0\.0" .IP \(bu 2 -Type: semver +Type: SemVer string .RE .P -The value that \fBnpm init\fP should use by default for the package -version number, if not already set in package\.json\. -.SS json +The value that \fBnpm init\fP should use by default for the package version +number, if not already set in package\.json\. +.SS \fBjson\fP .RS 0 .IP \(bu 2 Default: false @@ -954,19 +936,20 @@ Type: Boolean .P Whether or not to output JSON data, rather than the normal output\. .P -This feature is currently experimental, and the output data structures for many -commands is either not implemented in JSON yet, or subject to change\. Only the -output from \fBnpm ls \-\-json\fP and \fBnpm search \-\-json\fP are currently valid\. -.SS key +This feature is currently experimental, and the output data structures for +many commands is either not implemented in JSON yet, or subject to change\. +Only the output from \fBnpm ls \-\-json\fP and \fBnpm search \-\-json\fP are currently +valid\. +.SS \fBkey\fP .RS 0 .IP \(bu 2 -Default: \fBnull\fP +Default: null .IP \(bu 2 -Type: String +Type: null or String .RE .P -A client key to pass when accessing the registry\. Values should be in PEM +A client key to pass when accessing the registry\. Values should be in PEM format with newlines replaced by the string "\\n"\. For example: .P .RS 2 @@ -976,7 +959,7 @@ key="\-\-\-\-\-BEGIN PRIVATE KEY\-\-\-\-\-\\nXXXX\\nXXXX\\n\-\-\-\-\-END PRIVATE .RE .P It is \fInot\fR the path to a key file (and there is no "keyfile" option)\. -.SS legacy\-bundling +.SS \fBlegacy\-bundling\fP .RS 0 .IP \(bu 2 Default: false @@ -986,10 +969,10 @@ Type: Boolean .RE .P Causes npm to install the package such that versions of npm prior to 1\.4, -such as the one included with node 0\.8, can install the package\. This +such as the one included with node 0\.8, can install the package\. This eliminates all automatic deduping\. If used with \fBglobal\-style\fP this option will be preferred\. -.SS legacy\-peer\-deps +.SS \fBlegacy\-peer\-deps\fP .RS 0 .IP \(bu 2 Default: false @@ -1001,9 +984,8 @@ Type: Boolean Causes npm to completely ignore \fBpeerDependencies\fP when building a package tree, as in npm versions 3 through 6\. .P -If a package cannot be installed because of overly strict -\fBpeerDependencies\fP that collide, it provides a way to move forward -resolving the situation\. +If a package cannot be installed because of overly strict \fBpeerDependencies\fP +that collide, it provides a way to move forward resolving the situation\. .P This differs from \fB\-\-omit=peer\fP, in that \fB\-\-omit=peer\fP will avoid unpacking \fBpeerDependencies\fP on disk, but will still design a tree such that @@ -1011,7 +993,7 @@ This differs from \fB\-\-omit=peer\fP, in that \fB\-\-omit=peer\fP will avoid un .P Use of \fBlegacy\-peer\-deps\fP is not recommended, as it will not enforce the \fBpeerDependencies\fP contract that meta\-dependencies may rely on\. -.SS link +.SS \fBlink\fP .RS 0 .IP \(bu 2 Default: false @@ -1023,45 +1005,44 @@ Type: Boolean If true, then local installs will link if there is a suitable globally installed package\. .P -Note that this means that local installs can cause things to be -installed into the global space at the same time\. The link is only done -if one of the two conditions are met: +Note that this means that local installs can cause things to be installed +into the global space at the same time\. The link is only done if one of the +two conditions are met: .RS 0 .IP \(bu 2 The package is not already installed globally, or .IP \(bu 2 -the globally installed version is identical to the version that is -being installed locally\. +the globally installed version is identical to the version that is being +installed locally\. .RE -.SS local\-address +.SS \fBlocal\-address\fP .RS 0 .IP \(bu 2 -Default: undefined +Default: null .IP \(bu 2 Type: IP Address .RE .P -The IP address of the local interface to use when making connections -to the npm registry\. Must be IPv4 in versions of Node prior to 0\.12\. -.SS loglevel +The IP address of the local interface to use when making connections to the +npm registry\. Must be IPv4 in versions of Node prior to 0\.12\. +.SS \fBloglevel\fP .RS 0 .IP \(bu 2 Default: "notice" .IP \(bu 2 -Type: String -.IP \(bu 2 -Values: "silent", "error", "warn", "notice", "http", "timing", "info", -"verbose", "silly" +Type: "silent", "error", "warn", "notice", "http", "timing", "info", +"verbose", or "silly" .RE .P -What level of logs to report\. On failure, \fIall\fR logs are written to +What level of logs to report\. On failure, \fIall\fR logs are written to \fBnpm\-debug\.log\fP in the current working directory\. .P -Any logs of a higher level than the setting are shown\. The default is "notice"\. -.SS logs\-max +Any logs of a higher level than the setting are shown\. The default is +"notice"\. +.SS \fBlogs\-max\fP .RS 0 .IP \(bu 2 Default: 10 @@ -1071,7 +1052,7 @@ Type: Number .RE .P The maximum number of log files to store\. -.SS long +.SS \fBlong\fP .RS 0 .IP \(bu 2 Default: false @@ -1081,18 +1062,18 @@ Type: Boolean .RE .P Show extended information in \fBnpm ls\fP and \fBnpm search\fP\|\. -.SS maxsockets +.SS \fBmaxsockets\fP .RS 0 .IP \(bu 2 -Default: 50 +Default: Infinity .IP \(bu 2 Type: Number .RE .P The maximum number of connections to use per origin (protocol/host/port -combination)\. Passed to the \fBhttp\fP \fBAgent\fP used to make the request\. -.SS message +combination)\. +.SS \fBmessage\fP .RS 0 .IP \(bu 2 Default: "%s" @@ -1104,39 +1085,51 @@ Type: String Commit message which is used by \fBnpm version\fP when creating version commit\. .P Any "%s" in the message will be replaced with the version number\. -.SS node\-options +.SS \fBnode\-options\fP .RS 0 .IP \(bu 2 Default: null .IP \(bu 2 -Type: String +Type: null or String .RE .P Options to pass through to Node\.js via the \fBNODE_OPTIONS\fP environment -variable\. This does not impact how npm itself is executed but it does -impact how lifecycle scripts are called\. -.SS node\-version +variable\. This does not impact how npm itself is executed but it does impact +how lifecycle scripts are called\. +.SS \fBnode\-version\fP .RS 0 .IP \(bu 2 -Default: process\.version +Default: Node\.js \fBprocess\.version\fP value .IP \(bu 2 -Type: semver or false +Type: SemVer string .RE .P -The node version to use when checking a package's \fBengines\fP map\. -.SS noproxy +The node version to use when checking a package's \fBengines\fP setting\. +.SS \fBnoproxy\fP .RS 0 .IP \(bu 2 -Default: null +Default: The value of the NO_PROXY environment variable .IP \(bu 2 -Type: String or Array +Type: String (can be set multiple times) .RE .P -A comma\-separated string or an array of domain extensions that a proxy should not be used for\. -.SS offline +Domain extensions that should bypass any proxies\. +.P +Also accepts a comma\-delimited string\. +.SS \fBnpm\-version\fP +.RS 0 +.IP \(bu 2 +Default: Output of \fBnpm \-\-version\fP +.IP \(bu 2 +Type: SemVer string + +.RE +.P +The npm version to use when checking a package's \fBengines\fP setting\. +.SS \fBoffline\fP .RS 0 .IP \(bu 2 Default: false @@ -1145,53 +1138,54 @@ Type: Boolean .RE .P -Force offline mode: no network requests will be done during install\. To allow -the CLI to fill in missing cache data, see \fB\-\-prefer\-offline\fP\|\. -.SS only +Force offline mode: no network requests will be done during install\. To +allow the CLI to fill in missing cache data, see \fB\-\-prefer\-offline\fP\|\. +.SS \fBomit\fP .RS 0 .IP \(bu 2 -Default: null +Default: 'dev' if the NODE_ENV environment variable is set to 'production', +otherwise empty\. .IP \(bu 2 -Type: String +Type: "dev", "optional", or "peer" (can be set multiple times) .RE .P -When "dev" or "development" and running local \fBnpm install\fP without any -arguments, only devDependencies (and their dependencies) are installed\. +Dependency types to omit from the installation tree on disk\. .P -When "dev" or "development" and running local \fBnpm ls\fP, \fBnpm outdated\fP, or -\fBnpm update\fP, is an alias for \fB\-\-dev\fP\|\. +Note that these dependencies \fIare\fR still resolved and added to the +\fBpackage\-lock\.json\fP or \fBnpm\-shrinkwrap\.json\fP file\. They are just not +physically installed on disk\. .P -When "prod" or "production" and running local \fBnpm install\fP without any -arguments, only non\-devDependencies (and their dependencies) are -installed\. +If a package type appears in both the \fB\-\-include\fP and \fB\-\-omit\fP lists, then +it will be included\. .P -When "prod" or "production" and running local \fBnpm ls\fP, \fBnpm outdated\fP, or -\fBnpm update\fP, is an alias for \fB\-\-production\fP\|\. -.SS optional +If the resulting omit list includes \fB\|'dev'\fP, then the \fBNODE_ENV\fP environment +variable will be set to \fB\|'production'\fP for all lifecycle scripts\. +.SS \fBotp\fP .RS 0 .IP \(bu 2 -Default: true +Default: null .IP \(bu 2 -Type: Boolean +Type: null or String .RE .P -Attempt to install packages in the \fBoptionalDependencies\fP object\. Note -that if these packages fail to install, the overall installation -process is not aborted\. -.SS otp +This is a one\-time password from a two\-factor authenticator\. It's needed +when publishing or changing package permissions with \fBnpm access\fP\|\. +.P +If not set, and a registry response fails with a challenge for a one\-time +password, npm will prompt on the command line for one\. +.SS \fBpackage\fP .RS 0 .IP \(bu 2 -Default: null +Default: .IP \(bu 2 -Type: Number +Type: String (can be set multiple times) .RE .P -This is a one\-time password from a two\-factor authenticator\. It's needed -when publishing or changing package permissions with \fBnpm access\fP\|\. -.SS package\-lock +The package to install for npm help \fBexec\fP +.SS \fBpackage\-lock\fP .RS 0 .IP \(bu 2 Default: true @@ -1204,11 +1198,9 @@ If set to false, then ignore \fBpackage\-lock\.json\fP files when installing\. T will also prevent \fIwriting\fR \fBpackage\-lock\.json\fP if \fBsave\fP is true\. .P When package package\-locks are disabled, automatic pruning of extraneous -modules will also be disabled\. To remove extraneous modules with +modules will also be disabled\. To remove extraneous modules with package\-locks disabled use \fBnpm prune\fP\|\. -.P -This option is an alias for \fB\-\-shrinkwrap\fP\|\. -.SS package\-lock\-only +.SS \fBpackage\-lock\-only\fP .RS 0 .IP \(bu 2 Default: false @@ -1217,9 +1209,9 @@ Type: Boolean .RE .P -If set to true, it will update only the \fBpackage\-lock\.json\fP, -instead of checking \fBnode_modules\fP and downloading dependencies\. -.SS parseable +If set to true, it will update only the \fBpackage\-lock\.json\fP, instead of +checking \fBnode_modules\fP and downloading dependencies\. +.SS \fBparseable\fP .RS 0 .IP \(bu 2 Default: false @@ -1228,9 +1220,9 @@ Type: Boolean .RE .P -Output parseable results from commands that write to -standard output\. For \fBnpm search\fP, this will be tab\-separated table format\. -.SS prefer\-offline +Output parseable results from commands that write to standard output\. For +\fBnpm search\fP, this will be tab\-separated table format\. +.SS \fBprefer\-offline\fP .RS 0 .IP \(bu 2 Default: false @@ -1240,10 +1232,9 @@ Type: Boolean .RE .P If true, staleness checks for cached data will be bypassed, but missing data -will be requested from the server\. To force full offline mode, use \fB\-\-offline\fP\|\. -.P -This option is effectively equivalent to \fB\-\-cache\-min=9999999\fP\|\. -.SS prefer\-online +will be requested from the server\. To force full offline mode, use +\fB\-\-offline\fP\|\. +.SS \fBprefer\-online\fP .RS 0 .IP \(bu 2 Default: false @@ -1252,20 +1243,22 @@ Type: Boolean .RE .P -If true, staleness checks for cached data will be forced, making the CLI look -for updates immediately even for fresh package data\. -.SS prefix +If true, staleness checks for cached data will be forced, making the CLI +look for updates immediately even for fresh package data\. +.SS \fBprefix\fP .RS 0 .IP \(bu 2 -Default: see npm help folders +Default: In global mode, the folder where the node executable is installed\. +In local mode, the nearest parent folder containing either a package\.json +file or a node_modules folder\. .IP \(bu 2 -Type: path +Type: Path .RE .P -The location to install global items\. If set on the command line, then -it forces non\-global commands to run in the specified folder\. -.SS preid +The location to install global items\. If set on the command line, then it +forces non\-global commands to run in the specified folder\. +.SS \fBpreid\fP .RS 0 .IP \(bu 2 Default: "" @@ -1274,30 +1267,12 @@ Type: String .RE .P -The "prerelease identifier" to use as a prefix for the "prerelease" part of a -semver\. Like the \fBrc\fP in \fB1\.2\.0\-rc\.8\fP\|\. -.SS production +The "prerelease identifier" to use as a prefix for the "prerelease" part of +a semver\. Like the \fBrc\fP in \fB1\.2\.0\-rc\.8\fP\|\. +.SS \fBprogress\fP .RS 0 .IP \(bu 2 -Default: false -.IP \(bu 2 -Type: Boolean - -.RE -.P -Set to true to run in "production" mode\. -.RS 0 -.IP 1. 3 -devDependencies are not installed at the topmost level when running -local \fBnpm install\fP without any arguments\. -.IP 2. 3 -Set the NODE_ENV="production" for lifecycle scripts\. - -.RE -.SS progress -.RS 0 -.IP \(bu 2 -Default: true, unless TRAVIS or CI env vars set\. +Default: \fBtrue\fP unless running in a known CI system .IP \(bu 2 Type: Boolean @@ -1307,19 +1282,19 @@ When set to \fBtrue\fP, npm will display a progress bar during time intensive operations, if \fBprocess\.stderr\fP is a TTY\. .P Set to \fBfalse\fP to suppress the progress bar\. -.SS proxy +.SS \fBproxy\fP .RS 0 .IP \(bu 2 Default: null .IP \(bu 2 -Type: url +Type: null, false, or URL .RE .P A proxy to use for outgoing http requests\. If the \fBHTTP_PROXY\fP or -\fBhttp_proxy\fP environment variables are set, proxy settings will be -honored by the underlying \fBrequest\fP library\. -.SS read\-only +\fBhttp_proxy\fP environment variables are set, proxy settings will be honored +by the underlying \fBrequest\fP library\. +.SS \fBread\-only\fP .RS 0 .IP \(bu 2 Default: false @@ -1328,8 +1303,9 @@ Type: Boolean .RE .P -This is used to mark a token as unable to publish when configuring limited access tokens with the \fBnpm token create\fP command\. -.SS rebuild\-bundle +This is used to mark a token as unable to publish when configuring limited +access tokens with the \fBnpm token create\fP command\. +.SS \fBrebuild\-bundle\fP .RS 0 .IP \(bu 2 Default: true @@ -1339,27 +1315,17 @@ Type: Boolean .RE .P Rebuild bundled dependencies after installation\. -.SS registry +.SS \fBregistry\fP .RS 0 .IP \(bu 2 -Default: https://registry\.npmjs\.org/ +Default: "https://registry\.npmjs\.org/" .IP \(bu 2 -Type: url +Type: URL .RE .P -The base URL of the npm package registry\. -.SS rollback -.RS 0 -.IP \(bu 2 -Default: true -.IP \(bu 2 -Type: Boolean - -.RE -.P -Remove failed installs\. -.SS save +The base URL of the npm registry\. +.SS \fBsave\fP .RS 0 .IP \(bu 2 Default: true @@ -1370,11 +1336,9 @@ Type: Boolean .P Save installed packages to a package\.json file as dependencies\. .P -When used with the \fBnpm rm\fP command, it removes it from the \fBdependencies\fP -object\. -.P -Only works if there is already a package\.json file present\. -.SS save\-bundle +When used with the \fBnpm rm\fP command, removes the dependency from +package\.json\. +.SS \fBsave\-bundle\fP .RS 0 .IP \(bu 2 Default: false @@ -1387,9 +1351,8 @@ If a package would be saved at install time by the use of \fB\-\-save\fP, \fB\-\-save\-dev\fP, or \fB\-\-save\-optional\fP, then also put it in the \fBbundleDependencies\fP list\. .P -When used with the \fBnpm rm\fP command, it removes it from the -bundledDependencies list\. -.SS save\-prod +Ignore if \fB\-\-save\-peer\fP is set, since peerDependencies cannot be bundled\. +.SS \fBsave\-dev\fP .RS 0 .IP \(bu 2 Default: false @@ -1398,12 +1361,8 @@ Type: Boolean .RE .P -Makes sure that a package will be saved into \fBdependencies\fP specifically\. This -is useful if a package already exists in \fBdevDependencies\fP or -\fBoptionalDependencies\fP, but you want to move it to be a production dep\. This is -also the default behavior if \fB\-\-save\fP is true, and neither \fB\-\-save\-dev\fP or -\fB\-\-save\-optional\fP are true\. -.SS save\-dev +Save installed packages to a package\.json file as \fBdevDependencies\fP\|\. +.SS \fBsave\-exact\fP .RS 0 .IP \(bu 2 Default: false @@ -1412,13 +1371,9 @@ Type: Boolean .RE .P -Save installed packages to a package\.json file as \fBdevDependencies\fP\|\. -.P -When used with the \fBnpm rm\fP command, it removes it from the -\fBdevDependencies\fP object\. -.P -Only works if there is already a package\.json file present\. -.SS save\-exact +Dependencies saved to package\.json will be configured with an exact version +rather than using npm's default semver range operator\. +.SS \fBsave\-optional\fP .RS 0 .IP \(bu 2 Default: false @@ -1427,10 +1382,8 @@ Type: Boolean .RE .P -Dependencies saved to package\.json using \fB\-\-save\fP, \fB\-\-save\-dev\fP or -\fB\-\-save\-optional\fP will be configured with an exact version rather than -using npm's default semver range operator\. -.SS save\-optional +Save installed packages to a package\.json file as \fBoptionalDependencies\fP\|\. +.SS \fBsave\-peer\fP .RS 0 .IP \(bu 2 Default: false @@ -1439,17 +1392,11 @@ Type: Boolean .RE .P -Save installed packages to a package\.json file as -optionalDependencies\. -.P -When used with the \fBnpm rm\fP command, it removes it from the -\fBdevDependencies\fP object\. -.P -Only works if there is already a package\.json file present\. -.SS save\-prefix +Save installed packages\. to a package\.json file as \fBpeerDependencies\fP +.SS \fBsave\-prefix\fP .RS 0 .IP \(bu 2 -Default: '^' +Default: "^" .IP \(bu 2 Type: String @@ -1458,68 +1405,58 @@ Type: String Configure how versions of packages installed to a package\.json file via \fB\-\-save\fP or \fB\-\-save\-dev\fP get prefixed\. .P -For example if a package has version \fB1\.2\.3\fP, by default its version is -set to \fB^1\.2\.3\fP which allows minor upgrades for that package, but after -\fBnpm config set save\-prefix='~'\fP it would be set to \fB~1\.2\.3\fP which only allows +For example if a package has version \fB1\.2\.3\fP, by default its version is set +to \fB^1\.2\.3\fP which allows minor upgrades for that package, but after \fBnpm +config set save\-prefix='~'\fP it would be set to \fB~1\.2\.3\fP which only allows patch upgrades\. -.SS scope +.SS \fBsave\-prod\fP .RS 0 .IP \(bu 2 -Default: the scope of the current project, if any, or "" +Default: false .IP \(bu 2 -Type: String +Type: Boolean .RE .P -Associate an operation with a scope for a scoped registry\. Useful when logging -in to a private registry for the first time: -\fBnpm login \-\-scope=@organization \-\-registry=registry\.organization\.com\fP, which -will cause \fB@organization\fP to be mapped to the registry for future installation -of packages specified according to the pattern \fB@organization/package\fP\|\. -.SS script\-shell -.RS 0 -.IP \(bu 2 -Default: \fBnull\fP -.IP \(bu 2 -Type: path - -.RE +Save installed packages into \fBdependencies\fP specifically\. This is useful if +a package already exists in \fBdevDependencies\fP or \fBoptionalDependencies\fP, but +you want to move it to be a non\-optional production dependency\. .P -The shell to use for scripts run with the \fBnpm run\fP command\. -.SS scripts\-prepend\-node\-path +This is the default behavior if \fB\-\-save\fP is true, and neither \fB\-\-save\-dev\fP +or \fB\-\-save\-optional\fP are true\. +.SS \fBscope\fP .RS 0 .IP \(bu 2 -Default: "warn\-only" +Default: the scope of the current project, if any, or "" .IP \(bu 2 -Type: Boolean, \fB"auto"\fP or \fB"warn\-only"\fP +Type: String .RE .P -If set to \fBtrue\fP, add the directory in which the current \fBnode\fP executable -resides to the \fBPATH\fP environment variable when running scripts, -even if that means that \fBnpm\fP will invoke a different \fBnode\fP executable than -the one which it is running\. +Associate an operation with a scope for a scoped registry\. .P -If set to \fBfalse\fP, never modify \fBPATH\fP with that\. +Useful when logging in to a private registry for the first time: .P -If set to \fB"warn\-only"\fP, never modify \fBPATH\fP but print a warning if \fBnpm\fP thinks -that you may want to run it with \fBtrue\fP, e\.g\. because the \fBnode\fP executable -in the \fBPATH\fP is not the one \fBnpm\fP was invoked with\. +.RS 2 +.nf +npm login \-\-scope=@mycorp \-\-registry=https://registry\.mycorp\.com +.fi +.RE .P -If set to \fBauto\fP, only add that directory to the \fBPATH\fP environment variable -if the \fBnode\fP executable with which \fBnpm\fP was invoked and the one that is found -first on the \fBPATH\fP are different\. -.SS searchexclude +This will cause \fB@mycorp\fP to be mapped to the registry for future +installation of packages specified according to the pattern +\fB@mycorp/package\fP\|\. +.SS \fBscript\-shell\fP .RS 0 .IP \(bu 2 -Default: "" +Default: '/bin/sh' on POSIX systems, 'cmd\.exe' on Windows .IP \(bu 2 -Type: String +Type: null or String .RE .P -Space\-separated options that limit the results from search\. -.SS searchopts +The shell to use for scripts run with the \fBnpm run\fP command\. +.SS \fBsearchexclude\fP .RS 0 .IP \(bu 2 Default: "" @@ -1528,8 +1465,8 @@ Type: String .RE .P -Space\-separated options that are always passed to search\. -.SS searchlimit +Space\-separated options that limit the results from search\. +.SS \fBsearchlimit\fP .RS 0 .IP \(bu 2 Default: 20 @@ -1540,10 +1477,20 @@ Type: Number .P Number of items to limit search results to\. Will not apply at all to legacy searches\. -.SS searchstaleness +.SS \fBsearchopts\fP +.RS 0 +.IP \(bu 2 +Default: "" +.IP \(bu 2 +Type: String + +.RE +.P +Space\-separated options that are always passed to search\. +.SS \fBsearchstaleness\fP .RS 0 .IP \(bu 2 -Default: 900 (15 minutes) +Default: 900 .IP \(bu 2 Type: Number @@ -1551,31 +1498,32 @@ Type: Number .P The age of the cache, in seconds, before another registry request is made if using legacy search endpoint\. -.SS shell +.SS \fBshell\fP .RS 0 .IP \(bu 2 -Default: SHELL environment variable, or "bash" on Posix, or "cmd" on +Default: SHELL environment variable, or "bash" on Posix, or "cmd\.exe" on Windows .IP \(bu 2 -Type: path +Type: String .RE .P The shell to run for the \fBnpm explore\fP command\. -.SS shrinkwrap +.SS \fBsign\-git\-commit\fP .RS 0 .IP \(bu 2 -Default: true +Default: false .IP \(bu 2 Type: Boolean .RE .P -If set to false, then ignore \fBnpm\-shrinkwrap\.json\fP files when installing\. This -will also prevent \fIwriting\fR \fBnpm\-shrinkwrap\.json\fP if \fBsave\fP is true\. +If set to true, then the \fBnpm version\fP command will commit the new package +version using \fB\-S\fP to add a signature\. .P -This option is an alias for \fB\-\-package\-lock\fP\|\. -.SS sign\-git\-commit +Note that git requires you to have set up GPG keys in your git configs for +this to work properly\. +.SS \fBsign\-git\-tag\fP .RS 0 .IP \(bu 2 Default: false @@ -1584,12 +1532,12 @@ Type: Boolean .RE .P -If set to true, then the \fBnpm version\fP command will commit the new package -version using \fB\-S\fP to add a signature\. +If set to true, then the \fBnpm version\fP command will tag the version using +\fB\-s\fP to add a signature\. .P -Note that git requires you to have set up GPG keys in your git configs -for this to work properly\. -.SS sign\-git\-tag +Note that git requires you to have set up GPG keys in your git configs for +this to work properly\. +.SS \fBstrict\-peer\-deps\fP .RS 0 .IP \(bu 2 Default: false @@ -1598,33 +1546,63 @@ Type: Boolean .RE .P -If set to true, then the \fBnpm version\fP command will tag the version -using \fB\-s\fP to add a signature\. +If set to \fBtrue\fP, and \fB\-\-legacy\-peer\-deps\fP is not set, then \fIany\fR +conflicting \fBpeerDependencies\fP will be treated as an install failure, even +if npm could reasonably guess the appropriate resolution based on non\-peer +dependency relationships\. +.P +By default, conflicting \fBpeerDependencies\fP deep in the dependency graph will +be resolved using the nearest non\-peer dependency specification, even if +doing so will result in some packages receiving a peer dependency outside +the range set in their package's \fBpeerDependencies\fP object\. .P -Note that git requires you to have set up GPG keys in your git configs -for this to work properly\. -.SS sso\-poll\-frequency +When such and override is performed, a warning is printed, explaining the +conflict and the packages involved\. If \fB\-\-strict\-peer\-deps\fP is set, then +this warning is treated as a failure\. +.SS \fBstrict\-ssl\fP .RS 0 .IP \(bu 2 -Default: 500 +Default: true .IP \(bu 2 -Type: Number +Type: Boolean .RE .P -When used with SSO\-enabled \fBauth\-type\fPs, configures how regularly the registry -should be polled while the user is completing authentication\. -.SS sso\-type +Whether or not to do SSL key validation when making requests to the registry +via https\. +.P +See also the \fBca\fP config\. +.SS \fBtag\fP .RS 0 .IP \(bu 2 -Default: 'oauth' +Default: "latest" .IP \(bu 2 -Type: 'oauth', 'saml', or null +Type: String .RE .P -If \fB\-\-auth\-type=sso\fP, the type of SSO type to use\. -.SS strict\-peer\-deps +If you ask npm to install a package and don't tell it a specific version, +then it will install the specified tag\. +.P +Also the tag that is added to the package@version specified by the \fBnpm tag\fP +command, if no explicit tag is given\. +.SS \fBtag\-version\-prefix\fP +.RS 0 +.IP \(bu 2 +Default: "v" +.IP \(bu 2 +Type: String + +.RE +.P +If set, alters the prefix used when tagging a new version when performing a +version increment using \fBnpm\-version\fP\|\. To remove the prefix altogether, set +it to the empty string: \fB""\fP\|\. +.P +Because other tools may rely on the convention that npm version tags look +like \fBv1\.0\.0\fP, \fIonly use this property if it is absolutely necessary\fR\|\. In +particular, use care when overriding this setting for public packages\. +.SS \fBtiming\fP .RS 0 .IP \(bu 2 Default: false @@ -1633,19 +1611,48 @@ Type: Boolean .RE .P -If set to \fBtrue\fP, and \fB\-\-legacy\-peer\-deps\fP is not set, then \fIany\fR -conflicting \fBpeerDependencies\fP will be treated as an install failure, even -if npm could reasonably guess the appropriate resolution based on non\-peer -dependency relationships\. +If true, writes an \fBnpm\-debug\fP log to \fB_logs\fP and timing information to +\fB_timing\.json\fP, both in your cache, even if the command completes +successfully\. \fB_timing\.json\fP is a newline delimited list of JSON objects\. +.P +You can quickly view it with this json \fIhttps://npm\.im/json\fR command line: +\fBnpm exec \-\- json \-g < ~/\.npm/_timing\.json\fP\|\. +.SS \fBumask\fP +.RS 0 +.IP \(bu 2 +Default: 0 +.IP \(bu 2 +Type: Octal numeric string in range 0000\.\.0777 (0\.\.511) + +.RE +.P +The "umask" value to use when setting the file creation mode on files and +folders\. +.P +Folders and executables are given a mode which is \fB0o777\fP masked against +this value\. Other files are given a mode which is \fB0o666\fP masked against +this value\. +.P +Note that the underlying system will \fIalso\fR apply its own umask value to +files and folders that are created, and npm does not circumvent this, but +rather adds the \fB\-\-umask\fP config to it\. +.P +Thus, the effective default umask value on most POSIX systems is 0o22, +meaning that folders and executables are created with a mode of 0o755 and +other files are created with a mode of 0o644\. +.SS \fBunicode\fP +.RS 0 +.IP \(bu 2 +Default: false on windows, true on mac/unix systems with a unicode locale, +as defined by the LC_ALL, LC_CTYPE, or LANG environment variables\. +.IP \(bu 2 +Type: Boolean + +.RE .P -By default, conflicting \fBpeerDependencies\fP in the dependency graph will be -resolved using the nearest non\-peer dependency specification, even if doing -so will result in some packages receiving a peer dependency outside the -range set in their package's \fBpeerDependencies\fP object\. When such and -override is performed, a warning is printed, explaining the conflict and -the packages involved\. If \fB\-\-strict\-peer\-deps\fP is set, then the warning is -treated as a failure\. -.SS strict\-ssl +When set to true, npm uses unicode characters in the tree output\. When +false, it uses ascii characters instead of unicode glyphs\. +.SS \fBupdate\-notifier\fP .RS 0 .IP \(bu 2 Default: true @@ -1654,88 +1661,122 @@ Type: Boolean .RE .P -Whether or not to do SSL key validation when making requests to the -registry via https\. +Set to false to suppress the update notification when using an older version +of npm than the latest\. +.SS \fBusage\fP +.RS 0 +.IP \(bu 2 +Default: false +.IP \(bu 2 +Type: Boolean + +.RE .P -See also the \fBca\fP config\. -.SS tag +Show short usage output about the command specified\. +.SS \fBuser\-agent\fP .RS 0 .IP \(bu 2 -Default: latest +Default: "npm/{npm\-version} node/{node\-version} {platform} {arch} {ci}" .IP \(bu 2 Type: String .RE .P -If you ask npm to install a package and don't tell it a specific version, then -it will install the specified tag\. +Sets the User\-Agent request header\. The following fields are replaced with +their actual counterparts: +.RS 0 +.IP \(bu 2 +\fB{npm\-version}\fP \- The npm version in use +.IP \(bu 2 +\fB{node\-version}\fP \- The Node\.js version in use +.IP \(bu 2 +\fB{platform}\fP \- The value of \fBprocess\.platform\fP +.IP \(bu 2 +\fB{arch}\fP \- The value of \fBprocess\.arch\fP +.IP \(bu 2 +\fB{ci}\fP \- The value of the \fBci\-name\fP config, if set, prefixed with \fBci/\fP, or +an empty string if \fBci\-name\fP is empty\. + +.RE +.SS \fBuserconfig\fP +.RS 0 +.IP \(bu 2 +Default: "~/\.npmrc" +.IP \(bu 2 +Type: Path + +.RE +.P +The location of user\-level configuration settings\. .P -Also the tag that is added to the package@version specified by the \fBnpm -tag\fP command, if no explicit tag is given\. -.SS tag\-version\-prefix +This may be overridden by the \fBnpm_config_userconfig\fP environment variable +or the \fB\-\-userconfig\fP command line option, but may \fInot\fR be overridden by +settings in the \fBglobalconfig\fP file\. +.SS \fBversion\fP .RS 0 .IP \(bu 2 -Default: \fB"v"\fP +Default: false .IP \(bu 2 -Type: String +Type: Boolean .RE .P -If set, alters the prefix used when tagging a new version when performing a -version increment using \fBnpm\-version\fP\|\. To remove the prefix altogether, set it -to the empty string: \fB""\fP\|\. +If true, output the npm version and exit successfully\. .P -Because other tools may rely on the convention that npm version tags look like -\fBv1\.0\.0\fP, \fIonly use this property if it is absolutely necessary\fR\|\. In -particular, use care when overriding this setting for public packages\. -.SS timing +Only relevant when specified explicitly on the command line\. +.SS \fBversions\fP .RS 0 .IP \(bu 2 -Default: \fBfalse\fP +Default: false .IP \(bu 2 Type: Boolean .RE .P -If true, writes an \fBnpm\-debug\fP log to \fB_logs\fP and timing information to -\fB_timing\.json\fP, both in your cache\. \fB_timing\.json\fP is a newline delimited -list of JSON objects\. You can quickly view it with this -json \fIhttps://www\.npmjs\.com/package/json\fR command line: -\fBjson \-g < ~/\.npm/_timing\.json\fP\|\. -.SS tmp +If true, output the npm version as well as node's \fBprocess\.versions\fP map and +the version in the current working directory's \fBpackage\.json\fP file if one +exists, and exit successfully\. +.P +Only relevant when specified explicitly on the command line\. +.SS \fBviewer\fP .RS 0 .IP \(bu 2 -Default: TMPDIR environment variable, or "/tmp" +Default: "man" on Posix, "browser" on Windows .IP \(bu 2 -Type: path +Type: String .RE .P -Where to store temporary files and folders\. All temp files are deleted -on success, but left behind on failure for forensic purposes\. -.SS unicode +The program to use to view help content\. +.P +Set to \fB"browser"\fP to view html help content in the default web browser\. +.SS \fBwhich\fP .RS 0 .IP \(bu 2 -Default: false on windows, true on mac/unix systems with a unicode locale +Default: null .IP \(bu 2 -Type: Boolean +Type: null or Number .RE .P -When set to true, npm uses unicode characters in the tree output\. When -false, it uses ascii characters to draw trees\. -.SS update\-notifier +If there are multiple funding sources, which 1\-indexed source URL to open\. +.SS \fBworkspace\fP .RS 0 .IP \(bu 2 -Default: true +Default: .IP \(bu 2 -Type: Boolean +Type: String (can be set multiple times) .RE .P -Set to false to suppress the update notification when using an older -version of npm than the latest\. -.SS usage +Enable running a command in the context of the configured workspaces of the +current project while filtering by running only the workspaces defined by +this configuration option\. +.P +Valid values for the \fBworkspace\fP config are either: \- Workspace names \- Path +to a workspace directory \- Path to a parent workspace directory (will result +to selecting all of the nested workspaces) +.SS \fBworkspaces\fP .RS 0 .IP \(bu 2 Default: false @@ -1744,80 +1785,236 @@ Type: Boolean .RE .P -Set to show short usage output (like the \-H output) -instead of complete help when doing npm help \fBhelp\fP\|\. -.SS userconfig +Enable running a command in the context of \fBall\fR the configured +workspaces\. +.SS \fByes\fP .RS 0 .IP \(bu 2 -Default: ~/\.npmrc +Default: null .IP \(bu 2 -Type: path +Type: null or Boolean .RE .P -The location of user\-level configuration settings\. -.SS umask +Automatically answer "yes" to any prompts that npm might print on the +command line\. +.SS \fBalso\fP .RS 0 .IP \(bu 2 -Default: 022 +Default: null .IP \(bu 2 -Type: Octal numeric string in range 0000\.\.0777 (0\.\.511) +Type: null, "dev", or "development" +.IP \(bu 2 +DEPRECATED: Please use \-\-include=dev instead\. .RE .P -The "umask" value to use when setting the file creation mode on files -and folders\. +When set to \fBdev\fP or \fBdevelopment\fP, this is an alias for \fB\-\-include=dev\fP\|\. +.SS \fBauth\-type\fP +.RS 0 +.IP \(bu 2 +Default: "legacy" +.IP \(bu 2 +Type: "legacy", "sso", "saml", or "oauth" +.IP \(bu 2 +DEPRECATED: This method of SSO/SAML/OAuth is deprecated and will be removed +in a future version of npm in favor of web\-based login\. + +.RE +.P +What authentication strategy to use with \fBadduser\fP/\fBlogin\fP\|\. +.SS \fBcache\-max\fP +.RS 0 +.IP \(bu 2 +Default: Infinity +.IP \(bu 2 +Type: Number +.IP \(bu 2 +DEPRECATED: This option has been deprecated in favor of \fB\-\-prefer\-online\fP + +.RE +.P +\fB\-\-cache\-max=0\fP is an alias for \fB\-\-prefer\-online\fP +.SS \fBcache\-min\fP +.RS 0 +.IP \(bu 2 +Default: 0 +.IP \(bu 2 +Type: Number +.IP \(bu 2 +DEPRECATED: This option has been deprecated in favor of \fB\-\-prefer\-offline\fP\|\. + +.RE .P -Folders and executables are given a mode which is \fB0777\fP masked against -this value\. Other files are given a mode which is \fB0666\fP masked against -this value\. Thus, the defaults are \fB0755\fP and \fB0644\fP respectively\. -.SS user\-agent +\fB\-\-cache\-min=9999 (or bigger)\fP is an alias for \fB\-\-prefer\-offline\fP\|\. +.SS \fBinit\.author\.email\fP .RS 0 .IP \(bu 2 -Default: node/{process\.version} {process\.platform} {process\.arch} +Default: "" .IP \(bu 2 Type: String +.IP \(bu 2 +DEPRECATED: Use \fB\-\-init\-author\-email\fP instead\. .RE .P -Sets a User\-Agent to the request header -.SS version +Alias for \fB\-\-init\-author\-email\fP +.SS \fBinit\.author\.name\fP .RS 0 .IP \(bu 2 -Default: false +Default: "" +.IP \(bu 2 +Type: String .IP \(bu 2 -Type: boolean +DEPRECATED: Use \fB\-\-init\-author\-name\fP instead\. .RE .P -If true, output the npm version and exit successfully\. +Alias for \fB\-\-init\-author\-name\fP +.SS \fBinit\.author\.url\fP +.RS 0 +.IP \(bu 2 +Default: "" +.IP \(bu 2 +Type: "" or URL +.IP \(bu 2 +DEPRECATED: Use \fB\-\-init\-author\-url\fP instead\. + +.RE .P -Only relevant when specified explicitly on the command line\. -.SS versions +Alias for \fB\-\-init\-author\-url\fP +.SS \fBinit\.license\fP +.RS 0 +.IP \(bu 2 +Default: "ISC" +.IP \(bu 2 +Type: String +.IP \(bu 2 +DEPRECATED: Use \fB\-\-init\-license\fP instead\. + +.RE +.P +Alias for \fB\-\-init\-license\fP +.SS \fBinit\.module\fP +.RS 0 +.IP \(bu 2 +Default: "~/\.npm\-init\.js" +.IP \(bu 2 +Type: Path +.IP \(bu 2 +DEPRECATED: Use \fB\-\-init\-module\fP instead\. + +.RE +.P +Alias for \fB\-\-init\-module\fP +.SS \fBinit\.version\fP +.RS 0 +.IP \(bu 2 +Default: "1\.0\.0" +.IP \(bu 2 +Type: SemVer string +.IP \(bu 2 +DEPRECATED: Use \fB\-\-init\-version\fP instead\. + +.RE +.P +Alias for \fB\-\-init\-version\fP +.SS \fBonly\fP +.RS 0 +.IP \(bu 2 +Default: null +.IP \(bu 2 +Type: null, "prod", or "production" +.IP \(bu 2 +DEPRECATED: Use \fB\-\-omit=dev\fP to omit dev dependencies from the install\. + +.RE +.P +When set to \fBprod\fP or \fBproduction\fP, this is an alias for \fB\-\-omit=dev\fP\|\. +.SS \fBoptional\fP +.RS 0 +.IP \(bu 2 +Default: null +.IP \(bu 2 +Type: null or Boolean +.IP \(bu 2 +DEPRECATED: Use \fB\-\-omit=optional\fP to exclude optional dependencies, or +\fB\-\-include=optional\fP to include them\. + +.RE +.P +Default value does install optional deps unless otherwise omitted\. +.P +Alias for \-\-include=optional or \-\-omit=optional +.SS \fBproduction\fP .RS 0 .IP \(bu 2 Default: false .IP \(bu 2 -Type: boolean +Type: Boolean +.IP \(bu 2 +DEPRECATED: Use \fB\-\-omit=dev\fP instead\. .RE .P -If true, output the npm version as well as node's \fBprocess\.versions\fP map, and -exit successfully\. +Alias for \fB\-\-omit=dev\fP +.SS \fBshrinkwrap\fP +.RS 0 +.IP \(bu 2 +Default: true +.IP \(bu 2 +Type: Boolean +.IP \(bu 2 +DEPRECATED: Use the \-\-package\-lock setting instead\. + +.RE .P -Only relevant when specified explicitly on the command line\. -.SS viewer +Alias for \-\-package\-lock +.SS \fBsso\-poll\-frequency\fP .RS 0 .IP \(bu 2 -Default: "man" on Posix, "browser" on Windows +Default: 500 +.IP \(bu 2 +Type: Number .IP \(bu 2 -Type: path +DEPRECATED: The \-\-auth\-type method of SSO/SAML/OAuth will be removed in a +future version of npm in favor of web\-based login\. .RE .P -The program to use to view help content\. +When used with SSO\-enabled \fBauth\-type\fPs, configures how regularly the +registry should be polled while the user is completing authentication\. +.SS \fBsso\-type\fP +.RS 0 +.IP \(bu 2 +Default: "oauth" +.IP \(bu 2 +Type: null, "oauth", or "saml" +.IP \(bu 2 +DEPRECATED: The \-\-auth\-type method of SSO/SAML/OAuth will be removed in a +future version of npm in favor of web\-based login\. + +.RE .P -Set to \fB"browser"\fP to view html help content in the default web browser\. +If \fB\-\-auth\-type=sso\fP, the type of SSO type to use\. +.SS \fBtmp\fP +.RS 0 +.IP \(bu 2 +Default: The value returned by the Node\.js \fBos\.tmpdir()\fP method +https://nodejs\.org/api/os\.html#os_os_tmpdir +.IP \(bu 2 +Type: Path +.IP \(bu 2 +DEPRECATED: This setting is no longer used\. npm stores temporary files in a +special location in the cache, and they are managed by +\fBcacache\fP \fIhttp://npm\.im/cacache\fR\|\. + +.RE +.P +Historically, the location where temporary files were stored\. No longer +relevant\. +<!\-\- AUTOGENERATED CONFIG DESCRIPTIONS END \-\-> + .SS See also .RS 0 .IP \(bu 2 diff --git a/deps/npm/man/man7/workspaces.7 b/deps/npm/man/man7/workspaces.7 index 61da2ce657..2fa6a9cccc 100644 --- a/deps/npm/man/man7/workspaces.7 +++ b/deps/npm/man/man7/workspaces.7 @@ -90,11 +90,65 @@ This demonstrates how the nature of \fBnode_modules\fP resolution allows for \fBworkspaces\fR to enable a portable workflow for requiring each \fBworkspace\fR in such a way that is also easy to npm help publish these nested workspaces to be consumed elsewhere\. +.SS Running commands in the context of workspaces +.P +You man use the \fBworkspace\fP configuration option to run commands in the context +of a configured workspace\. +.P +Following is a quick example on how to use the \fBnpm run\fP command in the context +of nested workspaces\. For a project containing multiple workspaces, e\.g: +.P +.RS 2 +.nf +\|\. ++\-\- package\.json +`\-\- packages + +\-\- a + | `\-\- package\.json + `\-\- b + `\-\- package\.json +.fi +.RE +.P +By running a command using the \fBworkspace\fP option, it's possible to run the +given command in the context of that specific workspace\. e\.g: +.P +.RS 2 +.nf +npm run test \-\-workspace=a +.fi +.RE +.P +This will run the \fBtest\fP script defined within the +\fB\|\./packages/a/package\.json\fP file\. +.P +Please note that you can also specify this argument multiple times in the +command\-line in order to target multiple workspaces, e\.g: +.P +.RS 2 +.nf +npm run test \-\-workspace=a \-\-workspace=b +.fi +.RE +.P +It's also possible to use the \fBworkspaces\fP (plural) configuration option to +enable the same behavior but running that command in the context of \fBall\fR +configured workspaces\. e\.g: +.P +.RS 2 +.nf +npm run test \-\-workspaces +.fi +.RE +.P +Will run the \fBtest\fP script in both \fB\|\./packages/a\fP and \fB\|\./packages/b\fP\|\. .SS See also .RS 0 .IP \(bu 2 npm help install .IP \(bu 2 npm help publish +.IP \(bu 2 +npm help run\-script .RE diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/add-rm-pkg-deps.js b/deps/npm/node_modules/@npmcli/arborist/lib/add-rm-pkg-deps.js index 9e4825c526..9a96fd1b37 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/add-rm-pkg-deps.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/add-rm-pkg-deps.js @@ -71,7 +71,7 @@ const addSingle = ({pkg, spec, saveBundle, saveType}) => { pkg.devDependencies[name] = pkg.peerDependencies[name] } - if (saveBundle) { + if (saveBundle && saveType !== 'peer' && saveType !== 'peerOptional') { // keep it sorted, keep it unique const bd = new Set(pkg.bundleDependencies || []) bd.add(spec.name) 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 803fb9782f..0008045528 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js @@ -890,7 +890,7 @@ module.exports = cls => class Reifier extends cls { const root = this.idealTree const pkg = root.package for (const { name } of this[_resolvedAdd]) { - const req = npa(root.edgesOut.get(name).spec, root.realpath) + const req = npa.resolve(name, root.edgesOut.get(name).spec, root.realpath) const {rawSpec, subSpec} = req const spec = subSpec ? subSpec.rawSpec : rawSpec diff --git a/deps/npm/node_modules/@npmcli/arborist/package.json b/deps/npm/node_modules/@npmcli/arborist/package.json index bff10db4b0..e745be2c77 100644 --- a/deps/npm/node_modules/@npmcli/arborist/package.json +++ b/deps/npm/node_modules/@npmcli/arborist/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/arborist", - "version": "2.2.8", + "version": "2.2.9", "description": "Manage node_modules trees", "dependencies": { "@npmcli/installed-package-contents": "^1.0.7", @@ -26,7 +26,7 @@ "promise-call-limit": "^1.0.1", "read-package-json-fast": "^2.0.2", "readdir-scoped-modules": "^1.1.0", - "semver": "^7.3.4", + "semver": "^7.3.5", "tar": "^6.1.0", "treeverse": "^1.0.4", "walk-up-path": "^1.0.0" diff --git a/deps/npm/node_modules/@npmcli/config/lib/get-user-agent.js b/deps/npm/node_modules/@npmcli/config/lib/get-user-agent.js deleted file mode 100644 index c3d3c7a1bf..0000000000 --- a/deps/npm/node_modules/@npmcli/config/lib/get-user-agent.js +++ /dev/null @@ -1,13 +0,0 @@ -// Accepts a config object, returns a user-agent string -const getUserAgent = (config) => { - const ciName = config.get('ci-name') - return (config.get('user-agent') || '') - .replace(/\{node-version\}/gi, config.get('node-version')) - .replace(/\{npm-version\}/gi, config.get('npm-version')) - .replace(/\{platform\}/gi, process.platform) - .replace(/\{arch\}/gi, process.arch) - .replace(/\{ci\}/gi, ciName ? `ci/${ciName}` : '') - .trim() -} - -module.exports = getUserAgent diff --git a/deps/npm/node_modules/@npmcli/config/lib/index.js b/deps/npm/node_modules/@npmcli/config/lib/index.js index e7fac96c1c..21a37ded48 100644 --- a/deps/npm/node_modules/@npmcli/config/lib/index.js +++ b/deps/npm/node_modules/@npmcli/config/lib/index.js @@ -47,7 +47,6 @@ const envReplace = require('./env-replace.js') const parseField = require('./parse-field.js') const typeDescription = require('./type-description.js') const setEnvs = require('./set-envs.js') -const getUserAgent = require('./get-user-agent.js') // types that can be saved back to const confFileTypes = new Set([ @@ -69,6 +68,9 @@ const _get = Symbol('get') const _find = Symbol('find') const _loadObject = Symbol('loadObject') const _loadFile = Symbol('loadFile') +const _checkDeprecated = Symbol('checkDeprecated') +const _flatten = Symbol('flatten') +const _flatOptions = Symbol('flatOptions') class Config { static get typeDefs () { @@ -76,9 +78,9 @@ class Config { } constructor ({ - types, + definitions, shorthands, - defaults, + flatten, npmPath, // options just to override in tests, mostly @@ -89,10 +91,27 @@ class Config { execPath = process.execPath, cwd = process.cwd(), }) { - this.npmPath = npmPath + + // turn the definitions into nopt's weirdo syntax + this.definitions = definitions + const types = {} + const defaults = {} + this.deprecated = {} + for (const [key, def] of Object.entries(definitions)) { + defaults[key] = def.default + types[key] = def.type + if (def.deprecated) + this.deprecated[key] = def.deprecated.trim().replace(/\n +/, '\n') + } + + // populated the first time we flatten the object + this[_flatOptions] = null + this[_flatten] = flatten this.types = types this.shorthands = shorthands this.defaults = defaults + + this.npmPath = npmPath this.log = log this.argv = argv this.env = env @@ -183,10 +202,31 @@ class Config { if (!email) throw new Error('Cannot set _auth without first setting email') } - this.data.get(where).data[key] = val + this[_checkDeprecated](key) + const { data } = this.data.get(where) + data[key] = val // this is now dirty, the next call to this.valid will have to check it this.data.get(where)[_valid] = null + + // the flat options are invalidated, regenerate next time they're needed + this[_flatOptions] = null + } + + get flat () { + if (this[_flatOptions]) + return this[_flatOptions] + + // create the object for flat options passed to deps + process.emit('time', 'config:load:flatten') + this[_flatOptions] = {} + // walk from least priority to highest + for (const { data } of this.data.values()) { + this[_flatten](data, this[_flatOptions]) + } + process.emit('timeEnd', 'config:load:flatten') + + return this[_flatOptions] } delete (key, where = 'cli') { @@ -233,11 +273,6 @@ class Config { await this.loadGlobalConfig() process.emit('timeEnd', 'config:load:global') - // now the extras - process.emit('time', 'config:load:cafile') - await this.loadCAFile() - process.emit('timeEnd', 'config:load:cafile') - // warn if anything is not valid process.emit('time', 'config:load:validate') this.validate() @@ -250,10 +285,6 @@ class Config { // set proper globalPrefix now that everything is loaded this.globalPrefix = this.get('prefix') - process.emit('time', 'config:load:setUserAgent') - this.setUserAgent() - process.emit('timeEnd', 'config:load:setUserAgent') - process.emit('time', 'config:load:setEnvs') this.setEnvs() process.emit('timeEnd', 'config:load:setEnvs') @@ -376,13 +407,13 @@ class Config { this.data.get(where)[_valid] = false if (Array.isArray(type)) { - if (type.indexOf(typeDefs.url.type) !== -1) + if (type.includes(typeDefs.url.type)) type = typeDefs.url.type else { /* istanbul ignore if - no actual configs matching this, but * path types SHOULD be handled this way, like URLs, for the * same reason */ - if (type.indexOf(typeDefs.path.type) !== -1) + if (type.includes(typeDefs.path.type)) type = typeDefs.path.type } } @@ -428,11 +459,21 @@ class Config { for (const [key, value] of Object.entries(obj)) { const k = envReplace(key, this.env) const v = this.parseField(value, k) + if (where !== 'default') + this[_checkDeprecated](k, where, obj, [key, value]) conf.data[k] = v } } } + [_checkDeprecated] (key, where, obj, kv) { + // XXX a future npm version will make this a warning. + // An even more future npm version will make this an error. + if (this.deprecated[key]) { + this.log.verbose('config', key, this.deprecated[key]) + } + } + // Parse a field, coercing it to the best type available. parseField (f, key, listElement = false) { return parseField(f, key, this, listElement) @@ -675,48 +716,6 @@ class Config { return creds } - async loadCAFile () { - const where = this[_find]('cafile') - - /* istanbul ignore if - it'll always be set in the defaults */ - if (!where) - return - - const cafile = this[_get]('cafile', where) - const ca = this[_get]('ca', where) - - // if you have a ca, or cafile is set to null, then nothing to do here. - if (ca || !cafile) - return - - const raw = await readFile(cafile, 'utf8').catch(er => { - if (er.code !== 'ENOENT') - throw er - }) - if (!raw) - return - - const delim = '-----END CERTIFICATE-----' - const output = raw.replace(/\r\n/g, '\n').split(delim) - .filter(section => section.trim()) - .map(section => section.trimLeft() + delim) - - // make it non-enumerable so we don't save it back by accident - const { data } = this.data.get(where) - Object.defineProperty(data, 'ca', { - value: output, - enumerable: false, - configurable: true, - writable: true, - }) - } - - // the user-agent configuration is a template that gets populated - // with some variables, that takes place here - setUserAgent () { - this.set('user-agent', getUserAgent(this)) - } - // set up the environment object we have with npm_config_* environs // for all configs that are different from their default values, and // set EDITOR and HOME. diff --git a/deps/npm/node_modules/@npmcli/config/lib/set-envs.js b/deps/npm/node_modules/@npmcli/config/lib/set-envs.js index 36d3714546..ffaf5ab383 100644 --- a/deps/npm/node_modules/@npmcli/config/lib/set-envs.js +++ b/deps/npm/node_modules/@npmcli/config/lib/set-envs.js @@ -50,11 +50,13 @@ const setEnvs = (config) => { platform, env, defaults, + definitions, list: [cliConf, envConf], } = config env.INIT_CWD = process.cwd() + // if the key is deprecated, skip it always. // if the key is the default value, // if the environ is NOT the default value, // set the environ @@ -65,6 +67,10 @@ const setEnvs = (config) => { const cliSet = new Set(Object.keys(cliConf)) const envSet = new Set(Object.keys(envConf)) for (const key in cliConf) { + const { deprecated } = definitions[key] || {} + if (deprecated) + continue + if (sameConfigValue(defaults[key], cliConf[key])) { // config is the default, if the env thought different, then we // have to set it BACK to the default in the environment. diff --git a/deps/npm/node_modules/@npmcli/config/package.json b/deps/npm/node_modules/@npmcli/config/package.json index 644544a49d..b2b34f6af2 100644 --- a/deps/npm/node_modules/@npmcli/config/package.json +++ b/deps/npm/node_modules/@npmcli/config/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/config", - "version": "1.2.9", + "version": "2.0.0", "files": [ "lib" ], diff --git a/deps/npm/node_modules/@npmcli/run-script/lib/make-spawn-args.js b/deps/npm/node_modules/@npmcli/run-script/lib/make-spawn-args.js index 4c38b9401d..8ee24c06da 100644 --- a/deps/npm/node_modules/@npmcli/run-script/lib/make-spawn-args.js +++ b/deps/npm/node_modules/@npmcli/run-script/lib/make-spawn-args.js @@ -3,24 +3,6 @@ const isWindows = require('./is-windows.js') const setPATH = require('./set-path.js') const {resolve} = require('path') const npm_config_node_gyp = require.resolve('node-gyp/bin/node-gyp.js') -const { quoteForShell, ShellString, ShellStringText, ShellStringUnquoted } = require('puka') - -const escapeCmd = cmd => { - const result = [] - const parsed = ShellString.sh([cmd]) - for (const child of parsed.children) { - if (child instanceof ShellStringText) { - const children = child.contents.filter(segment => segment !== null).map(segment => quoteForShell(segment, false, isWindows && 'win32')) - result.push(...children) - } else if (child instanceof ShellStringUnquoted) { - result.push(child.value) - } else { - result.push(isWindows ? '&' : ';') - } - } - - return result.join('') -} const makeSpawnArgs = options => { const { @@ -34,7 +16,7 @@ const makeSpawnArgs = options => { } = options const isCmd = /(?:^|\\)cmd(?:\.exe)?$/i.test(scriptShell) - const args = isCmd ? ['/d', '/s', '/c', escapeCmd(cmd)] : ['-c', cmd] + const args = isCmd ? ['/d', '/s', '/c', cmd] : ['-c', cmd] const spawnOpts = { env: setPATH(path, { diff --git a/deps/npm/node_modules/@npmcli/run-script/package.json b/deps/npm/node_modules/@npmcli/run-script/package.json index 9df5b31178..7e0e5255de 100644 --- a/deps/npm/node_modules/@npmcli/run-script/package.json +++ b/deps/npm/node_modules/@npmcli/run-script/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/run-script", - "version": "1.8.3", + "version": "1.8.4", "description": "Run a lifecycle script for a package (descendant of npm-lifecycle)", "author": "Isaac Z. Schlueter <i@izs.me> (https://izs.me)", "license": "ISC", @@ -32,7 +32,6 @@ "@npmcli/promise-spawn": "^1.3.2", "infer-owner": "^1.0.4", "node-gyp": "^7.1.0", - "puka": "^1.0.1", "read-package-json-fast": "^2.0.1" }, "files": [ diff --git a/deps/npm/node_modules/cacache/CHANGELOG.md b/deps/npm/node_modules/cacache/CHANGELOG.md index 14eee0b381..d10160846b 100644 --- a/deps/npm/node_modules/cacache/CHANGELOG.md +++ b/deps/npm/node_modules/cacache/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [15.0.6](https://github.com/npm/cacache/compare/v15.0.5...v15.0.6) (2021-03-22) + ### [15.0.5](https://github.com/npm/cacache/compare/v15.0.4...v15.0.5) (2020-07-11) ### [15.0.4](https://github.com/npm/cacache/compare/v15.0.3...v15.0.4) (2020-06-03) diff --git a/deps/npm/node_modules/cacache/package.json b/deps/npm/node_modules/cacache/package.json index 053c245b52..afe569c8bd 100644 --- a/deps/npm/node_modules/cacache/package.json +++ b/deps/npm/node_modules/cacache/package.json @@ -1,6 +1,6 @@ { "name": "cacache", - "version": "15.0.5", + "version": "15.0.6", "cache-version": { "content": "2", "index": "5" @@ -72,7 +72,7 @@ "p-map": "^4.0.0", "promise-inflight": "^1.0.1", "rimraf": "^3.0.2", - "ssri": "^8.0.0", + "ssri": "^8.0.1", "tar": "^6.0.2", "unique-filename": "^1.1.1" }, diff --git a/deps/npm/node_modules/hosted-git-info/README.md b/deps/npm/node_modules/hosted-git-info/README.md index 7b723f6b9e..8740406029 100644 --- a/deps/npm/node_modules/hosted-git-info/README.md +++ b/deps/npm/node_modules/hosted-git-info/README.md @@ -22,7 +22,7 @@ var info = hostedGitInfo.fromUrl("git@github.com:npm/hosted-git-info.git", opts) If the URL can't be matched with a git host, `null` will be returned. We can match git, ssh and https urls. Additionally, we can match ssh connect strings (`git@github.com:npm/hosted-git-info`) and shortcuts (eg, -`github:npm/hosted-git-info`). Github specifically, is detected in the case +`github:npm/hosted-git-info`). GitHub specifically, is detected in the case of a third, unprefixed, form: `npm/hosted-git-info`. If it does match, the returned object has properties of: @@ -129,5 +129,5 @@ SSH connect strings will be normalized into `git+ssh` URLs. ## Supported hosts -Currently this supports Github, Bitbucket and Gitlab. Pull requests for +Currently this supports GitHub, Bitbucket and GitLab. Pull requests for additional hosts welcome. diff --git a/deps/npm/node_modules/hosted-git-info/git-host-info.js b/deps/npm/node_modules/hosted-git-info/git-host-info.js index da3348fa7b..360d7b096b 100644 --- a/deps/npm/node_modules/hosted-git-info/git-host-info.js +++ b/deps/npm/node_modules/hosted-git-info/git-host-info.js @@ -1,79 +1,154 @@ 'use strict' +const maybeJoin = (...args) => args.every(arg => arg) ? args.join('') : '' +const maybeEncode = (arg) => arg ? encodeURIComponent(arg) : '' -var gitHosts = module.exports = { - github: { - // First two are insecure and generally shouldn't be used any more, but - // they are still supported. - 'protocols': [ 'git', 'http', 'git+ssh', 'git+https', 'ssh', 'https' ], - 'domain': 'github.com', - 'treepath': 'tree', - 'filetemplate': 'https://{auth@}raw.githubusercontent.com/{user}/{project}/{committish}/{path}', - 'bugstemplate': 'https://{domain}/{user}/{project}/issues', - 'gittemplate': 'git://{auth@}{domain}/{user}/{project}.git{#committish}', - 'tarballtemplate': 'https://codeload.{domain}/{user}/{project}/tar.gz/{committish}' - }, - bitbucket: { - 'protocols': [ 'git+ssh', 'git+https', 'ssh', 'https' ], - 'domain': 'bitbucket.org', - 'treepath': 'src', - 'tarballtemplate': 'https://{domain}/{user}/{project}/get/{committish}.tar.gz' - }, - gitlab: { - 'protocols': [ 'git+ssh', 'git+https', 'ssh', 'https' ], - 'domain': 'gitlab.com', - 'treepath': 'tree', - 'bugstemplate': 'https://{domain}/{user}/{project}/issues', - 'httpstemplate': 'git+https://{auth@}{domain}/{user}/{projectPath}.git{#committish}', - 'tarballtemplate': 'https://{domain}/{user}/{project}/repository/archive.tar.gz?ref={committish}', - 'pathmatch': /^\/([^/]+)\/((?!.*(\/-\/|\/repository(\/[^/]+)?\/archive\.tar\.gz)).*?)(?:\.git|\/)?$/ - }, - gist: { - 'protocols': [ 'git', 'git+ssh', 'git+https', 'ssh', 'https' ], - 'domain': 'gist.github.com', - 'pathmatch': /^[/](?:([^/]+)[/])?([a-z0-9]{7,})(?:[.]git)?$/, - 'filetemplate': 'https://gist.githubusercontent.com/{user}/{project}/raw{/committish}/{path}', - 'bugstemplate': 'https://{domain}/{project}', - 'gittemplate': 'git://{domain}/{project}.git{#committish}', - 'sshtemplate': 'git@{domain}:/{project}.git{#committish}', - 'sshurltemplate': 'git+ssh://git@{domain}/{project}.git{#committish}', - 'browsetemplate': 'https://{domain}/{project}{/committish}', - 'browsefiletemplate': 'https://{domain}/{project}{/committish}{#path}', - 'docstemplate': 'https://{domain}/{project}{/committish}', - 'httpstemplate': 'git+https://{domain}/{project}.git{#committish}', - 'shortcuttemplate': '{type}:{project}{#committish}', - 'pathtemplate': '{project}{#committish}', - 'tarballtemplate': 'https://codeload.github.com/gist/{project}/tar.gz/{committish}', - 'hashformat': function (fragment) { - return 'file-' + formatHashFragment(fragment) +const defaults = { + sshtemplate: ({ domain, user, project, committish }) => `git@${domain}:${user}/${project}.git${maybeJoin('#', committish)}`, + sshurltemplate: ({ domain, user, project, committish }) => `git+ssh://git@${domain}/${user}/${project}.git${maybeJoin('#', committish)}`, + browsetemplate: ({ domain, user, project, committish, treepath }) => `https://${domain}/${user}/${project}${maybeJoin('/', treepath, '/', maybeEncode(committish))}`, + browsefiletemplate: ({ domain, user, project, committish, treepath, path, fragment, hashformat }) => `https://${domain}/${user}/${project}/${treepath}/${maybeEncode(committish || 'master')}/${path}${maybeJoin('#', hashformat(fragment || ''))}`, + docstemplate: ({ domain, user, project, treepath, committish }) => `https://${domain}/${user}/${project}${maybeJoin('/', treepath, '/', maybeEncode(committish))}#readme`, + httpstemplate: ({ auth, domain, user, project, committish }) => `git+https://${maybeJoin(auth, '@')}${domain}/${user}/${project}.git${maybeJoin('#', committish)}`, + filetemplate: ({ domain, user, project, committish, path }) => `https://${domain}/${user}/${project}/raw/${maybeEncode(committish) || 'master'}/${path}`, + shortcuttemplate: ({ type, user, project, committish }) => `${type}:${user}/${project}${maybeJoin('#', committish)}`, + pathtemplate: ({ user, project, committish }) => `${user}/${project}${maybeJoin('#', committish)}`, + bugstemplate: ({ domain, user, project }) => `https://${domain}/${user}/${project}/issues`, + hashformat: formatHashFragment +} + +const gitHosts = {} +gitHosts.github = Object.assign({}, defaults, { + // First two are insecure and generally shouldn't be used any more, but + // they are still supported. + protocols: ['git:', 'http:', 'git+ssh:', 'git+https:', 'ssh:', 'https:'], + domain: 'github.com', + treepath: 'tree', + filetemplate: ({ auth, user, project, committish, path }) => `https://${maybeJoin(auth, '@')}raw.githubusercontent.com/${user}/${project}/${maybeEncode(committish) || 'master'}/${path}`, + gittemplate: ({ auth, domain, user, project, committish }) => `git://${maybeJoin(auth, '@')}${domain}/${user}/${project}.git${maybeJoin('#', committish)}`, + tarballtemplate: ({ domain, user, project, committish }) => `https://codeload.${domain}/${user}/${project}/tar.gz/${maybeEncode(committish) || 'master'}`, + extract: (url) => { + let [, user, project, type, committish] = url.pathname.split('/', 5) + if (type && type !== 'tree') { + return + } + + if (!type) { + committish = url.hash.slice(1) + } + + if (project && project.endsWith('.git')) { + project = project.slice(0, -4) + } + + if (!user || !project) { + return } + + return { user, project, committish } } -} +}) -var gitHostDefaults = { - 'sshtemplate': 'git@{domain}:{user}/{project}.git{#committish}', - 'sshurltemplate': 'git+ssh://git@{domain}/{user}/{project}.git{#committish}', - 'browsetemplate': 'https://{domain}/{user}/{project}{/tree/committish}', - 'browsefiletemplate': 'https://{domain}/{user}/{project}/{treepath}/{committish}/{path}{#fragment}', - 'docstemplate': 'https://{domain}/{user}/{project}{/tree/committish}#readme', - 'httpstemplate': 'git+https://{auth@}{domain}/{user}/{project}.git{#committish}', - 'filetemplate': 'https://{domain}/{user}/{project}/raw/{committish}/{path}', - 'shortcuttemplate': '{type}:{user}/{project}{#committish}', - 'pathtemplate': '{user}/{project}{#committish}', - 'pathmatch': /^[/]([^/]+)[/]([^/]+?)(?:[.]git|[/])?$/, - 'hashformat': formatHashFragment -} +gitHosts.bitbucket = Object.assign({}, defaults, { + protocols: ['git+ssh:', 'git+https:', 'ssh:', 'https:'], + domain: 'bitbucket.org', + treepath: 'src', + tarballtemplate: ({ domain, user, project, committish }) => `https://${domain}/${user}/${project}/get/${maybeEncode(committish) || 'master'}.tar.gz`, + extract: (url) => { + let [, user, project, aux] = url.pathname.split('/', 4) + if (['get'].includes(aux)) { + return + } + + if (project && project.endsWith('.git')) { + project = project.slice(0, -4) + } + + if (!user || !project) { + return + } + + return { user, project, committish: url.hash.slice(1) } + } +}) + +gitHosts.gitlab = Object.assign({}, defaults, { + protocols: ['git+ssh:', 'git+https:', 'ssh:', 'https:'], + domain: 'gitlab.com', + treepath: 'tree', + httpstemplate: ({ auth, domain, user, project, committish }) => `git+https://${maybeJoin(auth, '@')}${domain}/${user}/${project}.git${maybeJoin('#', committish)}`, + tarballtemplate: ({ domain, user, project, committish }) => `https://${domain}/${user}/${project}/repository/archive.tar.gz?ref=${maybeEncode(committish) || 'master'}`, + extract: (url) => { + const path = url.pathname.slice(1) + if (path.includes('/-/')) { + return + } + + const segments = path.split('/') + let project = segments.pop() + if (project.endsWith('.git')) { + project = project.slice(0, -4) + } + + const user = segments.join('/') + if (!user || !project) { + return + } + + return { user, project, committish: url.hash.slice(1) } + } +}) + +gitHosts.gist = Object.assign({}, defaults, { + protocols: ['git:', 'git+ssh:', 'git+https:', 'ssh:', 'https:'], + domain: 'gist.github.com', + sshtemplate: ({ domain, project, committish }) => `git@${domain}:${project}.git${maybeJoin('#', committish)}`, + sshurltemplate: ({ domain, project, committish }) => `git+ssh://git@${domain}/${project}.git${maybeJoin('#', committish)}`, + browsetemplate: ({ domain, project, committish }) => `https://${domain}/${project}${maybeJoin('/', maybeEncode(committish))}`, + browsefiletemplate: ({ domain, project, committish, path, hashformat }) => `https://${domain}/${project}${maybeJoin('/', maybeEncode(committish))}${maybeJoin('#', hashformat(path))}`, + docstemplate: ({ domain, project, committish }) => `https://${domain}/${project}${maybeJoin('/', maybeEncode(committish))}`, + httpstemplate: ({ domain, project, committish }) => `git+https://${domain}/${project}.git${maybeJoin('#', committish)}`, + filetemplate: ({ user, project, committish, path }) => `https://gist.githubusercontent.com/${user}/${project}/raw${maybeJoin('/', maybeEncode(committish))}/${path}`, + shortcuttemplate: ({ type, project, committish }) => `${type}:${project}${maybeJoin('#', committish)}`, + pathtemplate: ({ project, committish }) => `${project}${maybeJoin('#', committish)}`, + bugstemplate: ({ domain, project }) => `https://${domain}/${project}`, + gittemplate: ({ domain, project, committish }) => `git://${domain}/${project}.git${maybeJoin('#', committish)}`, + tarballtemplate: ({ project, committish }) => `https://codeload.github.com/gist/${project}/tar.gz/${maybeEncode(committish) || 'master'}`, + extract: (url) => { + let [, user, project, aux] = url.pathname.split('/', 4) + if (aux === 'raw') { + return + } + + if (!project) { + if (!user) { + return + } + + project = user + user = null + } + + if (project.endsWith('.git')) { + project = project.slice(0, -4) + } -Object.keys(gitHosts).forEach(function (name) { - Object.keys(gitHostDefaults).forEach(function (key) { - if (gitHosts[name][key]) return - gitHosts[name][key] = gitHostDefaults[key] - }) - gitHosts[name].protocols_re = RegExp('^(' + - gitHosts[name].protocols.map(function (protocol) { - return protocol.replace(/([\\+*{}()[\]$^|])/g, '\\$1') - }).join('|') + '):$') + return { user, project, committish: url.hash.slice(1) } + }, + hashformat: function (fragment) { + return fragment && 'file-' + formatHashFragment(fragment) + } }) +const names = Object.keys(gitHosts) +gitHosts.byShortcut = {} +gitHosts.byDomain = {} +for (const name of names) { + gitHosts.byShortcut[`${name}:`] = name + gitHosts.byDomain[gitHosts[name].domain] = name +} + function formatHashFragment (fragment) { return fragment.toLowerCase().replace(/^\W+|\/|\W+$/g, '').replace(/\W+/g, '-') } + +module.exports = gitHosts diff --git a/deps/npm/node_modules/hosted-git-info/git-host.js b/deps/npm/node_modules/hosted-git-info/git-host.js index f9b1ec7456..8a975e92e5 100644 --- a/deps/npm/node_modules/hosted-git-info/git-host.js +++ b/deps/npm/node_modules/hosted-git-info/git-host.js @@ -1,156 +1,110 @@ 'use strict' -var gitHosts = require('./git-host-info.js') -/* eslint-disable node/no-deprecated-api */ - -// copy-pasta util._extend from node's source, to avoid pulling -// the whole util module into peoples' webpack bundles. -/* istanbul ignore next */ -var extend = Object.assign || function _extend (target, source) { - // Don't do anything if source isn't an object - if (source === null || typeof source !== 'object') return target - - const keys = Object.keys(source) - let i = keys.length - while (i--) { - target[keys[i]] = source[keys[i]] - } - return target -} +const gitHosts = require('./git-host-info.js') + +class GitHost { + constructor (type, user, auth, project, committish, defaultRepresentation, opts = {}) { + Object.assign(this, gitHosts[type]) + this.type = type + this.user = user + this.auth = auth + this.project = project + this.committish = committish + this.default = defaultRepresentation + this.opts = opts + } -module.exports = GitHost -function GitHost (type, user, auth, project, committish, defaultRepresentation, opts) { - var gitHostInfo = this - gitHostInfo.type = type - Object.keys(gitHosts[type]).forEach(function (key) { - gitHostInfo[key] = gitHosts[type][key] - }) - gitHostInfo.user = user - gitHostInfo.auth = auth - gitHostInfo.project = project - gitHostInfo.committish = committish - gitHostInfo.default = defaultRepresentation - gitHostInfo.opts = opts || {} -} + hash () { + return this.committish ? `#${this.committish}` : '' + } -GitHost.prototype.hash = function () { - return this.committish ? '#' + this.committish : '' -} + ssh (opts) { + return this._fill(this.sshtemplate, opts) + } + + _fill (template, opts) { + if (typeof template === 'function') { + const options = { ...this, ...this.opts, ...opts } + + // the path should always be set so we don't end up with 'undefined' in urls + if (!options.path) { + options.path = '' + } + + // template functions will insert the leading slash themselves + if (options.path.startsWith('/')) { + options.path = options.path.slice(1) + } -GitHost.prototype._fill = function (template, opts) { - if (!template) return - var vars = extend({}, opts) - vars.path = vars.path ? vars.path.replace(/^[/]+/g, '') : '' - opts = extend(extend({}, this.opts), opts) - var self = this - Object.keys(this).forEach(function (key) { - if (self[key] != null && vars[key] == null) vars[key] = self[key] - }) - var rawAuth = vars.auth - var rawcommittish = vars.committish - var rawFragment = vars.fragment - var rawPath = vars.path - var rawProject = vars.project - Object.keys(vars).forEach(function (key) { - var value = vars[key] - if ((key === 'path' || key === 'project') && typeof value === 'string') { - vars[key] = value.split('/').map(function (pathComponent) { - return encodeURIComponent(pathComponent) - }).join('/') - } else if (key !== 'domain') { - vars[key] = encodeURIComponent(value) + if (options.noCommittish) { + options.committish = null + } + + const result = template(options) + return options.noGitPlus && result.startsWith('git+') ? result.slice(4) : result } - }) - vars['auth@'] = rawAuth ? rawAuth + '@' : '' - vars['#fragment'] = rawFragment ? '#' + this.hashformat(rawFragment) : '' - vars.fragment = vars.fragment ? vars.fragment : '' - vars['#path'] = rawPath ? '#' + this.hashformat(rawPath) : '' - vars['/path'] = vars.path ? '/' + vars.path : '' - vars.projectPath = rawProject.split('/').map(encodeURIComponent).join('/') - if (opts.noCommittish) { - vars['#committish'] = '' - vars['/tree/committish'] = '' - vars['/committish'] = '' - vars.committish = '' - } else { - vars['#committish'] = rawcommittish ? '#' + rawcommittish : '' - vars['/tree/committish'] = vars.committish - ? '/' + vars.treepath + '/' + vars.committish - : '' - vars['/committish'] = vars.committish ? '/' + vars.committish : '' - vars.committish = vars.committish || 'master' - } - var res = template - Object.keys(vars).forEach(function (key) { - res = res.replace(new RegExp('[{]' + key + '[}]', 'g'), vars[key]) - }) - if (opts.noGitPlus) { - return res.replace(/^git[+]/, '') - } else { - return res + + return null } -} -GitHost.prototype.ssh = function (opts) { - return this._fill(this.sshtemplate, opts) -} + sshurl (opts) { + return this._fill(this.sshurltemplate, opts) + } -GitHost.prototype.sshurl = function (opts) { - return this._fill(this.sshurltemplate, opts) -} + browse (path, fragment, opts) { + // not a string, treat path as opts + if (typeof path !== 'string') { + return this._fill(this.browsetemplate, path) + } -GitHost.prototype.browse = function (P, F, opts) { - if (typeof P === 'string') { - if (typeof F !== 'string') { - opts = F - F = null + if (typeof fragment !== 'string') { + opts = fragment + fragment = null } - return this._fill(this.browsefiletemplate, extend({ - fragment: F, - path: P - }, opts)) - } else { - return this._fill(this.browsetemplate, P) + return this._fill(this.browsefiletemplate, { ...opts, fragment, path }) } -} -GitHost.prototype.docs = function (opts) { - return this._fill(this.docstemplate, opts) -} + docs (opts) { + return this._fill(this.docstemplate, opts) + } -GitHost.prototype.bugs = function (opts) { - return this._fill(this.bugstemplate, opts) -} + bugs (opts) { + return this._fill(this.bugstemplate, opts) + } -GitHost.prototype.https = function (opts) { - return this._fill(this.httpstemplate, opts) -} + https (opts) { + return this._fill(this.httpstemplate, opts) + } -GitHost.prototype.git = function (opts) { - return this._fill(this.gittemplate, opts) -} + git (opts) { + return this._fill(this.gittemplate, opts) + } -GitHost.prototype.shortcut = function (opts) { - return this._fill(this.shortcuttemplate, opts) -} + shortcut (opts) { + return this._fill(this.shortcuttemplate, opts) + } -GitHost.prototype.path = function (opts) { - return this._fill(this.pathtemplate, opts) -} + path (opts) { + return this._fill(this.pathtemplate, opts) + } -GitHost.prototype.tarball = function (opts_) { - var opts = extend({}, opts_, { noCommittish: false }) - return this._fill(this.tarballtemplate, opts) -} + tarball (opts) { + return this._fill(this.tarballtemplate, { ...opts, noCommittish: false }) + } -GitHost.prototype.file = function (P, opts) { - return this._fill(this.filetemplate, extend({ path: P }, opts)) -} + file (path, opts) { + return this._fill(this.filetemplate, { ...opts, path }) + } -GitHost.prototype.getDefaultRepresentation = function () { - return this.default -} + getDefaultRepresentation () { + return this.default + } + + toString (opts) { + if (this.default && typeof this[this.default] === 'function') { + return this[this.default](opts) + } -GitHost.prototype.toString = function (opts) { - if (this.default && typeof this[this.default] === 'function') return this[this.default](opts) - return this.sshurl(opts) + return this.sshurl(opts) + } } +module.exports = GitHost diff --git a/deps/npm/node_modules/hosted-git-info/index.js b/deps/npm/node_modules/hosted-git-info/index.js index 8b3eaba3da..f35c570c46 100644 --- a/deps/npm/node_modules/hosted-git-info/index.js +++ b/deps/npm/node_modules/hosted-git-info/index.js @@ -1,11 +1,11 @@ 'use strict' -var url = require('url') -var gitHosts = require('./git-host-info.js') -var GitHost = module.exports = require('./git-host.js') -var LRU = require('lru-cache') -var cache = new LRU({max: 1000}) +const url = require('url') +const gitHosts = require('./git-host-info.js') +const GitHost = module.exports = require('./git-host.js') +const LRU = require('lru-cache') +const cache = new LRU({ max: 1000 }) -var protocolToRepresentationMap = { +const protocolToRepresentationMap = { 'git+ssh:': 'sshurl', 'git+https:': 'https', 'ssh:': 'sshurl', @@ -16,7 +16,7 @@ function protocolToRepresentation (protocol) { return protocolToRepresentationMap[protocol] || protocol.slice(0, -1) } -var authProtocols = { +const authProtocols = { 'git:': true, 'https:': true, 'git+https:': true, @@ -24,9 +24,14 @@ var authProtocols = { 'git+http:': true } +const knownProtocols = Object.keys(gitHosts.byShortcut).concat(['http:', 'https:', 'git:', 'git+ssh:', 'git+https:', 'ssh:']) + module.exports.fromUrl = function (giturl, opts) { - if (typeof giturl !== 'string') return - var key = giturl + JSON.stringify(opts || {}) + if (typeof giturl !== 'string') { + return + } + + const key = giturl + JSON.stringify(opts || {}) if (!cache.has(key)) { cache.set(key, fromUrl(giturl, opts)) @@ -36,111 +41,197 @@ module.exports.fromUrl = function (giturl, opts) { } function fromUrl (giturl, opts) { - if (giturl == null || giturl === '') return - var url = fixupUnqualifiedGist( - isGitHubShorthand(giturl) ? 'github:' + giturl : giturl - ) - var parsed = parseGitUrl(url) - var shortcutMatch = url.match(/^([^:]+):(?:[^@]+@)?(?:([^/]*)\/)?([^#]+)/) - var matches = Object.keys(gitHosts).map(function (gitHostName) { - try { - var gitHostInfo = gitHosts[gitHostName] - var auth = null - if (parsed.auth && authProtocols[parsed.protocol]) { - auth = parsed.auth + if (!giturl) { + return + } + + const url = isGitHubShorthand(giturl) ? 'github:' + giturl : correctProtocol(giturl) + const parsed = parseGitUrl(url) + if (!parsed) { + return parsed + } + + const gitHostShortcut = gitHosts.byShortcut[parsed.protocol] + const gitHostDomain = gitHosts.byDomain[parsed.hostname.startsWith('www.') ? parsed.hostname.slice(4) : parsed.hostname] + const gitHostName = gitHostShortcut || gitHostDomain + if (!gitHostName) { + return + } + + const gitHostInfo = gitHosts[gitHostShortcut || gitHostDomain] + let auth = null + if (authProtocols[parsed.protocol] && (parsed.username || parsed.password)) { + auth = `${parsed.username}${parsed.password ? ':' + parsed.password : ''}` + } + + let committish = null + let user = null + let project = null + let defaultRepresentation = null + + try { + if (gitHostShortcut) { + let pathname = parsed.pathname.startsWith('/') ? parsed.pathname.slice(1) : parsed.pathname + const firstAt = pathname.indexOf('@') + // we ignore auth for shortcuts, so just trim it out + if (firstAt > -1) { + pathname = pathname.slice(firstAt + 1) } - var committish = parsed.hash ? decodeURIComponent(parsed.hash.substr(1)) : null - var user = null - var project = null - var defaultRepresentation = null - if (shortcutMatch && shortcutMatch[1] === gitHostName) { - user = shortcutMatch[2] && decodeURIComponent(shortcutMatch[2]) - project = decodeURIComponent(shortcutMatch[3].replace(/\.git$/, '')) - defaultRepresentation = 'shortcut' - } else { - if (parsed.host && parsed.host !== gitHostInfo.domain && parsed.host.replace(/^www[.]/, '') !== gitHostInfo.domain) return - if (!gitHostInfo.protocols_re.test(parsed.protocol)) return - if (!parsed.path) return - var pathmatch = gitHostInfo.pathmatch - var matched = parsed.path.match(pathmatch) - if (!matched) return - /* istanbul ignore else */ - if (matched[1] !== null && matched[1] !== undefined) { - user = decodeURIComponent(matched[1].replace(/^:/, '')) + + const lastSlash = pathname.lastIndexOf('/') + if (lastSlash > -1) { + user = decodeURIComponent(pathname.slice(0, lastSlash)) + // we want nulls only, never empty strings + if (!user) { + user = null } - project = decodeURIComponent(matched[2]) - defaultRepresentation = protocolToRepresentation(parsed.protocol) + project = decodeURIComponent(pathname.slice(lastSlash + 1)) + } else { + project = decodeURIComponent(pathname) + } + + if (project.endsWith('.git')) { + project = project.slice(0, -4) + } + + if (parsed.hash) { + committish = decodeURIComponent(parsed.hash.slice(1)) + } + + defaultRepresentation = 'shortcut' + } else { + if (!gitHostInfo.protocols.includes(parsed.protocol)) { + return } - return new GitHost(gitHostName, user, auth, project, committish, defaultRepresentation, opts) - } catch (ex) { - /* istanbul ignore else */ - if (ex instanceof URIError) { - } else throw ex + + const segments = gitHostInfo.extract(parsed) + if (!segments) { + return + } + + user = segments.user && decodeURIComponent(segments.user) + project = decodeURIComponent(segments.project) + committish = decodeURIComponent(segments.committish) + defaultRepresentation = protocolToRepresentation(parsed.protocol) } - }).filter(function (gitHostInfo) { return gitHostInfo }) - if (matches.length !== 1) return - return matches[0] -} + } catch (err) { + /* istanbul ignore else */ + if (err instanceof URIError) { + return + } else { + throw err + } + } -function isGitHubShorthand (arg) { - // Note: This does not fully test the git ref format. - // See https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html - // - // The only way to do this properly would be to shell out to - // git-check-ref-format, and as this is a fast sync function, - // we don't want to do that. Just let git fail if it turns - // out that the commit-ish is invalid. - // GH usernames cannot start with . or - - return /^[^:@%/\s.-][^:@%/\s]*[/][^:@\s/%]+(?:#.*)?$/.test(arg) + return new GitHost(gitHostName, user, auth, project, committish, defaultRepresentation, opts) } -function fixupUnqualifiedGist (giturl) { - // necessary for round-tripping gists - var parsed = url.parse(giturl) - if (parsed.protocol === 'gist:' && parsed.host && !parsed.path) { - return parsed.protocol + '/' + parsed.host - } else { - return giturl +// accepts input like git:github.com:user/repo and inserts the // after the first : +const correctProtocol = (arg) => { + const firstColon = arg.indexOf(':') + const proto = arg.slice(0, firstColon + 1) + if (knownProtocols.includes(proto)) { + return arg } -} -function parseGitUrl (giturl) { - var matched = giturl.match(/^([^@]+)@([^:/]+):[/]?((?:[^/]+[/])?[^/]+?)(?:[.]git)?(#.*)?$/) - if (!matched) { - var legacy = url.parse(giturl) - if (legacy.auth) { - // git urls can be in the form of scp-style/ssh-connect strings, like - // git+ssh://user@host.com:some/path, which the legacy url parser - // supports, but WhatWG url.URL class does not. However, the legacy - // parser de-urlencodes the username and password, so something like - // https://user%3An%40me:p%40ss%3Aword@x.com/ becomes - // https://user:n@me:p@ss:word@x.com/ which is all kinds of wrong. - // Pull off just the auth and host, so we dont' get the confusing - // scp-style URL, then pass that to the WhatWG parser to get the - // auth properly escaped. - const authmatch = giturl.match(/[^@]+@[^:/]+/) - /* istanbul ignore else - this should be impossible */ - if (authmatch) { - var whatwg = new url.URL(authmatch[0]) - legacy.auth = whatwg.username || '' - if (whatwg.password) legacy.auth += ':' + whatwg.password - } + const firstAt = arg.indexOf('@') + if (firstAt > -1) { + if (firstAt > firstColon) { + return `git+ssh://${arg}` + } else { + return arg } - return legacy } - return { - protocol: 'git+ssh:', - slashes: true, - auth: matched[1], - host: matched[2], - port: null, - hostname: matched[2], - hash: matched[4], - search: null, - query: null, - pathname: '/' + matched[3], - path: '/' + matched[3], - href: 'git+ssh://' + matched[1] + '@' + matched[2] + - '/' + matched[3] + (matched[4] || '') + + const doubleSlash = arg.indexOf('//') + if (doubleSlash === firstColon + 1) { + return arg + } + + return arg.slice(0, firstColon + 1) + '//' + arg.slice(firstColon + 1) +} + +// look for github shorthand inputs, such as npm/cli +const isGitHubShorthand = (arg) => { + // it cannot contain whitespace before the first # + // it cannot start with a / because that's probably an absolute file path + // but it must include a slash since repos are username/repository + // it cannot start with a . because that's probably a relative file path + // it cannot start with an @ because that's a scoped package if it passes the other tests + // it cannot contain a : before a # because that tells us that there's a protocol + // a second / may not exist before a # + const firstHash = arg.indexOf('#') + const firstSlash = arg.indexOf('/') + const secondSlash = arg.indexOf('/', firstSlash + 1) + const firstColon = arg.indexOf(':') + const firstSpace = /\s/.exec(arg) + const firstAt = arg.indexOf('@') + + const spaceOnlyAfterHash = !firstSpace || (firstHash > -1 && firstSpace.index > firstHash) + const atOnlyAfterHash = firstAt === -1 || (firstHash > -1 && firstAt > firstHash) + const colonOnlyAfterHash = firstColon === -1 || (firstHash > -1 && firstColon > firstHash) + const secondSlashOnlyAfterHash = secondSlash === -1 || (firstHash > -1 && secondSlash > firstHash) + const hasSlash = firstSlash > 0 + // if a # is found, what we really want to know is that the character immediately before # is not a / + const doesNotEndWithSlash = firstHash > -1 ? arg[firstHash - 1] !== '/' : !arg.endsWith('/') + const doesNotStartWithDot = !arg.startsWith('.') + + return spaceOnlyAfterHash && hasSlash && doesNotEndWithSlash && doesNotStartWithDot && atOnlyAfterHash && colonOnlyAfterHash && secondSlashOnlyAfterHash +} + +// attempt to correct an scp style url so that it will parse with `new URL()` +const correctUrl = (giturl) => { + const firstAt = giturl.indexOf('@') + const lastHash = giturl.lastIndexOf('#') + let firstColon = giturl.indexOf(':') + let lastColon = giturl.lastIndexOf(':', lastHash > -1 ? lastHash : Infinity) + + let corrected + if (lastColon > firstAt) { + // the last : comes after the first @ (or there is no @) + // like it would in: + // proto://hostname.com:user/repo + // username@hostname.com:user/repo + // :password@hostname.com:user/repo + // username:password@hostname.com:user/repo + // proto://username@hostname.com:user/repo + // proto://:password@hostname.com:user/repo + // proto://username:password@hostname.com:user/repo + // then we replace the last : with a / to create a valid path + corrected = giturl.slice(0, lastColon) + '/' + giturl.slice(lastColon + 1) + // // and we find our new : positions + firstColon = corrected.indexOf(':') + lastColon = corrected.lastIndexOf(':') + } + + if (firstColon === -1 && giturl.indexOf('//') === -1) { + // we have no : at all + // as it would be in: + // username@hostname.com/user/repo + // then we prepend a protocol + corrected = `git+ssh://${corrected}` + } + + return corrected +} + +// try to parse the url as its given to us, if that throws +// then we try to clean the url and parse that result instead +// THIS FUNCTION SHOULD NEVER THROW +const parseGitUrl = (giturl) => { + let result + try { + result = new url.URL(giturl) + } catch (err) {} + + if (result) { + return result } + + const correctedUrl = correctUrl(giturl) + try { + result = new url.URL(correctedUrl) + } catch (err) {} + + return result } diff --git a/deps/npm/node_modules/hosted-git-info/package.json b/deps/npm/node_modules/hosted-git-info/package.json index 32712269f0..930e3b693b 100644 --- a/deps/npm/node_modules/hosted-git-info/package.json +++ b/deps/npm/node_modules/hosted-git-info/package.json @@ -1,7 +1,7 @@ { "name": "hosted-git-info", - "version": "3.0.8", - "description": "Provides metadata and conversions from repository urls for Github, Bitbucket and Gitlab", + "version": "4.0.1", + "description": "Provides metadata and conversions from repository urls for GitHub, Bitbucket and GitLab", "main": "index.js", "repository": { "type": "git", @@ -20,20 +20,21 @@ }, "homepage": "https://github.com/npm/hosted-git-info", "scripts": { - "prerelease": "npm t", - "postrelease": "npm publish && git push --follow-tags", "posttest": "standard", - "release": "standard-version -s", - "test:coverage": "tap --coverage-report=html -J --100 --no-esm test/*.js", - "test": "tap -J --100 --no-esm test/*.js" + "postversion": "npm publish", + "prepublishOnly": "git push origin --follow-tags", + "preversion": "npm test", + "snap": "tap", + "test": "tap", + "test:coverage": "tap --coverage-report=html" }, "dependencies": { "lru-cache": "^6.0.0" }, "devDependencies": { - "standard": "^11.0.1", - "standard-version": "^4.4.0", - "tap": "^12.7.0" + "standard": "^16.0.3", + "standard-version": "^9.1.0", + "tap": "^14.11.0" }, "files": [ "index.js", @@ -42,5 +43,10 @@ ], "engines": { "node": ">=10" + }, + "tap": { + "color": 1, + "coverage": true, + "esm": false } } diff --git a/deps/npm/node_modules/libnpmversion/lib/index.js b/deps/npm/node_modules/libnpmversion/lib/index.js index 525d8264e7..c3f554834b 100644 --- a/deps/npm/node_modules/libnpmversion/lib/index.js +++ b/deps/npm/node_modules/libnpmversion/lib/index.js @@ -1,4 +1,4 @@ -const readJson = require('read-package-json-fast') +const readJson = require('./read-json.js') const version = require('./version.js') const proclog = require('./proc-log.js') diff --git a/deps/npm/node_modules/libnpmversion/lib/read-json.js b/deps/npm/node_modules/libnpmversion/lib/read-json.js new file mode 100644 index 0000000000..0a1f64f2f7 --- /dev/null +++ b/deps/npm/node_modules/libnpmversion/lib/read-json.js @@ -0,0 +1,7 @@ +// can't use read-package-json-fast, because we want to ensure +// that we make as few changes as possible, even for safety issues. +const {promisify} = require('util') +const readFile = promisify(require('fs').readFile) +const parse = require('json-parse-even-better-errors') + +module.exports = async path => parse(await readFile(path)) diff --git a/deps/npm/node_modules/libnpmversion/lib/version.js b/deps/npm/node_modules/libnpmversion/lib/version.js index 31e6023f01..0fe1ea6213 100644 --- a/deps/npm/node_modules/libnpmversion/lib/version.js +++ b/deps/npm/node_modules/libnpmversion/lib/version.js @@ -4,7 +4,7 @@ const retrieveTag = require('./retrieve-tag.js') const semver = require('semver') const enforceClean = require('./enforce-clean.js') const writeJson = require('./write-json.js') -const readJson = require('read-package-json-fast') +const readJson = require('./read-json.js') const git = require('@npmcli/git') const commit = require('./commit.js') const tag = require('./tag.js') diff --git a/deps/npm/node_modules/libnpmversion/package.json b/deps/npm/node_modules/libnpmversion/package.json index 3d15bbc2f7..0135c21e72 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.11", + "version": "1.0.12", "main": "lib/index.js", "files": [ "lib/*.js" @@ -30,7 +30,7 @@ "dependencies": { "@npmcli/git": "^2.0.6", "@npmcli/run-script": "^1.8.3", - "read-package-json-fast": "^2.0.1", + "json-parse-even-better-errors": "^2.3.1", "semver": "^7.3.4", "stringify-package": "^1.0.1" } diff --git a/deps/npm/node_modules/normalize-package-data/README.md b/deps/npm/node_modules/normalize-package-data/README.md index d2bd7bc7ff..84da5e8bcf 100644 --- a/deps/npm/node_modules/normalize-package-data/README.md +++ b/deps/npm/node_modules/normalize-package-data/README.md @@ -1,4 +1,6 @@ -# normalize-package-data [![Build Status](https://travis-ci.org/npm/normalize-package-data.png?branch=master)](https://travis-ci.org/npm/normalize-package-data) +# normalize-package-data + +[![Build Status](https://travis-ci.org/npm/normalize-package-data.svg?branch=master)](https://travis-ci.org/npm/normalize-package-data) normalize-package-data exports a function that normalizes package metadata. This data is typically found in a package.json file, but in principle could come from any source - for example the npm registry. diff --git a/deps/npm/node_modules/normalize-package-data/node_modules/hosted-git-info/CHANGELOG.md b/deps/npm/node_modules/normalize-package-data/node_modules/hosted-git-info/CHANGELOG.md new file mode 100644 index 0000000000..3ffcacacc5 --- /dev/null +++ b/deps/npm/node_modules/normalize-package-data/node_modules/hosted-git-info/CHANGELOG.md @@ -0,0 +1,185 @@ +# Change Log + +All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. + +<a name="3.0.8"></a> +## [3.0.8](https://github.com/npm/hosted-git-info/compare/v3.0.7...v3.0.8) (2021-01-28) + + +### Bug Fixes + +* simplify the regular expression for shortcut matching ([bede0dc](https://github.com/npm/hosted-git-info/commit/bede0dc)), closes [#76](https://github.com/npm/hosted-git-info/issues/76) + + + +<a name="3.0.7"></a> +## [3.0.7](https://github.com/npm/hosted-git-info/compare/v3.0.6...v3.0.7) (2020-10-15) + + +### Bug Fixes + +* correctly filter out urls for tarballs in gitlab ([eb5bd5a](https://github.com/npm/hosted-git-info/commit/eb5bd5a)), closes [#69](https://github.com/npm/hosted-git-info/issues/69) + + + +<a name="3.0.6"></a> +## [3.0.6](https://github.com/npm/hosted-git-info/compare/v3.0.5...v3.0.6) (2020-10-12) + + +### Bug Fixes + +* support to github gist legacy hash length ([c067102](https://github.com/npm/hosted-git-info/commit/c067102)), closes [#68](https://github.com/npm/hosted-git-info/issues/68) + + + +<a name="3.0.5"></a> +## [3.0.5](https://github.com/npm/hosted-git-info/compare/v3.0.4...v3.0.5) (2020-07-11) + + + +<a name="3.0.4"></a> +## [3.0.4](https://github.com/npm/hosted-git-info/compare/v3.0.3...v3.0.4) (2020-02-26) + + +### Bug Fixes + +* Do not pass scp-style URLs to the WhatWG url.URL ([0835306](https://github.com/npm/hosted-git-info/commit/0835306)), closes [#60](https://github.com/npm/hosted-git-info/issues/60) [#63](https://github.com/npm/hosted-git-info/issues/63) + + + +<a name="3.0.3"></a> +## [3.0.3](https://github.com/npm/hosted-git-info/compare/v3.0.2...v3.0.3) (2020-02-25) + + + +<a name="3.0.2"></a> +## [3.0.2](https://github.com/npm/hosted-git-info/compare/v3.0.1...v3.0.2) (2019-10-08) + + +### Bug Fixes + +* do not encodeURIComponent the domain ([3e5fbec](https://github.com/npm/hosted-git-info/commit/3e5fbec)), closes [#53](https://github.com/npm/hosted-git-info/issues/53) + + + +<a name="3.0.1"></a> +## [3.0.1](https://github.com/npm/hosted-git-info/compare/v3.0.0...v3.0.1) (2019-10-07) + + +### Bug Fixes + +* update pathmatch for gitlab ([e3e3054](https://github.com/npm/hosted-git-info/commit/e3e3054)), closes [#52](https://github.com/npm/hosted-git-info/issues/52) +* updated pathmatch for gitlab ([fa87af7](https://github.com/npm/hosted-git-info/commit/fa87af7)) + + + +<a name="3.0.0"></a> +# [3.0.0](https://github.com/npm/hosted-git-info/compare/v2.8.3...v3.0.0) (2019-08-12) + + +### Bug Fixes + +* **cache:** Switch to lru-cache to save ourselves from unlimited memory consumption ([37c2891](https://github.com/npm/hosted-git-info/commit/37c2891)), closes [#38](https://github.com/npm/hosted-git-info/issues/38) + + +### BREAKING CHANGES + +* **cache:** Drop support for node 0.x + + + +<a name="2.8.3"></a> +## [2.8.3](https://github.com/npm/hosted-git-info/compare/v2.8.2...v2.8.3) (2019-08-12) + + + +<a name="2.8.2"></a> +## [2.8.2](https://github.com/npm/hosted-git-info/compare/v2.8.1...v2.8.2) (2019-08-05) + + +### Bug Fixes + +* http protocol use sshurl by default ([3b1d629](https://github.com/npm/hosted-git-info/commit/3b1d629)), closes [#48](https://github.com/npm/hosted-git-info/issues/48) + + + +<a name="2.8.1"></a> +## [2.8.1](https://github.com/npm/hosted-git-info/compare/v2.8.0...v2.8.1) (2019-08-05) + + +### Bug Fixes + +* ignore noCommittish on tarball url generation ([5d4a8d7](https://github.com/npm/hosted-git-info/commit/5d4a8d7)) +* use gist tarball url that works for anonymous gists ([1692435](https://github.com/npm/hosted-git-info/commit/1692435)) + + + +<a name="2.8.0"></a> +# [2.8.0](https://github.com/npm/hosted-git-info/compare/v2.7.1...v2.8.0) (2019-08-05) + + +### Bug Fixes + +* Allow slashes in gitlab project section ([bbcf7b2](https://github.com/npm/hosted-git-info/commit/bbcf7b2)), closes [#46](https://github.com/npm/hosted-git-info/issues/46) [#43](https://github.com/npm/hosted-git-info/issues/43) +* **git-host:** disallow URI-encoded slash (%2F) in `path` ([3776fa5](https://github.com/npm/hosted-git-info/commit/3776fa5)), closes [#44](https://github.com/npm/hosted-git-info/issues/44) +* **gitlab:** Do not URL encode slashes in project name for GitLab https URL ([cbf04f9](https://github.com/npm/hosted-git-info/commit/cbf04f9)), closes [#47](https://github.com/npm/hosted-git-info/issues/47) +* do not allow invalid gist urls ([d5cf830](https://github.com/npm/hosted-git-info/commit/d5cf830)) +* **cache:** Switch to lru-cache to save ourselves from unlimited memory consumption ([e518222](https://github.com/npm/hosted-git-info/commit/e518222)), closes [#38](https://github.com/npm/hosted-git-info/issues/38) + + +### Features + +* give these objects a name ([60abaea](https://github.com/npm/hosted-git-info/commit/60abaea)) + + + +<a name="2.7.1"></a> +## [2.7.1](https://github.com/npm/hosted-git-info/compare/v2.7.0...v2.7.1) (2018-07-07) + + +### Bug Fixes + +* **index:** Guard against non-string types ([5bc580d](https://github.com/npm/hosted-git-info/commit/5bc580d)) +* **parse:** Crash on strings that parse to having no host ([c931482](https://github.com/npm/hosted-git-info/commit/c931482)), closes [#35](https://github.com/npm/hosted-git-info/issues/35) + + + +<a name="2.7.0"></a> +# [2.7.0](https://github.com/npm/hosted-git-info/compare/v2.6.1...v2.7.0) (2018-07-06) + + +### Bug Fixes + +* **github tarball:** update github tarballtemplate ([6efd582](https://github.com/npm/hosted-git-info/commit/6efd582)), closes [#34](https://github.com/npm/hosted-git-info/issues/34) +* **gitlab docs:** switched to lowercase anchors for readmes ([701bcd1](https://github.com/npm/hosted-git-info/commit/701bcd1)) + + +### Features + +* **all:** Support www. prefixes on hostnames ([3349575](https://github.com/npm/hosted-git-info/commit/3349575)), closes [#32](https://github.com/npm/hosted-git-info/issues/32) + + + +<a name="2.6.1"></a> +## [2.6.1](https://github.com/npm/hosted-git-info/compare/v2.6.0...v2.6.1) (2018-06-25) + +### Bug Fixes + +* **Revert:** "compat: remove Object.assign fallback ([#25](https://github.com/npm/hosted-git-info/issues/25))" ([cce5a62](https://github.com/npm/hosted-git-info/commit/cce5a62)) +* **Revert:** "git-host: fix forgotten extend()" ([a815ec9](https://github.com/npm/hosted-git-info/commit/a815ec9)) + + + +<a name="2.6.0"></a> +# [2.6.0](https://github.com/npm/hosted-git-info/compare/v2.5.0...v2.6.0) (2018-03-07) + + +### Bug Fixes + +* **compat:** remove Object.assign fallback ([#25](https://github.com/npm/hosted-git-info/issues/25)) ([627ab55](https://github.com/npm/hosted-git-info/commit/627ab55)) +* **git-host:** fix forgotten extend() ([eba1f7b](https://github.com/npm/hosted-git-info/commit/eba1f7b)) + + +### Features + +* **browse:** fragment support for browse() ([#28](https://github.com/npm/hosted-git-info/issues/28)) ([cd5e5bb](https://github.com/npm/hosted-git-info/commit/cd5e5bb)) diff --git a/deps/npm/node_modules/normalize-package-data/node_modules/hosted-git-info/LICENSE b/deps/npm/node_modules/normalize-package-data/node_modules/hosted-git-info/LICENSE new file mode 100644 index 0000000000..45055763dc --- /dev/null +++ b/deps/npm/node_modules/normalize-package-data/node_modules/hosted-git-info/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2015, Rebecca Turner + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. diff --git a/deps/npm/node_modules/normalize-package-data/node_modules/hosted-git-info/README.md b/deps/npm/node_modules/normalize-package-data/node_modules/hosted-git-info/README.md new file mode 100644 index 0000000000..8740406029 --- /dev/null +++ b/deps/npm/node_modules/normalize-package-data/node_modules/hosted-git-info/README.md @@ -0,0 +1,133 @@ +# hosted-git-info + +This will let you identify and transform various git hosts URLs between +protocols. It also can tell you what the URL is for the raw path for +particular file for direct access without git. + +## Example + +```javascript +var hostedGitInfo = require("hosted-git-info") +var info = hostedGitInfo.fromUrl("git@github.com:npm/hosted-git-info.git", opts) +/* info looks like: +{ + type: "github", + domain: "github.com", + user: "npm", + project: "hosted-git-info" +} +*/ +``` + +If the URL can't be matched with a git host, `null` will be returned. We +can match git, ssh and https urls. Additionally, we can match ssh connect +strings (`git@github.com:npm/hosted-git-info`) and shortcuts (eg, +`github:npm/hosted-git-info`). GitHub specifically, is detected in the case +of a third, unprefixed, form: `npm/hosted-git-info`. + +If it does match, the returned object has properties of: + +* info.type -- The short name of the service +* info.domain -- The domain for git protocol use +* info.user -- The name of the user/org on the git host +* info.project -- The name of the project on the git host + +## Version Contract + +The major version will be bumped any time… + +* The constructor stops accepting URLs that it previously accepted. +* A method is removed. +* A method can no longer accept the number and type of arguments it previously accepted. +* A method can return a different type than it currently returns. + +Implications: + +* I do not consider the specific format of the urls returned from, say + `.https()` to be a part of the contract. The contract is that it will + return a string that can be used to fetch the repo via HTTPS. But what + that string looks like, specifically, can change. +* Dropping support for a hosted git provider would constitute a breaking + change. + +## Usage + +### var info = hostedGitInfo.fromUrl(gitSpecifier[, options]) + +* *gitSpecifer* is a URL of a git repository or a SCP-style specifier of one. +* *options* is an optional object. It can have the following properties: + * *noCommittish* — If true then committishes won't be included in generated URLs. + * *noGitPlus* — If true then `git+` won't be prefixed on URLs. + +## Methods + +All of the methods take the same options as the `fromUrl` factory. Options +provided to a method override those provided to the constructor. + +* info.file(path, opts) + +Given the path of a file relative to the repository, returns a URL for +directly fetching it from the githost. If no committish was set then +`master` will be used as the default. + +For example `hostedGitInfo.fromUrl("git@github.com:npm/hosted-git-info.git#v1.0.0").file("package.json")` +would return `https://raw.githubusercontent.com/npm/hosted-git-info/v1.0.0/package.json` + +* info.shortcut(opts) + +eg, `github:npm/hosted-git-info` + +* info.browse(path, fragment, opts) + +eg, `https://github.com/npm/hosted-git-info/tree/v1.2.0`, +`https://github.com/npm/hosted-git-info/tree/v1.2.0/package.json`, +`https://github.com/npm/hosted-git-info/tree/v1.2.0/REAMDE.md#supported-hosts` + +* info.bugs(opts) + +eg, `https://github.com/npm/hosted-git-info/issues` + +* info.docs(opts) + +eg, `https://github.com/npm/hosted-git-info/tree/v1.2.0#readme` + +* info.https(opts) + +eg, `git+https://github.com/npm/hosted-git-info.git` + +* info.sshurl(opts) + +eg, `git+ssh://git@github.com/npm/hosted-git-info.git` + +* info.ssh(opts) + +eg, `git@github.com:npm/hosted-git-info.git` + +* info.path(opts) + +eg, `npm/hosted-git-info` + +* info.tarball(opts) + +eg, `https://github.com/npm/hosted-git-info/archive/v1.2.0.tar.gz` + +* info.getDefaultRepresentation() + +Returns the default output type. The default output type is based on the +string you passed in to be parsed + +* info.toString(opts) + +Uses the getDefaultRepresentation to call one of the other methods to get a URL for +this resource. As such `hostedGitInfo.fromUrl(url).toString()` will give +you a normalized version of the URL that still uses the same protocol. + +Shortcuts will still be returned as shortcuts, but the special case github +form of `org/project` will be normalized to `github:org/project`. + +SSH connect strings will be normalized into `git+ssh` URLs. + +## Supported hosts + +Currently this supports GitHub, Bitbucket and GitLab. Pull requests for +additional hosts welcome. diff --git a/deps/npm/node_modules/normalize-package-data/node_modules/hosted-git-info/git-host-info.js b/deps/npm/node_modules/normalize-package-data/node_modules/hosted-git-info/git-host-info.js new file mode 100644 index 0000000000..360d7b096b --- /dev/null +++ b/deps/npm/node_modules/normalize-package-data/node_modules/hosted-git-info/git-host-info.js @@ -0,0 +1,154 @@ +'use strict' +const maybeJoin = (...args) => args.every(arg => arg) ? args.join('') : '' +const maybeEncode = (arg) => arg ? encodeURIComponent(arg) : '' + +const defaults = { + sshtemplate: ({ domain, user, project, committish }) => `git@${domain}:${user}/${project}.git${maybeJoin('#', committish)}`, + sshurltemplate: ({ domain, user, project, committish }) => `git+ssh://git@${domain}/${user}/${project}.git${maybeJoin('#', committish)}`, + browsetemplate: ({ domain, user, project, committish, treepath }) => `https://${domain}/${user}/${project}${maybeJoin('/', treepath, '/', maybeEncode(committish))}`, + browsefiletemplate: ({ domain, user, project, committish, treepath, path, fragment, hashformat }) => `https://${domain}/${user}/${project}/${treepath}/${maybeEncode(committish || 'master')}/${path}${maybeJoin('#', hashformat(fragment || ''))}`, + docstemplate: ({ domain, user, project, treepath, committish }) => `https://${domain}/${user}/${project}${maybeJoin('/', treepath, '/', maybeEncode(committish))}#readme`, + httpstemplate: ({ auth, domain, user, project, committish }) => `git+https://${maybeJoin(auth, '@')}${domain}/${user}/${project}.git${maybeJoin('#', committish)}`, + filetemplate: ({ domain, user, project, committish, path }) => `https://${domain}/${user}/${project}/raw/${maybeEncode(committish) || 'master'}/${path}`, + shortcuttemplate: ({ type, user, project, committish }) => `${type}:${user}/${project}${maybeJoin('#', committish)}`, + pathtemplate: ({ user, project, committish }) => `${user}/${project}${maybeJoin('#', committish)}`, + bugstemplate: ({ domain, user, project }) => `https://${domain}/${user}/${project}/issues`, + hashformat: formatHashFragment +} + +const gitHosts = {} +gitHosts.github = Object.assign({}, defaults, { + // First two are insecure and generally shouldn't be used any more, but + // they are still supported. + protocols: ['git:', 'http:', 'git+ssh:', 'git+https:', 'ssh:', 'https:'], + domain: 'github.com', + treepath: 'tree', + filetemplate: ({ auth, user, project, committish, path }) => `https://${maybeJoin(auth, '@')}raw.githubusercontent.com/${user}/${project}/${maybeEncode(committish) || 'master'}/${path}`, + gittemplate: ({ auth, domain, user, project, committish }) => `git://${maybeJoin(auth, '@')}${domain}/${user}/${project}.git${maybeJoin('#', committish)}`, + tarballtemplate: ({ domain, user, project, committish }) => `https://codeload.${domain}/${user}/${project}/tar.gz/${maybeEncode(committish) || 'master'}`, + extract: (url) => { + let [, user, project, type, committish] = url.pathname.split('/', 5) + if (type && type !== 'tree') { + return + } + + if (!type) { + committish = url.hash.slice(1) + } + + if (project && project.endsWith('.git')) { + project = project.slice(0, -4) + } + + if (!user || !project) { + return + } + + return { user, project, committish } + } +}) + +gitHosts.bitbucket = Object.assign({}, defaults, { + protocols: ['git+ssh:', 'git+https:', 'ssh:', 'https:'], + domain: 'bitbucket.org', + treepath: 'src', + tarballtemplate: ({ domain, user, project, committish }) => `https://${domain}/${user}/${project}/get/${maybeEncode(committish) || 'master'}.tar.gz`, + extract: (url) => { + let [, user, project, aux] = url.pathname.split('/', 4) + if (['get'].includes(aux)) { + return + } + + if (project && project.endsWith('.git')) { + project = project.slice(0, -4) + } + + if (!user || !project) { + return + } + + return { user, project, committish: url.hash.slice(1) } + } +}) + +gitHosts.gitlab = Object.assign({}, defaults, { + protocols: ['git+ssh:', 'git+https:', 'ssh:', 'https:'], + domain: 'gitlab.com', + treepath: 'tree', + httpstemplate: ({ auth, domain, user, project, committish }) => `git+https://${maybeJoin(auth, '@')}${domain}/${user}/${project}.git${maybeJoin('#', committish)}`, + tarballtemplate: ({ domain, user, project, committish }) => `https://${domain}/${user}/${project}/repository/archive.tar.gz?ref=${maybeEncode(committish) || 'master'}`, + extract: (url) => { + const path = url.pathname.slice(1) + if (path.includes('/-/')) { + return + } + + const segments = path.split('/') + let project = segments.pop() + if (project.endsWith('.git')) { + project = project.slice(0, -4) + } + + const user = segments.join('/') + if (!user || !project) { + return + } + + return { user, project, committish: url.hash.slice(1) } + } +}) + +gitHosts.gist = Object.assign({}, defaults, { + protocols: ['git:', 'git+ssh:', 'git+https:', 'ssh:', 'https:'], + domain: 'gist.github.com', + sshtemplate: ({ domain, project, committish }) => `git@${domain}:${project}.git${maybeJoin('#', committish)}`, + sshurltemplate: ({ domain, project, committish }) => `git+ssh://git@${domain}/${project}.git${maybeJoin('#', committish)}`, + browsetemplate: ({ domain, project, committish }) => `https://${domain}/${project}${maybeJoin('/', maybeEncode(committish))}`, + browsefiletemplate: ({ domain, project, committish, path, hashformat }) => `https://${domain}/${project}${maybeJoin('/', maybeEncode(committish))}${maybeJoin('#', hashformat(path))}`, + docstemplate: ({ domain, project, committish }) => `https://${domain}/${project}${maybeJoin('/', maybeEncode(committish))}`, + httpstemplate: ({ domain, project, committish }) => `git+https://${domain}/${project}.git${maybeJoin('#', committish)}`, + filetemplate: ({ user, project, committish, path }) => `https://gist.githubusercontent.com/${user}/${project}/raw${maybeJoin('/', maybeEncode(committish))}/${path}`, + shortcuttemplate: ({ type, project, committish }) => `${type}:${project}${maybeJoin('#', committish)}`, + pathtemplate: ({ project, committish }) => `${project}${maybeJoin('#', committish)}`, + bugstemplate: ({ domain, project }) => `https://${domain}/${project}`, + gittemplate: ({ domain, project, committish }) => `git://${domain}/${project}.git${maybeJoin('#', committish)}`, + tarballtemplate: ({ project, committish }) => `https://codeload.github.com/gist/${project}/tar.gz/${maybeEncode(committish) || 'master'}`, + extract: (url) => { + let [, user, project, aux] = url.pathname.split('/', 4) + if (aux === 'raw') { + return + } + + if (!project) { + if (!user) { + return + } + + project = user + user = null + } + + if (project.endsWith('.git')) { + project = project.slice(0, -4) + } + + return { user, project, committish: url.hash.slice(1) } + }, + hashformat: function (fragment) { + return fragment && 'file-' + formatHashFragment(fragment) + } +}) + +const names = Object.keys(gitHosts) +gitHosts.byShortcut = {} +gitHosts.byDomain = {} +for (const name of names) { + gitHosts.byShortcut[`${name}:`] = name + gitHosts.byDomain[gitHosts[name].domain] = name +} + +function formatHashFragment (fragment) { + return fragment.toLowerCase().replace(/^\W+|\/|\W+$/g, '').replace(/\W+/g, '-') +} + +module.exports = gitHosts diff --git a/deps/npm/node_modules/normalize-package-data/node_modules/hosted-git-info/git-host.js b/deps/npm/node_modules/normalize-package-data/node_modules/hosted-git-info/git-host.js new file mode 100644 index 0000000000..8a975e92e5 --- /dev/null +++ b/deps/npm/node_modules/normalize-package-data/node_modules/hosted-git-info/git-host.js @@ -0,0 +1,110 @@ +'use strict' +const gitHosts = require('./git-host-info.js') + +class GitHost { + constructor (type, user, auth, project, committish, defaultRepresentation, opts = {}) { + Object.assign(this, gitHosts[type]) + this.type = type + this.user = user + this.auth = auth + this.project = project + this.committish = committish + this.default = defaultRepresentation + this.opts = opts + } + + hash () { + return this.committish ? `#${this.committish}` : '' + } + + ssh (opts) { + return this._fill(this.sshtemplate, opts) + } + + _fill (template, opts) { + if (typeof template === 'function') { + const options = { ...this, ...this.opts, ...opts } + + // the path should always be set so we don't end up with 'undefined' in urls + if (!options.path) { + options.path = '' + } + + // template functions will insert the leading slash themselves + if (options.path.startsWith('/')) { + options.path = options.path.slice(1) + } + + if (options.noCommittish) { + options.committish = null + } + + const result = template(options) + return options.noGitPlus && result.startsWith('git+') ? result.slice(4) : result + } + + return null + } + + sshurl (opts) { + return this._fill(this.sshurltemplate, opts) + } + + browse (path, fragment, opts) { + // not a string, treat path as opts + if (typeof path !== 'string') { + return this._fill(this.browsetemplate, path) + } + + if (typeof fragment !== 'string') { + opts = fragment + fragment = null + } + return this._fill(this.browsefiletemplate, { ...opts, fragment, path }) + } + + docs (opts) { + return this._fill(this.docstemplate, opts) + } + + bugs (opts) { + return this._fill(this.bugstemplate, opts) + } + + https (opts) { + return this._fill(this.httpstemplate, opts) + } + + git (opts) { + return this._fill(this.gittemplate, opts) + } + + shortcut (opts) { + return this._fill(this.shortcuttemplate, opts) + } + + path (opts) { + return this._fill(this.pathtemplate, opts) + } + + tarball (opts) { + return this._fill(this.tarballtemplate, { ...opts, noCommittish: false }) + } + + file (path, opts) { + return this._fill(this.filetemplate, { ...opts, path }) + } + + getDefaultRepresentation () { + return this.default + } + + toString (opts) { + if (this.default && typeof this[this.default] === 'function') { + return this[this.default](opts) + } + + return this.sshurl(opts) + } +} +module.exports = GitHost diff --git a/deps/npm/node_modules/normalize-package-data/node_modules/hosted-git-info/index.js b/deps/npm/node_modules/normalize-package-data/node_modules/hosted-git-info/index.js new file mode 100644 index 0000000000..f35c570c46 --- /dev/null +++ b/deps/npm/node_modules/normalize-package-data/node_modules/hosted-git-info/index.js @@ -0,0 +1,237 @@ +'use strict' +const url = require('url') +const gitHosts = require('./git-host-info.js') +const GitHost = module.exports = require('./git-host.js') +const LRU = require('lru-cache') +const cache = new LRU({ max: 1000 }) + +const protocolToRepresentationMap = { + 'git+ssh:': 'sshurl', + 'git+https:': 'https', + 'ssh:': 'sshurl', + 'git:': 'git' +} + +function protocolToRepresentation (protocol) { + return protocolToRepresentationMap[protocol] || protocol.slice(0, -1) +} + +const authProtocols = { + 'git:': true, + 'https:': true, + 'git+https:': true, + 'http:': true, + 'git+http:': true +} + +const knownProtocols = Object.keys(gitHosts.byShortcut).concat(['http:', 'https:', 'git:', 'git+ssh:', 'git+https:', 'ssh:']) + +module.exports.fromUrl = function (giturl, opts) { + if (typeof giturl !== 'string') { + return + } + + const key = giturl + JSON.stringify(opts || {}) + + if (!cache.has(key)) { + cache.set(key, fromUrl(giturl, opts)) + } + + return cache.get(key) +} + +function fromUrl (giturl, opts) { + if (!giturl) { + return + } + + const url = isGitHubShorthand(giturl) ? 'github:' + giturl : correctProtocol(giturl) + const parsed = parseGitUrl(url) + if (!parsed) { + return parsed + } + + const gitHostShortcut = gitHosts.byShortcut[parsed.protocol] + const gitHostDomain = gitHosts.byDomain[parsed.hostname.startsWith('www.') ? parsed.hostname.slice(4) : parsed.hostname] + const gitHostName = gitHostShortcut || gitHostDomain + if (!gitHostName) { + return + } + + const gitHostInfo = gitHosts[gitHostShortcut || gitHostDomain] + let auth = null + if (authProtocols[parsed.protocol] && (parsed.username || parsed.password)) { + auth = `${parsed.username}${parsed.password ? ':' + parsed.password : ''}` + } + + let committish = null + let user = null + let project = null + let defaultRepresentation = null + + try { + if (gitHostShortcut) { + let pathname = parsed.pathname.startsWith('/') ? parsed.pathname.slice(1) : parsed.pathname + const firstAt = pathname.indexOf('@') + // we ignore auth for shortcuts, so just trim it out + if (firstAt > -1) { + pathname = pathname.slice(firstAt + 1) + } + + const lastSlash = pathname.lastIndexOf('/') + if (lastSlash > -1) { + user = decodeURIComponent(pathname.slice(0, lastSlash)) + // we want nulls only, never empty strings + if (!user) { + user = null + } + project = decodeURIComponent(pathname.slice(lastSlash + 1)) + } else { + project = decodeURIComponent(pathname) + } + + if (project.endsWith('.git')) { + project = project.slice(0, -4) + } + + if (parsed.hash) { + committish = decodeURIComponent(parsed.hash.slice(1)) + } + + defaultRepresentation = 'shortcut' + } else { + if (!gitHostInfo.protocols.includes(parsed.protocol)) { + return + } + + const segments = gitHostInfo.extract(parsed) + if (!segments) { + return + } + + user = segments.user && decodeURIComponent(segments.user) + project = decodeURIComponent(segments.project) + committish = decodeURIComponent(segments.committish) + defaultRepresentation = protocolToRepresentation(parsed.protocol) + } + } catch (err) { + /* istanbul ignore else */ + if (err instanceof URIError) { + return + } else { + throw err + } + } + + return new GitHost(gitHostName, user, auth, project, committish, defaultRepresentation, opts) +} + +// accepts input like git:github.com:user/repo and inserts the // after the first : +const correctProtocol = (arg) => { + const firstColon = arg.indexOf(':') + const proto = arg.slice(0, firstColon + 1) + if (knownProtocols.includes(proto)) { + return arg + } + + const firstAt = arg.indexOf('@') + if (firstAt > -1) { + if (firstAt > firstColon) { + return `git+ssh://${arg}` + } else { + return arg + } + } + + const doubleSlash = arg.indexOf('//') + if (doubleSlash === firstColon + 1) { + return arg + } + + return arg.slice(0, firstColon + 1) + '//' + arg.slice(firstColon + 1) +} + +// look for github shorthand inputs, such as npm/cli +const isGitHubShorthand = (arg) => { + // it cannot contain whitespace before the first # + // it cannot start with a / because that's probably an absolute file path + // but it must include a slash since repos are username/repository + // it cannot start with a . because that's probably a relative file path + // it cannot start with an @ because that's a scoped package if it passes the other tests + // it cannot contain a : before a # because that tells us that there's a protocol + // a second / may not exist before a # + const firstHash = arg.indexOf('#') + const firstSlash = arg.indexOf('/') + const secondSlash = arg.indexOf('/', firstSlash + 1) + const firstColon = arg.indexOf(':') + const firstSpace = /\s/.exec(arg) + const firstAt = arg.indexOf('@') + + const spaceOnlyAfterHash = !firstSpace || (firstHash > -1 && firstSpace.index > firstHash) + const atOnlyAfterHash = firstAt === -1 || (firstHash > -1 && firstAt > firstHash) + const colonOnlyAfterHash = firstColon === -1 || (firstHash > -1 && firstColon > firstHash) + const secondSlashOnlyAfterHash = secondSlash === -1 || (firstHash > -1 && secondSlash > firstHash) + const hasSlash = firstSlash > 0 + // if a # is found, what we really want to know is that the character immediately before # is not a / + const doesNotEndWithSlash = firstHash > -1 ? arg[firstHash - 1] !== '/' : !arg.endsWith('/') + const doesNotStartWithDot = !arg.startsWith('.') + + return spaceOnlyAfterHash && hasSlash && doesNotEndWithSlash && doesNotStartWithDot && atOnlyAfterHash && colonOnlyAfterHash && secondSlashOnlyAfterHash +} + +// attempt to correct an scp style url so that it will parse with `new URL()` +const correctUrl = (giturl) => { + const firstAt = giturl.indexOf('@') + const lastHash = giturl.lastIndexOf('#') + let firstColon = giturl.indexOf(':') + let lastColon = giturl.lastIndexOf(':', lastHash > -1 ? lastHash : Infinity) + + let corrected + if (lastColon > firstAt) { + // the last : comes after the first @ (or there is no @) + // like it would in: + // proto://hostname.com:user/repo + // username@hostname.com:user/repo + // :password@hostname.com:user/repo + // username:password@hostname.com:user/repo + // proto://username@hostname.com:user/repo + // proto://:password@hostname.com:user/repo + // proto://username:password@hostname.com:user/repo + // then we replace the last : with a / to create a valid path + corrected = giturl.slice(0, lastColon) + '/' + giturl.slice(lastColon + 1) + // // and we find our new : positions + firstColon = corrected.indexOf(':') + lastColon = corrected.lastIndexOf(':') + } + + if (firstColon === -1 && giturl.indexOf('//') === -1) { + // we have no : at all + // as it would be in: + // username@hostname.com/user/repo + // then we prepend a protocol + corrected = `git+ssh://${corrected}` + } + + return corrected +} + +// try to parse the url as its given to us, if that throws +// then we try to clean the url and parse that result instead +// THIS FUNCTION SHOULD NEVER THROW +const parseGitUrl = (giturl) => { + let result + try { + result = new url.URL(giturl) + } catch (err) {} + + if (result) { + return result + } + + const correctedUrl = correctUrl(giturl) + try { + result = new url.URL(correctedUrl) + } catch (err) {} + + return result +} diff --git a/deps/npm/node_modules/normalize-package-data/node_modules/hosted-git-info/package.json b/deps/npm/node_modules/normalize-package-data/node_modules/hosted-git-info/package.json new file mode 100644 index 0000000000..930e3b693b --- /dev/null +++ b/deps/npm/node_modules/normalize-package-data/node_modules/hosted-git-info/package.json @@ -0,0 +1,52 @@ +{ + "name": "hosted-git-info", + "version": "4.0.1", + "description": "Provides metadata and conversions from repository urls for GitHub, Bitbucket and GitLab", + "main": "index.js", + "repository": { + "type": "git", + "url": "git+https://github.com/npm/hosted-git-info.git" + }, + "keywords": [ + "git", + "github", + "bitbucket", + "gitlab" + ], + "author": "Rebecca Turner <me@re-becca.org> (http://re-becca.org)", + "license": "ISC", + "bugs": { + "url": "https://github.com/npm/hosted-git-info/issues" + }, + "homepage": "https://github.com/npm/hosted-git-info", + "scripts": { + "posttest": "standard", + "postversion": "npm publish", + "prepublishOnly": "git push origin --follow-tags", + "preversion": "npm test", + "snap": "tap", + "test": "tap", + "test:coverage": "tap --coverage-report=html" + }, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "devDependencies": { + "standard": "^16.0.3", + "standard-version": "^9.1.0", + "tap": "^14.11.0" + }, + "files": [ + "index.js", + "git-host.js", + "git-host-info.js" + ], + "engines": { + "node": ">=10" + }, + "tap": { + "color": 1, + "coverage": true, + "esm": false + } +} diff --git a/deps/npm/node_modules/normalize-package-data/package.json b/deps/npm/node_modules/normalize-package-data/package.json index 8df2f8fcac..09b184c19d 100644 --- a/deps/npm/node_modules/normalize-package-data/package.json +++ b/deps/npm/node_modules/normalize-package-data/package.json @@ -1,6 +1,6 @@ { "name": "normalize-package-data", - "version": "3.0.0", + "version": "3.0.2", "author": "Meryn Stol <merynstol@gmail.com>", "description": "Normalizes data that can be found in package.json files.", "license": "BSD-2-Clause", @@ -10,16 +10,19 @@ }, "main": "lib/normalize.js", "scripts": { + "postversion": "npm publish", + "prepublishOnly": "git push origin --follow-tags", + "preversion": "npm test", "test": "tap test/*.js" }, "dependencies": { - "hosted-git-info": "^3.0.6", - "resolve": "^1.17.0", - "semver": "^7.3.2", + "hosted-git-info": "^4.0.1", + "resolve": "^1.20.0", + "semver": "^7.3.4", "validate-npm-package-license": "^3.0.1" }, "devDependencies": { - "tap": "^14.10.8" + "tap": "^14.11.0" }, "files": [ "lib/*.js", diff --git a/deps/npm/node_modules/npm-package-arg/node_modules/hosted-git-info/CHANGELOG.md b/deps/npm/node_modules/npm-package-arg/node_modules/hosted-git-info/CHANGELOG.md new file mode 100644 index 0000000000..3ffcacacc5 --- /dev/null +++ b/deps/npm/node_modules/npm-package-arg/node_modules/hosted-git-info/CHANGELOG.md @@ -0,0 +1,185 @@ +# Change Log + +All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. + +<a name="3.0.8"></a> +## [3.0.8](https://github.com/npm/hosted-git-info/compare/v3.0.7...v3.0.8) (2021-01-28) + + +### Bug Fixes + +* simplify the regular expression for shortcut matching ([bede0dc](https://github.com/npm/hosted-git-info/commit/bede0dc)), closes [#76](https://github.com/npm/hosted-git-info/issues/76) + + + +<a name="3.0.7"></a> +## [3.0.7](https://github.com/npm/hosted-git-info/compare/v3.0.6...v3.0.7) (2020-10-15) + + +### Bug Fixes + +* correctly filter out urls for tarballs in gitlab ([eb5bd5a](https://github.com/npm/hosted-git-info/commit/eb5bd5a)), closes [#69](https://github.com/npm/hosted-git-info/issues/69) + + + +<a name="3.0.6"></a> +## [3.0.6](https://github.com/npm/hosted-git-info/compare/v3.0.5...v3.0.6) (2020-10-12) + + +### Bug Fixes + +* support to github gist legacy hash length ([c067102](https://github.com/npm/hosted-git-info/commit/c067102)), closes [#68](https://github.com/npm/hosted-git-info/issues/68) + + + +<a name="3.0.5"></a> +## [3.0.5](https://github.com/npm/hosted-git-info/compare/v3.0.4...v3.0.5) (2020-07-11) + + + +<a name="3.0.4"></a> +## [3.0.4](https://github.com/npm/hosted-git-info/compare/v3.0.3...v3.0.4) (2020-02-26) + + +### Bug Fixes + +* Do not pass scp-style URLs to the WhatWG url.URL ([0835306](https://github.com/npm/hosted-git-info/commit/0835306)), closes [#60](https://github.com/npm/hosted-git-info/issues/60) [#63](https://github.com/npm/hosted-git-info/issues/63) + + + +<a name="3.0.3"></a> +## [3.0.3](https://github.com/npm/hosted-git-info/compare/v3.0.2...v3.0.3) (2020-02-25) + + + +<a name="3.0.2"></a> +## [3.0.2](https://github.com/npm/hosted-git-info/compare/v3.0.1...v3.0.2) (2019-10-08) + + +### Bug Fixes + +* do not encodeURIComponent the domain ([3e5fbec](https://github.com/npm/hosted-git-info/commit/3e5fbec)), closes [#53](https://github.com/npm/hosted-git-info/issues/53) + + + +<a name="3.0.1"></a> +## [3.0.1](https://github.com/npm/hosted-git-info/compare/v3.0.0...v3.0.1) (2019-10-07) + + +### Bug Fixes + +* update pathmatch for gitlab ([e3e3054](https://github.com/npm/hosted-git-info/commit/e3e3054)), closes [#52](https://github.com/npm/hosted-git-info/issues/52) +* updated pathmatch for gitlab ([fa87af7](https://github.com/npm/hosted-git-info/commit/fa87af7)) + + + +<a name="3.0.0"></a> +# [3.0.0](https://github.com/npm/hosted-git-info/compare/v2.8.3...v3.0.0) (2019-08-12) + + +### Bug Fixes + +* **cache:** Switch to lru-cache to save ourselves from unlimited memory consumption ([37c2891](https://github.com/npm/hosted-git-info/commit/37c2891)), closes [#38](https://github.com/npm/hosted-git-info/issues/38) + + +### BREAKING CHANGES + +* **cache:** Drop support for node 0.x + + + +<a name="2.8.3"></a> +## [2.8.3](https://github.com/npm/hosted-git-info/compare/v2.8.2...v2.8.3) (2019-08-12) + + + +<a name="2.8.2"></a> +## [2.8.2](https://github.com/npm/hosted-git-info/compare/v2.8.1...v2.8.2) (2019-08-05) + + +### Bug Fixes + +* http protocol use sshurl by default ([3b1d629](https://github.com/npm/hosted-git-info/commit/3b1d629)), closes [#48](https://github.com/npm/hosted-git-info/issues/48) + + + +<a name="2.8.1"></a> +## [2.8.1](https://github.com/npm/hosted-git-info/compare/v2.8.0...v2.8.1) (2019-08-05) + + +### Bug Fixes + +* ignore noCommittish on tarball url generation ([5d4a8d7](https://github.com/npm/hosted-git-info/commit/5d4a8d7)) +* use gist tarball url that works for anonymous gists ([1692435](https://github.com/npm/hosted-git-info/commit/1692435)) + + + +<a name="2.8.0"></a> +# [2.8.0](https://github.com/npm/hosted-git-info/compare/v2.7.1...v2.8.0) (2019-08-05) + + +### Bug Fixes + +* Allow slashes in gitlab project section ([bbcf7b2](https://github.com/npm/hosted-git-info/commit/bbcf7b2)), closes [#46](https://github.com/npm/hosted-git-info/issues/46) [#43](https://github.com/npm/hosted-git-info/issues/43) +* **git-host:** disallow URI-encoded slash (%2F) in `path` ([3776fa5](https://github.com/npm/hosted-git-info/commit/3776fa5)), closes [#44](https://github.com/npm/hosted-git-info/issues/44) +* **gitlab:** Do not URL encode slashes in project name for GitLab https URL ([cbf04f9](https://github.com/npm/hosted-git-info/commit/cbf04f9)), closes [#47](https://github.com/npm/hosted-git-info/issues/47) +* do not allow invalid gist urls ([d5cf830](https://github.com/npm/hosted-git-info/commit/d5cf830)) +* **cache:** Switch to lru-cache to save ourselves from unlimited memory consumption ([e518222](https://github.com/npm/hosted-git-info/commit/e518222)), closes [#38](https://github.com/npm/hosted-git-info/issues/38) + + +### Features + +* give these objects a name ([60abaea](https://github.com/npm/hosted-git-info/commit/60abaea)) + + + +<a name="2.7.1"></a> +## [2.7.1](https://github.com/npm/hosted-git-info/compare/v2.7.0...v2.7.1) (2018-07-07) + + +### Bug Fixes + +* **index:** Guard against non-string types ([5bc580d](https://github.com/npm/hosted-git-info/commit/5bc580d)) +* **parse:** Crash on strings that parse to having no host ([c931482](https://github.com/npm/hosted-git-info/commit/c931482)), closes [#35](https://github.com/npm/hosted-git-info/issues/35) + + + +<a name="2.7.0"></a> +# [2.7.0](https://github.com/npm/hosted-git-info/compare/v2.6.1...v2.7.0) (2018-07-06) + + +### Bug Fixes + +* **github tarball:** update github tarballtemplate ([6efd582](https://github.com/npm/hosted-git-info/commit/6efd582)), closes [#34](https://github.com/npm/hosted-git-info/issues/34) +* **gitlab docs:** switched to lowercase anchors for readmes ([701bcd1](https://github.com/npm/hosted-git-info/commit/701bcd1)) + + +### Features + +* **all:** Support www. prefixes on hostnames ([3349575](https://github.com/npm/hosted-git-info/commit/3349575)), closes [#32](https://github.com/npm/hosted-git-info/issues/32) + + + +<a name="2.6.1"></a> +## [2.6.1](https://github.com/npm/hosted-git-info/compare/v2.6.0...v2.6.1) (2018-06-25) + +### Bug Fixes + +* **Revert:** "compat: remove Object.assign fallback ([#25](https://github.com/npm/hosted-git-info/issues/25))" ([cce5a62](https://github.com/npm/hosted-git-info/commit/cce5a62)) +* **Revert:** "git-host: fix forgotten extend()" ([a815ec9](https://github.com/npm/hosted-git-info/commit/a815ec9)) + + + +<a name="2.6.0"></a> +# [2.6.0](https://github.com/npm/hosted-git-info/compare/v2.5.0...v2.6.0) (2018-03-07) + + +### Bug Fixes + +* **compat:** remove Object.assign fallback ([#25](https://github.com/npm/hosted-git-info/issues/25)) ([627ab55](https://github.com/npm/hosted-git-info/commit/627ab55)) +* **git-host:** fix forgotten extend() ([eba1f7b](https://github.com/npm/hosted-git-info/commit/eba1f7b)) + + +### Features + +* **browse:** fragment support for browse() ([#28](https://github.com/npm/hosted-git-info/issues/28)) ([cd5e5bb](https://github.com/npm/hosted-git-info/commit/cd5e5bb)) diff --git a/deps/npm/node_modules/npm-package-arg/node_modules/hosted-git-info/LICENSE b/deps/npm/node_modules/npm-package-arg/node_modules/hosted-git-info/LICENSE new file mode 100644 index 0000000000..45055763dc --- /dev/null +++ b/deps/npm/node_modules/npm-package-arg/node_modules/hosted-git-info/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2015, Rebecca Turner + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. diff --git a/deps/npm/node_modules/npm-package-arg/node_modules/hosted-git-info/README.md b/deps/npm/node_modules/npm-package-arg/node_modules/hosted-git-info/README.md new file mode 100644 index 0000000000..8740406029 --- /dev/null +++ b/deps/npm/node_modules/npm-package-arg/node_modules/hosted-git-info/README.md @@ -0,0 +1,133 @@ +# hosted-git-info + +This will let you identify and transform various git hosts URLs between +protocols. It also can tell you what the URL is for the raw path for +particular file for direct access without git. + +## Example + +```javascript +var hostedGitInfo = require("hosted-git-info") +var info = hostedGitInfo.fromUrl("git@github.com:npm/hosted-git-info.git", opts) +/* info looks like: +{ + type: "github", + domain: "github.com", + user: "npm", + project: "hosted-git-info" +} +*/ +``` + +If the URL can't be matched with a git host, `null` will be returned. We +can match git, ssh and https urls. Additionally, we can match ssh connect +strings (`git@github.com:npm/hosted-git-info`) and shortcuts (eg, +`github:npm/hosted-git-info`). GitHub specifically, is detected in the case +of a third, unprefixed, form: `npm/hosted-git-info`. + +If it does match, the returned object has properties of: + +* info.type -- The short name of the service +* info.domain -- The domain for git protocol use +* info.user -- The name of the user/org on the git host +* info.project -- The name of the project on the git host + +## Version Contract + +The major version will be bumped any time… + +* The constructor stops accepting URLs that it previously accepted. +* A method is removed. +* A method can no longer accept the number and type of arguments it previously accepted. +* A method can return a different type than it currently returns. + +Implications: + +* I do not consider the specific format of the urls returned from, say + `.https()` to be a part of the contract. The contract is that it will + return a string that can be used to fetch the repo via HTTPS. But what + that string looks like, specifically, can change. +* Dropping support for a hosted git provider would constitute a breaking + change. + +## Usage + +### var info = hostedGitInfo.fromUrl(gitSpecifier[, options]) + +* *gitSpecifer* is a URL of a git repository or a SCP-style specifier of one. +* *options* is an optional object. It can have the following properties: + * *noCommittish* — If true then committishes won't be included in generated URLs. + * *noGitPlus* — If true then `git+` won't be prefixed on URLs. + +## Methods + +All of the methods take the same options as the `fromUrl` factory. Options +provided to a method override those provided to the constructor. + +* info.file(path, opts) + +Given the path of a file relative to the repository, returns a URL for +directly fetching it from the githost. If no committish was set then +`master` will be used as the default. + +For example `hostedGitInfo.fromUrl("git@github.com:npm/hosted-git-info.git#v1.0.0").file("package.json")` +would return `https://raw.githubusercontent.com/npm/hosted-git-info/v1.0.0/package.json` + +* info.shortcut(opts) + +eg, `github:npm/hosted-git-info` + +* info.browse(path, fragment, opts) + +eg, `https://github.com/npm/hosted-git-info/tree/v1.2.0`, +`https://github.com/npm/hosted-git-info/tree/v1.2.0/package.json`, +`https://github.com/npm/hosted-git-info/tree/v1.2.0/REAMDE.md#supported-hosts` + +* info.bugs(opts) + +eg, `https://github.com/npm/hosted-git-info/issues` + +* info.docs(opts) + +eg, `https://github.com/npm/hosted-git-info/tree/v1.2.0#readme` + +* info.https(opts) + +eg, `git+https://github.com/npm/hosted-git-info.git` + +* info.sshurl(opts) + +eg, `git+ssh://git@github.com/npm/hosted-git-info.git` + +* info.ssh(opts) + +eg, `git@github.com:npm/hosted-git-info.git` + +* info.path(opts) + +eg, `npm/hosted-git-info` + +* info.tarball(opts) + +eg, `https://github.com/npm/hosted-git-info/archive/v1.2.0.tar.gz` + +* info.getDefaultRepresentation() + +Returns the default output type. The default output type is based on the +string you passed in to be parsed + +* info.toString(opts) + +Uses the getDefaultRepresentation to call one of the other methods to get a URL for +this resource. As such `hostedGitInfo.fromUrl(url).toString()` will give +you a normalized version of the URL that still uses the same protocol. + +Shortcuts will still be returned as shortcuts, but the special case github +form of `org/project` will be normalized to `github:org/project`. + +SSH connect strings will be normalized into `git+ssh` URLs. + +## Supported hosts + +Currently this supports GitHub, Bitbucket and GitLab. Pull requests for +additional hosts welcome. diff --git a/deps/npm/node_modules/npm-package-arg/node_modules/hosted-git-info/git-host-info.js b/deps/npm/node_modules/npm-package-arg/node_modules/hosted-git-info/git-host-info.js new file mode 100644 index 0000000000..360d7b096b --- /dev/null +++ b/deps/npm/node_modules/npm-package-arg/node_modules/hosted-git-info/git-host-info.js @@ -0,0 +1,154 @@ +'use strict' +const maybeJoin = (...args) => args.every(arg => arg) ? args.join('') : '' +const maybeEncode = (arg) => arg ? encodeURIComponent(arg) : '' + +const defaults = { + sshtemplate: ({ domain, user, project, committish }) => `git@${domain}:${user}/${project}.git${maybeJoin('#', committish)}`, + sshurltemplate: ({ domain, user, project, committish }) => `git+ssh://git@${domain}/${user}/${project}.git${maybeJoin('#', committish)}`, + browsetemplate: ({ domain, user, project, committish, treepath }) => `https://${domain}/${user}/${project}${maybeJoin('/', treepath, '/', maybeEncode(committish))}`, + browsefiletemplate: ({ domain, user, project, committish, treepath, path, fragment, hashformat }) => `https://${domain}/${user}/${project}/${treepath}/${maybeEncode(committish || 'master')}/${path}${maybeJoin('#', hashformat(fragment || ''))}`, + docstemplate: ({ domain, user, project, treepath, committish }) => `https://${domain}/${user}/${project}${maybeJoin('/', treepath, '/', maybeEncode(committish))}#readme`, + httpstemplate: ({ auth, domain, user, project, committish }) => `git+https://${maybeJoin(auth, '@')}${domain}/${user}/${project}.git${maybeJoin('#', committish)}`, + filetemplate: ({ domain, user, project, committish, path }) => `https://${domain}/${user}/${project}/raw/${maybeEncode(committish) || 'master'}/${path}`, + shortcuttemplate: ({ type, user, project, committish }) => `${type}:${user}/${project}${maybeJoin('#', committish)}`, + pathtemplate: ({ user, project, committish }) => `${user}/${project}${maybeJoin('#', committish)}`, + bugstemplate: ({ domain, user, project }) => `https://${domain}/${user}/${project}/issues`, + hashformat: formatHashFragment +} + +const gitHosts = {} +gitHosts.github = Object.assign({}, defaults, { + // First two are insecure and generally shouldn't be used any more, but + // they are still supported. + protocols: ['git:', 'http:', 'git+ssh:', 'git+https:', 'ssh:', 'https:'], + domain: 'github.com', + treepath: 'tree', + filetemplate: ({ auth, user, project, committish, path }) => `https://${maybeJoin(auth, '@')}raw.githubusercontent.com/${user}/${project}/${maybeEncode(committish) || 'master'}/${path}`, + gittemplate: ({ auth, domain, user, project, committish }) => `git://${maybeJoin(auth, '@')}${domain}/${user}/${project}.git${maybeJoin('#', committish)}`, + tarballtemplate: ({ domain, user, project, committish }) => `https://codeload.${domain}/${user}/${project}/tar.gz/${maybeEncode(committish) || 'master'}`, + extract: (url) => { + let [, user, project, type, committish] = url.pathname.split('/', 5) + if (type && type !== 'tree') { + return + } + + if (!type) { + committish = url.hash.slice(1) + } + + if (project && project.endsWith('.git')) { + project = project.slice(0, -4) + } + + if (!user || !project) { + return + } + + return { user, project, committish } + } +}) + +gitHosts.bitbucket = Object.assign({}, defaults, { + protocols: ['git+ssh:', 'git+https:', 'ssh:', 'https:'], + domain: 'bitbucket.org', + treepath: 'src', + tarballtemplate: ({ domain, user, project, committish }) => `https://${domain}/${user}/${project}/get/${maybeEncode(committish) || 'master'}.tar.gz`, + extract: (url) => { + let [, user, project, aux] = url.pathname.split('/', 4) + if (['get'].includes(aux)) { + return + } + + if (project && project.endsWith('.git')) { + project = project.slice(0, -4) + } + + if (!user || !project) { + return + } + + return { user, project, committish: url.hash.slice(1) } + } +}) + +gitHosts.gitlab = Object.assign({}, defaults, { + protocols: ['git+ssh:', 'git+https:', 'ssh:', 'https:'], + domain: 'gitlab.com', + treepath: 'tree', + httpstemplate: ({ auth, domain, user, project, committish }) => `git+https://${maybeJoin(auth, '@')}${domain}/${user}/${project}.git${maybeJoin('#', committish)}`, + tarballtemplate: ({ domain, user, project, committish }) => `https://${domain}/${user}/${project}/repository/archive.tar.gz?ref=${maybeEncode(committish) || 'master'}`, + extract: (url) => { + const path = url.pathname.slice(1) + if (path.includes('/-/')) { + return + } + + const segments = path.split('/') + let project = segments.pop() + if (project.endsWith('.git')) { + project = project.slice(0, -4) + } + + const user = segments.join('/') + if (!user || !project) { + return + } + + return { user, project, committish: url.hash.slice(1) } + } +}) + +gitHosts.gist = Object.assign({}, defaults, { + protocols: ['git:', 'git+ssh:', 'git+https:', 'ssh:', 'https:'], + domain: 'gist.github.com', + sshtemplate: ({ domain, project, committish }) => `git@${domain}:${project}.git${maybeJoin('#', committish)}`, + sshurltemplate: ({ domain, project, committish }) => `git+ssh://git@${domain}/${project}.git${maybeJoin('#', committish)}`, + browsetemplate: ({ domain, project, committish }) => `https://${domain}/${project}${maybeJoin('/', maybeEncode(committish))}`, + browsefiletemplate: ({ domain, project, committish, path, hashformat }) => `https://${domain}/${project}${maybeJoin('/', maybeEncode(committish))}${maybeJoin('#', hashformat(path))}`, + docstemplate: ({ domain, project, committish }) => `https://${domain}/${project}${maybeJoin('/', maybeEncode(committish))}`, + httpstemplate: ({ domain, project, committish }) => `git+https://${domain}/${project}.git${maybeJoin('#', committish)}`, + filetemplate: ({ user, project, committish, path }) => `https://gist.githubusercontent.com/${user}/${project}/raw${maybeJoin('/', maybeEncode(committish))}/${path}`, + shortcuttemplate: ({ type, project, committish }) => `${type}:${project}${maybeJoin('#', committish)}`, + pathtemplate: ({ project, committish }) => `${project}${maybeJoin('#', committish)}`, + bugstemplate: ({ domain, project }) => `https://${domain}/${project}`, + gittemplate: ({ domain, project, committish }) => `git://${domain}/${project}.git${maybeJoin('#', committish)}`, + tarballtemplate: ({ project, committish }) => `https://codeload.github.com/gist/${project}/tar.gz/${maybeEncode(committish) || 'master'}`, + extract: (url) => { + let [, user, project, aux] = url.pathname.split('/', 4) + if (aux === 'raw') { + return + } + + if (!project) { + if (!user) { + return + } + + project = user + user = null + } + + if (project.endsWith('.git')) { + project = project.slice(0, -4) + } + + return { user, project, committish: url.hash.slice(1) } + }, + hashformat: function (fragment) { + return fragment && 'file-' + formatHashFragment(fragment) + } +}) + +const names = Object.keys(gitHosts) +gitHosts.byShortcut = {} +gitHosts.byDomain = {} +for (const name of names) { + gitHosts.byShortcut[`${name}:`] = name + gitHosts.byDomain[gitHosts[name].domain] = name +} + +function formatHashFragment (fragment) { + return fragment.toLowerCase().replace(/^\W+|\/|\W+$/g, '').replace(/\W+/g, '-') +} + +module.exports = gitHosts diff --git a/deps/npm/node_modules/npm-package-arg/node_modules/hosted-git-info/git-host.js b/deps/npm/node_modules/npm-package-arg/node_modules/hosted-git-info/git-host.js new file mode 100644 index 0000000000..8a975e92e5 --- /dev/null +++ b/deps/npm/node_modules/npm-package-arg/node_modules/hosted-git-info/git-host.js @@ -0,0 +1,110 @@ +'use strict' +const gitHosts = require('./git-host-info.js') + +class GitHost { + constructor (type, user, auth, project, committish, defaultRepresentation, opts = {}) { + Object.assign(this, gitHosts[type]) + this.type = type + this.user = user + this.auth = auth + this.project = project + this.committish = committish + this.default = defaultRepresentation + this.opts = opts + } + + hash () { + return this.committish ? `#${this.committish}` : '' + } + + ssh (opts) { + return this._fill(this.sshtemplate, opts) + } + + _fill (template, opts) { + if (typeof template === 'function') { + const options = { ...this, ...this.opts, ...opts } + + // the path should always be set so we don't end up with 'undefined' in urls + if (!options.path) { + options.path = '' + } + + // template functions will insert the leading slash themselves + if (options.path.startsWith('/')) { + options.path = options.path.slice(1) + } + + if (options.noCommittish) { + options.committish = null + } + + const result = template(options) + return options.noGitPlus && result.startsWith('git+') ? result.slice(4) : result + } + + return null + } + + sshurl (opts) { + return this._fill(this.sshurltemplate, opts) + } + + browse (path, fragment, opts) { + // not a string, treat path as opts + if (typeof path !== 'string') { + return this._fill(this.browsetemplate, path) + } + + if (typeof fragment !== 'string') { + opts = fragment + fragment = null + } + return this._fill(this.browsefiletemplate, { ...opts, fragment, path }) + } + + docs (opts) { + return this._fill(this.docstemplate, opts) + } + + bugs (opts) { + return this._fill(this.bugstemplate, opts) + } + + https (opts) { + return this._fill(this.httpstemplate, opts) + } + + git (opts) { + return this._fill(this.gittemplate, opts) + } + + shortcut (opts) { + return this._fill(this.shortcuttemplate, opts) + } + + path (opts) { + return this._fill(this.pathtemplate, opts) + } + + tarball (opts) { + return this._fill(this.tarballtemplate, { ...opts, noCommittish: false }) + } + + file (path, opts) { + return this._fill(this.filetemplate, { ...opts, path }) + } + + getDefaultRepresentation () { + return this.default + } + + toString (opts) { + if (this.default && typeof this[this.default] === 'function') { + return this[this.default](opts) + } + + return this.sshurl(opts) + } +} +module.exports = GitHost diff --git a/deps/npm/node_modules/npm-package-arg/node_modules/hosted-git-info/index.js b/deps/npm/node_modules/npm-package-arg/node_modules/hosted-git-info/index.js new file mode 100644 index 0000000000..f35c570c46 --- /dev/null +++ b/deps/npm/node_modules/npm-package-arg/node_modules/hosted-git-info/index.js @@ -0,0 +1,237 @@ +'use strict' +const url = require('url') +const gitHosts = require('./git-host-info.js') +const GitHost = module.exports = require('./git-host.js') +const LRU = require('lru-cache') +const cache = new LRU({ max: 1000 }) + +const protocolToRepresentationMap = { + 'git+ssh:': 'sshurl', + 'git+https:': 'https', + 'ssh:': 'sshurl', + 'git:': 'git' +} + +function protocolToRepresentation (protocol) { + return protocolToRepresentationMap[protocol] || protocol.slice(0, -1) +} + +const authProtocols = { + 'git:': true, + 'https:': true, + 'git+https:': true, + 'http:': true, + 'git+http:': true +} + +const knownProtocols = Object.keys(gitHosts.byShortcut).concat(['http:', 'https:', 'git:', 'git+ssh:', 'git+https:', 'ssh:']) + +module.exports.fromUrl = function (giturl, opts) { + if (typeof giturl !== 'string') { + return + } + + const key = giturl + JSON.stringify(opts || {}) + + if (!cache.has(key)) { + cache.set(key, fromUrl(giturl, opts)) + } + + return cache.get(key) +} + +function fromUrl (giturl, opts) { + if (!giturl) { + return + } + + const url = isGitHubShorthand(giturl) ? 'github:' + giturl : correctProtocol(giturl) + const parsed = parseGitUrl(url) + if (!parsed) { + return parsed + } + + const gitHostShortcut = gitHosts.byShortcut[parsed.protocol] + const gitHostDomain = gitHosts.byDomain[parsed.hostname.startsWith('www.') ? parsed.hostname.slice(4) : parsed.hostname] + const gitHostName = gitHostShortcut || gitHostDomain + if (!gitHostName) { + return + } + + const gitHostInfo = gitHosts[gitHostShortcut || gitHostDomain] + let auth = null + if (authProtocols[parsed.protocol] && (parsed.username || parsed.password)) { + auth = `${parsed.username}${parsed.password ? ':' + parsed.password : ''}` + } + + let committish = null + let user = null + let project = null + let defaultRepresentation = null + + try { + if (gitHostShortcut) { + let pathname = parsed.pathname.startsWith('/') ? parsed.pathname.slice(1) : parsed.pathname + const firstAt = pathname.indexOf('@') + // we ignore auth for shortcuts, so just trim it out + if (firstAt > -1) { + pathname = pathname.slice(firstAt + 1) + } + + const lastSlash = pathname.lastIndexOf('/') + if (lastSlash > -1) { + user = decodeURIComponent(pathname.slice(0, lastSlash)) + // we want nulls only, never empty strings + if (!user) { + user = null + } + project = decodeURIComponent(pathname.slice(lastSlash + 1)) + } else { + project = decodeURIComponent(pathname) + } + + if (project.endsWith('.git')) { + project = project.slice(0, -4) + } + + if (parsed.hash) { + committish = decodeURIComponent(parsed.hash.slice(1)) + } + + defaultRepresentation = 'shortcut' + } else { + if (!gitHostInfo.protocols.includes(parsed.protocol)) { + return + } + + const segments = gitHostInfo.extract(parsed) + if (!segments) { + return + } + + user = segments.user && decodeURIComponent(segments.user) + project = decodeURIComponent(segments.project) + committish = decodeURIComponent(segments.committish) + defaultRepresentation = protocolToRepresentation(parsed.protocol) + } + } catch (err) { + /* istanbul ignore else */ + if (err instanceof URIError) { + return + } else { + throw err + } + } + + return new GitHost(gitHostName, user, auth, project, committish, defaultRepresentation, opts) +} + +// accepts input like git:github.com:user/repo and inserts the // after the first : +const correctProtocol = (arg) => { + const firstColon = arg.indexOf(':') + const proto = arg.slice(0, firstColon + 1) + if (knownProtocols.includes(proto)) { + return arg + } + + const firstAt = arg.indexOf('@') + if (firstAt > -1) { + if (firstAt > firstColon) { + return `git+ssh://${arg}` + } else { + return arg + } + } + + const doubleSlash = arg.indexOf('//') + if (doubleSlash === firstColon + 1) { + return arg + } + + return arg.slice(0, firstColon + 1) + '//' + arg.slice(firstColon + 1) +} + +// look for github shorthand inputs, such as npm/cli +const isGitHubShorthand = (arg) => { + // it cannot contain whitespace before the first # + // it cannot start with a / because that's probably an absolute file path + // but it must include a slash since repos are username/repository + // it cannot start with a . because that's probably a relative file path + // it cannot start with an @ because that's a scoped package if it passes the other tests + // it cannot contain a : before a # because that tells us that there's a protocol + // a second / may not exist before a # + const firstHash = arg.indexOf('#') + const firstSlash = arg.indexOf('/') + const secondSlash = arg.indexOf('/', firstSlash + 1) + const firstColon = arg.indexOf(':') + const firstSpace = /\s/.exec(arg) + const firstAt = arg.indexOf('@') + + const spaceOnlyAfterHash = !firstSpace || (firstHash > -1 && firstSpace.index > firstHash) + const atOnlyAfterHash = firstAt === -1 || (firstHash > -1 && firstAt > firstHash) + const colonOnlyAfterHash = firstColon === -1 || (firstHash > -1 && firstColon > firstHash) + const secondSlashOnlyAfterHash = secondSlash === -1 || (firstHash > -1 && secondSlash > firstHash) + const hasSlash = firstSlash > 0 + // if a # is found, what we really want to know is that the character immediately before # is not a / + const doesNotEndWithSlash = firstHash > -1 ? arg[firstHash - 1] !== '/' : !arg.endsWith('/') + const doesNotStartWithDot = !arg.startsWith('.') + + return spaceOnlyAfterHash && hasSlash && doesNotEndWithSlash && doesNotStartWithDot && atOnlyAfterHash && colonOnlyAfterHash && secondSlashOnlyAfterHash +} + +// attempt to correct an scp style url so that it will parse with `new URL()` +const correctUrl = (giturl) => { + const firstAt = giturl.indexOf('@') + const lastHash = giturl.lastIndexOf('#') + let firstColon = giturl.indexOf(':') + let lastColon = giturl.lastIndexOf(':', lastHash > -1 ? lastHash : Infinity) + + let corrected + if (lastColon > firstAt) { + // the last : comes after the first @ (or there is no @) + // like it would in: + // proto://hostname.com:user/repo + // username@hostname.com:user/repo + // :password@hostname.com:user/repo + // username:password@hostname.com:user/repo + // proto://username@hostname.com:user/repo + // proto://:password@hostname.com:user/repo + // proto://username:password@hostname.com:user/repo + // then we replace the last : with a / to create a valid path + corrected = giturl.slice(0, lastColon) + '/' + giturl.slice(lastColon + 1) + // // and we find our new : positions + firstColon = corrected.indexOf(':') + lastColon = corrected.lastIndexOf(':') + } + + if (firstColon === -1 && giturl.indexOf('//') === -1) { + // we have no : at all + // as it would be in: + // username@hostname.com/user/repo + // then we prepend a protocol + corrected = `git+ssh://${corrected}` + } + + return corrected +} + +// try to parse the url as its given to us, if that throws +// then we try to clean the url and parse that result instead +// THIS FUNCTION SHOULD NEVER THROW +const parseGitUrl = (giturl) => { + let result + try { + result = new url.URL(giturl) + } catch (err) {} + + if (result) { + return result + } + + const correctedUrl = correctUrl(giturl) + try { + result = new url.URL(correctedUrl) + } catch (err) {} + + return result +} diff --git a/deps/npm/node_modules/npm-package-arg/node_modules/hosted-git-info/package.json b/deps/npm/node_modules/npm-package-arg/node_modules/hosted-git-info/package.json new file mode 100644 index 0000000000..930e3b693b --- /dev/null +++ b/deps/npm/node_modules/npm-package-arg/node_modules/hosted-git-info/package.json @@ -0,0 +1,52 @@ +{ + "name": "hosted-git-info", + "version": "4.0.1", + "description": "Provides metadata and conversions from repository urls for GitHub, Bitbucket and GitLab", + "main": "index.js", + "repository": { + "type": "git", + "url": "git+https://github.com/npm/hosted-git-info.git" + }, + "keywords": [ + "git", + "github", + "bitbucket", + "gitlab" + ], + "author": "Rebecca Turner <me@re-becca.org> (http://re-becca.org)", + "license": "ISC", + "bugs": { + "url": "https://github.com/npm/hosted-git-info/issues" + }, + "homepage": "https://github.com/npm/hosted-git-info", + "scripts": { + "posttest": "standard", + "postversion": "npm publish", + "prepublishOnly": "git push origin --follow-tags", + "preversion": "npm test", + "snap": "tap", + "test": "tap", + "test:coverage": "tap --coverage-report=html" + }, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "devDependencies": { + "standard": "^16.0.3", + "standard-version": "^9.1.0", + "tap": "^14.11.0" + }, + "files": [ + "index.js", + "git-host.js", + "git-host-info.js" + ], + "engines": { + "node": ">=10" + }, + "tap": { + "color": 1, + "coverage": true, + "esm": false + } +} diff --git a/deps/npm/node_modules/npm-package-arg/package.json b/deps/npm/node_modules/npm-package-arg/package.json index c460be828e..ed3b364442 100644 --- a/deps/npm/node_modules/npm-package-arg/package.json +++ b/deps/npm/node_modules/npm-package-arg/package.json @@ -1,6 +1,6 @@ { "name": "npm-package-arg", - "version": "8.1.1", + "version": "8.1.2", "description": "Parse the things that can be arguments to `npm install`", "main": "npa.js", "directories": { @@ -10,12 +10,12 @@ "npa.js" ], "dependencies": { - "hosted-git-info": "^3.0.6", - "semver": "^7.0.0", + "hosted-git-info": "^4.0.1", + "semver": "^7.3.4", "validate-npm-package-name": "^3.0.0" }, "devDependencies": { - "tap": "^14.10.2" + "tap": "^14.11.0" }, "scripts": { "preversion": "npm test", diff --git a/deps/npm/node_modules/npm-pick-manifest/CHANGELOG.md b/deps/npm/node_modules/npm-pick-manifest/CHANGELOG.md index a4ee13e92a..5edb4a33c1 100644 --- a/deps/npm/node_modules/npm-pick-manifest/CHANGELOG.md +++ b/deps/npm/node_modules/npm-pick-manifest/CHANGELOG.md @@ -1,6 +1,10 @@ # Changelog -All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +All notable changes to this project will be documented in this file. + +## [6.1.1](https://github.com/npm/npm-pick-manifest/compare/v6.0.0...v6.1.0) (2020-04-07) + +* normalize package bins in returned manifest ## [6.1.0](https://github.com/npm/npm-pick-manifest/compare/v6.0.0...v6.1.0) (2020-04-07) diff --git a/deps/npm/node_modules/npm-pick-manifest/index.js b/deps/npm/node_modules/npm-pick-manifest/index.js index 2b3ea6ffa4..695450524d 100644 --- a/deps/npm/node_modules/npm-pick-manifest/index.js +++ b/deps/npm/node_modules/npm-pick-manifest/index.js @@ -3,6 +3,7 @@ const npa = require('npm-package-arg') const semver = require('semver') const { checkEngine } = require('npm-install-checks') +const normalizeBin = require('npm-normalize-package-bin') const engineOk = (manifest, npmVersion, nodeVersion) => { try { @@ -183,7 +184,8 @@ const pickManifest = (packument, wanted, opts) => { } module.exports = (packument, wanted, opts = {}) => { - const picked = pickManifest(packument, wanted, opts) + const mani = pickManifest(packument, wanted, opts) + const picked = mani && normalizeBin(mani) const policyRestrictions = packument.policyRestrictions const restricted = (policyRestrictions && policyRestrictions.versions) || {} diff --git a/deps/npm/node_modules/npm-pick-manifest/package.json b/deps/npm/node_modules/npm-pick-manifest/package.json index 805f5ac23a..4b4866cbf8 100644 --- a/deps/npm/node_modules/npm-pick-manifest/package.json +++ b/deps/npm/node_modules/npm-pick-manifest/package.json @@ -1,6 +1,6 @@ { "name": "npm-pick-manifest", - "version": "6.1.0", + "version": "6.1.1", "description": "Resolves a matching manifest from a package metadata document according to standard npm semver resolution rules.", "main": "index.js", "files": [ @@ -9,12 +9,11 @@ "scripts": { "coverage": "tap", "lint": "standard", - "postrelease": "npm publish", + "test": "tap", "posttest": "npm run lint", - "prepublishOnly": "git push --follow-tags", - "prerelease": "npm t", - "release": "standard-version -s", - "test": "tap" + "preversion": "npm test", + "postversion": "npm publish", + "prepublishOnly": "git push origin --follow-tags" }, "repository": "https://github.com/npm/npm-pick-manifest", "keywords": [ @@ -30,13 +29,13 @@ "license": "ISC", "dependencies": { "npm-install-checks": "^4.0.0", - "npm-package-arg": "^8.0.0", - "semver": "^7.0.0" + "npm-normalize-package-bin": "^1.0.1", + "npm-package-arg": "^8.1.2", + "semver": "^7.3.4" }, "devDependencies": { "standard": "^14.3.1", - "standard-version": "^7.0.1", - "tap": "^14.10.2" + "tap": "^14.11.0" }, "tap": { "check-coverage": true diff --git a/deps/npm/node_modules/pacote/lib/util/tar-create-options.js b/deps/npm/node_modules/pacote/lib/util/tar-create-options.js index e8abbe175b..31ab34c9d9 100644 --- a/deps/npm/node_modules/pacote/lib/util/tar-create-options.js +++ b/deps/npm/node_modules/pacote/lib/util/tar-create-options.js @@ -4,7 +4,13 @@ const tarCreateOptions = manifest => ({ cwd: manifest._resolved, prefix: 'package/', portable: true, - gzip: true, + gzip: { + // forcing the level to 9 seems to avoid some + // platform specific optimizations that cause + // integrity mismatch errors due to differing + // end results after compression + level: 9 + }, // ensure that package bins are always executable // Note that npm-packlist is already filtering out diff --git a/deps/npm/node_modules/pacote/package.json b/deps/npm/node_modules/pacote/package.json index dca67f3e88..dd6bf9400c 100644 --- a/deps/npm/node_modules/pacote/package.json +++ b/deps/npm/node_modules/pacote/package.json @@ -1,6 +1,6 @@ { "name": "pacote", - "version": "11.3.0", + "version": "11.3.1", "description": "JavaScript package downloader", "author": "Isaac Z. Schlueter <i@izs.me> (https://izs.me)", "bin": { diff --git a/deps/npm/node_modules/puka/CHANGELOG.md b/deps/npm/node_modules/puka/CHANGELOG.md deleted file mode 100644 index 781b81295a..0000000000 --- a/deps/npm/node_modules/puka/CHANGELOG.md +++ /dev/null @@ -1,31 +0,0 @@ -# Changelog -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## [1.0.1](https://gitlab.com/rhendric/puka/-/compare/v1.0.0...v1.0.1) - 2020-05-16 - -### Fixed - -- Add more carets to win32 command arguments ([45965ca](https://gitlab.com/rhendric/puka/-/commit/45965ca60fcc518082e0b085d8e81f3f3279ffb4)) - - As previously documented and implemented, Puka assumed that all programs - are batch files for the purpose of multi-escaping commands that appear - in pipelines. However, regardless of whether a command is in a pipeline, - one extra layer of escaping is needed if the command invokes a batch - file, which Puka was not producing. This only applies to the arguments - to the command, not to the batch file path, nor to paths used in - redirects. (The property-based spawn test which was supposed to catch - such oversights missed this one because it was invoking the Node.js - executable directly, not, as recommended in the documentation, a batch - file.) - - Going forward, the caveats described in the documentation continue to - apply: if you are running programs on Windows with Puka, make sure they - are batch files, or you may find arguments are being escaped with too - many carets. As the documentation says, if this causes problems for you, - please open an issue so we can work out the details of what a good - workaround looks like. - -## [1.0.0](https://gitlab.com/rhendric/puka/-/tags/v1.0.0) - 2017-09-29 diff --git a/deps/npm/node_modules/puka/LICENSE.txt b/deps/npm/node_modules/puka/LICENSE.txt deleted file mode 100644 index 0141196a59..0000000000 --- a/deps/npm/node_modules/puka/LICENSE.txt +++ /dev/null @@ -1,18 +0,0 @@ -Copyright 2017 Ryan Hendrickson <ryan.hendrickson@alum.mit.edu> - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/deps/npm/node_modules/puka/README.md b/deps/npm/node_modules/puka/README.md deleted file mode 100644 index 2670f742b3..0000000000 --- a/deps/npm/node_modules/puka/README.md +++ /dev/null @@ -1,411 +0,0 @@ -# Puka - -[![GitLab CI pipeline status](https://gitlab.com/rhendric/puka/badges/master/pipeline.svg)](https://gitlab.com/rhendric/puka/commits/master) [![AppVeyor build status](https://img.shields.io/appveyor/ci/rhendric/puka.svg?label=windows%20tests)](https://ci.appveyor.com/project/rhendric/puka) [![Codecov status](https://img.shields.io/codecov/c/gl/rhendric/puka.svg)](https://codecov.io/gl/rhendric/puka) - -Puka is a cross-platform library for safely passing strings through shells. - -#### Contents - -- [Introduction](#introduction) - - [Why would I use Puka?](#why-would-i-use-puka) - - [How do I use Puka?](#how-do-i-use-puka) - - [What's the catch?](#whats-the-catch) -- [API Documentation](#api-documentation) - - [Basic API](#basic-api) - - [sh](#sh) - - [unquoted](#unquoted) - - [Advanced API](#advanced-api) - - [quoteForShell](#quoteforshell) - - [quoteForCmd](#quoteforcmd) - - [quoteForSh](#quoteforsh) - - [ShellString](#shellstring) - - [Secret API](#secret-api) -- [The sh DSL](#the-sh-dsl) - - [Syntax](#syntax) - - [Semantics](#semantics) - - [Types of placeholders](#types-of-placeholders) - -## Introduction - -### Why would I use Puka? - -When launching a child process from Node, you have a choice between launching -directly from the operating system (as with [child_process.spawn](https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options), -if you don't use the `{ shell: true }` option), and running the command through -a shell (as with [child_process.exec](https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback)). -Using a shell gives you more power, such as the ability to chain multiple -commands together or use redirection, but you have to construct your command as -a single string instead of using an array of arguments. And doing that can be -buggy (if not dangerous) if you don't take care to quote any arguments -correctly for the shell you're targeting, _and_ the quoting has to be done -differently on Windows and non-Windows shells. - -Puka solves that problem by giving you a simple and platform-agnostic way to -build shell commands with arguments that pass through your shell unaltered and -with no unsafe side effects, **whether you are running on Windows or a -Unix-based OS**. - -### How do I use Puka? - -Puka gives you an `sh` function intended for tagging -[template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals), -which quotes (if necessary) any values interpolated into the template. A simple -example: - -```javascript -const { sh } = require('puka'); -const { execSync } = require('child_process'); - -const arg = 'file with spaces.txt'; -execSync(sh`some-command ${arg}`); -``` - -But Puka supports more than this! See [the `sh` DSL documentation](#the-sh-dsl) -for a detailed description of all the features currently supported. - -### What's the catch? - -Here are the ones I know about: - -Puka does _not_ ensure that the actual commands you're running are -cross-platform. If you're running npm programs, you generally won't have a -problem with that, but if you want to run ``sh`cat file` `` on Windows, you'll -need to depend on something like -[cash-cat](https://www.npmjs.com/package/cash-cat). - -I searched for days for a way to quote or escape line breaks in arguments to -`cmd.exe`, but couldn't find one (regular `^`-prepending and quotation marks -don't seem to cut it). If you know of a way that works, please [open an -issue](https://gitlab.com/rhendric/puka/issues/new) to tell me about it! Until -then, any line break characters (`\r` or `\n`) in values being interpolated by -`sh` will cause an error to be thrown on Windows only. - -Also on Windows, you may notice quoting mistakes if you run commands that -involve invoking a native executable (not a batch file ending in `.cmd` or -`.bat`). Unfortunately, batch files require some extra escaping on Windows, and -Puka assumes all programs are batch files because npm creates batch file shims -for programs it installs (and, if you care about cross-platform, you'll be -using npm programs in your commands). If this causes problems for you, please -[open an issue](https://gitlab.com/rhendric/puka/issues/new); if your situation -is specific enough, there may be workarounds or improvements to Puka to be -found. - -## API Documentation - -### Basic API - - - - -#### sh - -A string template tag for safely constructing cross-platform shell commands. - -An `sh` template is not actually treated as a literal string to be -interpolated; instead, it is a tiny DSL designed to make working with shell -strings safe, simple, and straightforward. To get started quickly, see the -examples below. [More detailed documentation][1] is available -further down. - -##### Examples - -```javascript -const title = '"this" & "that"'; -sh`script --title=${title}`; // => "script '--title=\"this\" & \"that\"'" -// Note: these examples show results for non-Windows platforms. -// On Windows, the above would instead be -// 'script ^^^"--title=\\^^^"this\\^^^" ^^^& \\^^^"that\\^^^"^^^"'. - -const names = ['file1', 'file 2']; -sh`rimraf ${names}.txt`; // => "rimraf file1.txt 'file 2.txt'" - -const cmd1 = ['cat', 'file 1.txt', 'file 2.txt']; -const cmd2 = ['use-input', '-abc']; -sh`${cmd1}|${cmd2}`; // => "cat 'file 1.txt' 'file 2.txt'|use-input -abc" -``` - -Returns **[String][2]** a string formatted for the platform Node is currently -running on. - -#### unquoted - -This function permits raw strings to be interpolated into a `sh` template. - -**IMPORTANT**: If you're using Puka due to security concerns, make sure you -don't pass any untrusted content to `unquoted`. This may be obvious, but -stray punctuation in an `unquoted` section can compromise the safety of the -entire shell command. - -##### Parameters - -- `value` any value (it will be treated as a string) - -##### Examples - -```javascript -const both = true; -sh`foo ${unquoted(both ? '&&' : '||')} bar`; // => 'foo && bar' -``` - -### Advanced API - -If these functions make life easier for you, go ahead and use them; they -are just as well supported as the above. But if you aren't certain you -need them, you probably don't. - - -#### quoteForShell - -Quotes a string for injecting into a shell command. - -This function is exposed for some hypothetical case when the `sh` DSL simply -won't do; `sh` is expected to be the more convenient option almost always. -Compare: - -```javascript -console.log('cmd' + args.map(a => ' ' + quoteForShell(a)).join('')); -console.log(sh`cmd ${args}`); // same as above - -console.log('cmd' + args.map(a => ' ' + quoteForShell(a, true)).join('')); -console.log(sh`cmd "${args}"`); // same as above -``` - -Additionally, on Windows, `sh` checks the entire command string for pipes, -which subtly change how arguments need to be quoted. If your commands may -involve pipes, you are strongly encouraged to use `sh` and not try to roll -your own with `quoteForShell`. - -##### Parameters - -- `text` **[String][2]** to be quoted -- `forceQuote` **[Boolean][3]?** whether to always add quotes even if the string - is already safe. Defaults to `false`. -- `platform` **[String][2]?** a value that `process.platform` might take: - `'win32'`, `'linux'`, etc.; determines how the string is to be formatted. - When omitted, effectively the same as `process.platform`. - -Returns **[String][2]** a string that is safe for the current (or specified) -platform. - -#### quoteForCmd - -A Windows-specific version of [quoteForShell][4]. - -##### Parameters - -- `text` **[String][2]** to be quoted -- `forceQuote` **[Boolean][3]?** whether to always add quotes even if the string - is already safe. Defaults to `false`. - -#### quoteForSh - -A Unix-specific version of [quoteForShell][4]. - -##### Parameters - -- `text` **[String][2]** to be quoted -- `forceQuote` **[Boolean][3]?** whether to always add quotes even if the string - is already safe. Defaults to `false`. - -#### ShellString - -A ShellString represents a shell command after it has been interpolated, but -before it has been formatted for a particular platform. ShellStrings are -useful if you want to prepare a command for a different platform than the -current one, for instance. - -To create a ShellString, use `ShellString.sh` the same way you would use -top-level `sh`. - -##### toString - -A method to format a ShellString into a regular String formatted for a -particular platform. - -###### Parameters - -- `platform` **[String][2]?** a value that `process.platform` might take: - `'win32'`, `'linux'`, etc.; determines how the string is to be formatted. - When omitted, effectively the same as `process.platform`. - -Returns **[String][2]** - -##### sh - -`ShellString.sh` is a template tag just like `sh`; the only difference is -that this function returns a ShellString which has not yet been formatted -into a String. - -Returns **[ShellString][5]** - -### Secret API - -Some internals of string formatting have been exposed for the ambitious and -brave souls who want to try to extend Puka to handle more shells or custom -interpolated values. This ‘secret’ API is partially documented in the code -but not here, and the semantic versioning guarantees on this API are bumped -down by one level: in other words, minor version releases of Puka can change -the secret API in backward-incompatible ways, and patch releases can add or -deprecate functionality. - -If it's not even documented in the code, use at your own risk—no semver -guarantees apply. - - -[1]: #the-sh-dsl - -[2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String - -[3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean - -[4]: #quoteforshell - -[5]: #shellstring - -## The sh DSL - -### Syntax - -An `sh` template comprises words, separated by whitespace. Words can contain: - -- text, which is composed of any characters that are not whitespace, single or - double quotes, or any of the special characters - ``# $ & ( ) ; < > \ ` |``; -- quotations, which are matching single or double quotes surrounding any - characters other than the delimiting quote; and -- placeholders, using the standard JavaScript template syntax (`${}`). - (Placeholders may also appear inside quotations.) - -The special characters ``# $ & ( ) ; < > \ ` |``, if unquoted, form their own -words. - -Redirect operators (`<`, `>`, `>>`, `2>`, etc.) receive their own special -handling, as do semicolons. Other than these two exceptions, no attempt is made -to understand any more sophisticated features of shell syntax. - -Standard JavaScript escape sequences, such as `\t`, are honored in the template -literal, and are treated equivalently to the characters they represent. There -is no further mechanism for escaping within the `sh` DSL itself; in particular, -if you want to put quotes inside quotes, you have to use interpolation, like -this: - -```javascript -sh`echo "${'single = \', double = "'}"` // => "echo 'single = '\\'', double = \"'" -``` - -### Semantics - -Words that do not contain placeholders are emitted mostly verbatim to the -output string. Quotations are formatted in the expected style for the target -platform (single quotes for Unix, double quotes for Windows) regardless of the -quotes used in the template literal—as with JavaScript, single and double quotes -are interchangeable, except for the requirement to pair like with like. Unquoted -semicolons are translated to ampersands on Windows; all other special characters -(as enumerated above), when unquoted, are passed as-is to the output for the -shell to interpret. - -Puka may still quote words not containing the above special characters, if they -contain characters that need quoting on the target platform. For example, on -Windows, the character `%` is used for variable interpolation in `cmd.exe`, and -Puka quotes it on on that platform even if it appears unquoted in the template -literal. Consequently, there is no need to be paranoid about quoting anything -that doesn't look alphanumeric inside a `sh` template literal, for fear of being -burned on a different operating system; anything that matches the definition of -‘text’ above will never need manual quoting. - -#### Types of placeholders - -##### Strings - -If a word contains a string placeholder, then the value of the placeholder is -interpolated into the word and the entire word, if necessary, is quoted. If -the placeholder occurs within quotes, no further quoting is performed: - -```javascript -sh`script --file="${'herp derp'}.txt"`; // => "script --file='herp derp.txt'" -``` - -This behavior can be exploited to force consistent quoting, if desired; but -both of the examples below are safe on all platforms: - -```javascript -const words = ['oneword', 'two words']; -sh`minimal ${words[0]}`; // => "minimal oneword" -sh`minimal ${words[1]}`; // => "minimal 'two words'" -sh`consistent '${words[0]}'`; // => "consistent 'oneword'" -sh`consistent '${words[1]}'`; // => "consistent 'two words'" -``` - -##### Arrays and iterables - -If a word contains a placeholder for an array (or other iterable object), then -the entire word is repeated once for each value in the array, separated by -spaces. If the array is empty, then the word is not emitted at all, and neither -is any leading whitespace. - -```javascript -const files = ['foo', 'bar']; -sh`script ${files}`; // => "script foo bar" -sh`script --file=${files}`; // => "script --file=foo --file=bar" -sh`script --file=${[]}`; // => "script" -``` - -Note that, since special characters are their own words, the pipe operator here -is not repeated: - -```javascript -const cmd = ['script', 'foo', 'bar']; -sh`${cmd}|another-script`; // => "script foo bar|another-script" -``` - -Multiple arrays in the same word generate a Cartesian product: - -```javascript -const names = ['foo', 'bar'], exts = ['log', 'txt']; -// Same word -sh`... ${names}.${exts}`; // => "... foo.log foo.txt bar.log bar.txt" -sh`... "${names} ${exts}"`; // => "... 'foo log' 'foo txt' 'bar log' 'bar txt'" - -// Not the same word (extra space just for emphasis): -sh`... ${names} ${exts}`; // => "... foo bar log txt" -sh`... ${names};${exts}`; // => "... foo bar;log txt" -``` - -Finally, if a placeholder appears in the object of a redirect operator, the -entire redirect is repeated as necessary: - -```javascript -sh`script > ${['foo', 'bar']}.txt`; // => "script > foo.txt > bar.txt" -sh`script > ${[]}.txt`; // => "script" -``` - -##### unquoted - -The `unquoted` function returns a value that will skip being quoted when used -in a placeholder, alone or in an array. - -```javascript -const cmd = 'script < input.txt'; -const fields = ['foo', 'bar']; -sh`${unquoted(cmd)} | json ${fields}`; // => "script < input.txt | json foo bar" -``` - -##### ShellString - -If `ShellString.sh` is used to construct an unformatted ShellString, that value -can be used in a placeholder to insert the contents of the ShellString into the -outer template literal. This is safer than using `unquoted` as in the previous -example, but `unquoted` can be used when all you have is a string from another -(trusted!) source. - -```javascript -const url = 'http://example.com/data.json?x=1&y=2'; -const curl = ShellString.sh`curl -L ${url}`; -const fields = ['foo', 'bar']; -sh`${curl} | json ${fields}`; // => "curl -L 'http://example.com/data.json?x=1&y=2' | json foo bar" -``` - -##### Anything else - -... is treated like a string—namely, a value `x` is equivalent to `'' + x`, if -not in one of the above categories. diff --git a/deps/npm/node_modules/puka/index.js b/deps/npm/node_modules/puka/index.js deleted file mode 100644 index b69e47d763..0000000000 --- a/deps/npm/node_modules/puka/index.js +++ /dev/null @@ -1,804 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, '__esModule', { value: true }); - -/** - * Key a method on your object with this symbol and you can get special - * formatting for that value! See ShellStringText, ShellStringUnquoted, or - * shellStringSemicolon for examples. - * @ignore - */ -const formatSymbol = Symbol('format'); -/** - * This symbol is for implementing advanced behaviors like the need for extra - * carets in Windows shell strings that use pipes. If present, it's called in - * an earlier phase than formatSymbol, and is passed a mutable context that can - * be read during the format phase to influence formatting. - * @ignore - */ -const preformatSymbol = Symbol('preformat'); - -// When minimum Node version becomes 6, replace calls to sticky with /.../y and -// inline execFrom. -let stickySupported = true; -try { - new RegExp('', 'y'); -} catch (e) { - stickySupported = false; -} -const sticky = stickySupported ? source => new RegExp(source, 'y') : source => new RegExp(`^(?:${source})`); -const execFrom = stickySupported ? (re, haystack, index) => (re.lastIndex = index, re.exec(haystack)) : (re, haystack, index) => re.exec(haystack.substr(index)); - -function quoteForCmd(text, forceQuote) { - let caretDepth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; - // See the below blog post for an explanation of this function and - // quoteForWin32: - // https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/ - if (!text.length) { - return '""'; - } - if (/[\n\r]/.test(text)) { - throw new Error("Line breaks can't be quoted on Windows"); - } - const caretEscape = /["%]/.test(text); - text = quoteForWin32(text, forceQuote || !caretEscape && /[&()<>^|]/.test(text)); - if (caretEscape) { - // See Win32Context for explanation of what caretDepth is for. - do { - text = text.replace(/[\t "%&()<>^|]/g, '^$&'); - } while (caretDepth--); - } - return text; -} -const quoteForWin32 = (text, forceQuote) => forceQuote || /[\t "]/.test(text) ? `"${text.replace(/\\+(?=$|")/g, '$&$&').replace(/"/g, '\\"')}"` : text; -const cmdMetaChars = /[\t\n\r "%&()<>^|]/; -class Win32Context { - constructor() { - this.currentScope = newScope(null); - this.scopesByObject = new Map(); - this.argDetectState = 0; - this.argSet = new Set(); - } - read(text) { - // When cmd.exe executes a batch file, or pipes to or from one, it spawns a - // second copy of itself to run the inner command. This necessitates - // doubling up on carets so that escaped characters survive both cmd.exe - // invocations. See: - // https://stackoverflow.com/questions/8192318/why-does-delayed-expansion-fail-when-inside-a-piped-block-of-code#8194279 - // https://ss64.com/nt/syntax-redirection.html - // - // Parentheses can create an additional subshell, requiring additional - // escaping... it's a mess. - // - // So here's what we do about it: we read all unquoted text in a shell - // string and put it through this tiny parser that looks for pipes, - // sequence operators (&, &&, ||), redirects, and parentheses. This can't - // be part of the main Puka parsing, because it can be affected by - // `unquoted(...)` values provided at evaluation time. - // - // Then, after associating each thing that needs to be quoted with a scope - // (via `mark()`), and identifying whether or not it's an argument to a - // command, we can determine the depth of caret escaping required in each - // scope and pass it (via `Formatter::quote()`) to `quoteForCmd()`. - // - // See also `ShellStringText`, which holds the logic for the previous - // paragraph. - const length = text.length; - for (let pos = 0, match; pos < length;) { - while (match = execFrom(reUnimportant, text, pos)) { - if (match[2] == null) { - // (not whitespace) - if (match[1] != null) { - // (>&) - this.argDetectState = this.argDetectState === 0 ? ADS_FLAG_INITIAL_REDIRECT : 0; - } else if (this.argDetectState !== ADS_FLAG_ARGS) { - this.argDetectState |= ADS_FLAG_WORD; - } - } else { - // (whitespace) - if ((this.argDetectState & ADS_FLAG_WORD) !== 0) { - this.argDetectState = ADS_FLAG_ARGS & ~this.argDetectState >> 1; - } - } - pos += match[0].length; - } - if (pos >= length) break; - if (match = execFrom(reSeqOp, text, pos)) { - this.seq(); - pos += match[0].length; - } else { - const char = text.charCodeAt(pos); - if (char === CARET) { - pos += 2; - } else if (char === QUOTE) { - // If you were foolish enough to leave a dangling quotation mark in - // an unquoted span... you're likely to have bigger problems than - // incorrect escaping. So we just do the simplest thing of looking for - // the end quote only in this piece of text. - pos += execFrom(reNotQuote, text, pos + 1)[0].length + 2; - } else { - if (char === OPEN_PAREN) { - this.enterScope(); - } else if (char === CLOSE_PAREN) { - this.exitScope(); - } else if (char === PIPE) { - this.pipe(); - } else { - // (char === '<' or '>') - this.argDetectState = this.argDetectState === 0 ? ADS_FLAG_INITIAL_REDIRECT : 0; - } - pos++; - } - } - } - } - enterScope() { - this.currentScope = newScope(this.currentScope); - this.argDetectState = 0; - } - exitScope() { - this.currentScope = this.currentScope.parent || (this.currentScope.parent = newScope(null)); - this.argDetectState = ADS_FLAG_ARGS; - } - seq() { - // | binds tighter than sequence operators, so the latter create new sibling - // scopes for future |s to mutate. - this.currentScope = newScope(this.currentScope.parent); - this.argDetectState = 0; - } - pipe() { - this.currentScope.depthDelta = 1; - this.argDetectState = 0; - } - mark(obj) { - this.scopesByObject.set(obj, this.currentScope); - if (this.argDetectState === ADS_FLAG_ARGS) { - this.argSet.add(obj); - } else { - this.argDetectState |= ADS_FLAG_WORD; - } - } - at(obj) { - const scope = this.scopesByObject.get(obj); - return { - depth: getDepth(scope), - isArgument: this.argSet.has(obj), - isNative: scope.isNative - }; - } -} -// These flags span the Win32Context's argument detection state machine. WORD -// is set when the context is inside a word that is not an argument (meaning it -// is either the first word in the command, or it is the object of a redirect). -// ARGS is set when the context has reached the arguments of a command. -// INITIAL_REDIRECT tracks the edge case when a redirect occurs before the -// first word of the command (if this flag is set, reaching the end of a word -// should take the state machine back to 0 instead of setting ADS_FLAG_ARGS). -const ADS_FLAG_WORD = 0x1; -const ADS_FLAG_ARGS = 0x2; -const ADS_FLAG_INITIAL_REDIRECT = 0x4; -const getDepth = scope => scope === null ? 0 : scope.depth !== -1 ? scope.depth : scope.depth = getDepth(scope.parent) + scope.depthDelta; -const newScope = parent => ({ - parent, - depthDelta: 0, - depth: -1, - isNative: false -}); -const CARET = '^'.charCodeAt(); -const QUOTE = '"'.charCodeAt(); -const OPEN_PAREN = '('.charCodeAt(); -const CLOSE_PAREN = ')'.charCodeAt(); -const PIPE = '|'.charCodeAt(); -const reNotQuote = sticky('[^"]*'); -const reSeqOp = sticky('&&?|\\|\\|'); -const reUnimportant = sticky('(\\d*>&)|[^\\s"$&()<>^|]+|(\\s+)'); - -const quoteForSh = (text, forceQuote) => text.length ? forceQuote || shMetaChars.test(text) ? `'${text.replace(/'/g, "'\\''")}'`.replace(/^(?:'')+(?!$)/, '').replace(/\\'''/g, "\\'") : text : "''"; -const shMetaChars = /[\t\n\r "#$&'()*;<>?\\`|~]/; - -/** - * To get a Formatter, call `Formatter.for`. - * - * To create a new Formatter, pass an object to `Formatter.declare`. - * - * To set the global default Formatter, assign to `Formatter.default`. - * - * @class - * @property {Formatter} default - The Formatter to be used when no platform - * is provided—for example, when creating strings with `sh`. - * @ignore - */ -function Formatter() {} -Object.assign(Formatter, -/** @lends Formatter */ -{ - /** - * Gets a Formatter that has been declared for the provided platform, or - * the base `'sh'` formatter if there is no Formatter specific to this - * platform, or the Formatter for the current platform if no specific platform - * is provided. - */ - for(platform) { - return platform == null ? Formatter.default || (Formatter.default = Formatter.for(process.platform)) : Formatter._registry.get(platform) || Formatter._registry.get('sh'); - }, - /** - * Creates a new Formatter or mutates the properties on an existing - * Formatter. The `platform` key on the provided properties object determines - * when the Formatter is retrieved. - */ - declare(props) { - const platform = props && props.platform || 'sh'; - const existingFormatter = Formatter._registry.get(platform); - const formatter = Object.assign(existingFormatter || new Formatter(), props); - formatter.emptyString === void 0 && (formatter.emptyString = formatter.quote('', true)); - existingFormatter || Formatter._registry.set(formatter.platform, formatter); - }, - _registry: new Map(), - prototype: { - platform: 'sh', - quote: quoteForSh, - metaChars: shMetaChars, - hasExtraMetaChars: false, - statementSeparator: ';', - createContext() { - return defaultContext; - } - } -}); -const defaultContext = { - at() {} -}; -Formatter.declare(); -Formatter.declare({ - platform: 'win32', - quote(text, forceQuote, opts) { - const caretDepth = opts ? (opts.depth || 0) + (opts.isArgument && !opts.isNative ? 1 : 0) : 0; - return quoteForCmd(text, forceQuote, caretDepth); - }, - metaChars: cmdMetaChars, - hasExtraMetaChars: true, - statementSeparator: '&', - createContext(root) { - const context = new this.Context(); - root[preformatSymbol](context); - return context; - }, - Context: Win32Context -}); - -const isObject = any => any === Object(any); -function memoize(f) { - const cache = new WeakMap(); - return arg => { - let result = cache.get(arg); - if (result === void 0) { - result = f(arg); - cache.set(arg, result); - } - return result; - }; -} - -/** - * Represents a contiguous span of text that may or must be quoted. The contents - * may already contain quoted segments, which will always be quoted. If unquoted - * segments also require quoting, the entire span will be quoted together. - * @ignore - */ -class ShellStringText { - constructor(contents, untested) { - this.contents = contents; - this.untested = untested; - } - [formatSymbol](formatter, context) { - const unformattedContents = this.contents; - const length = unformattedContents.length; - const contents = new Array(length); - for (let i = 0; i < length; i++) { - const c = unformattedContents[i]; - contents[i] = isObject(c) && formatSymbol in c ? c[formatSymbol](formatter) : c; - } - for (let unquoted = true, i = 0; i < length; i++) { - const content = contents[i]; - if (content === null) { - unquoted = !unquoted; - } else { - if (unquoted && (formatter.hasExtraMetaChars || this.untested && this.untested.has(i)) && formatter.metaChars.test(content)) { - return formatter.quote(contents.join(''), false, context.at(this)); - } - } - } - const parts = []; - for (let quoted = null, i = 0; i < length; i++) { - const content = contents[i]; - if (content === null) { - quoted = quoted ? (parts.push(formatter.quote(quoted.join(''), true, context.at(this))), null) : []; - } else { - (quoted || parts).push(content); - } - } - const result = parts.join(''); - return result.length ? result : formatter.emptyString; - } - [preformatSymbol](context) { - context.mark(this); - } -} - -/** - * Represents a contiguous span of text that will not be quoted. - * @ignore - */ -class ShellStringUnquoted { - constructor(value) { - this.value = value; - } - [formatSymbol]() { - return this.value; - } - [preformatSymbol](context) { - context.read(this.value); - } -} - -/** - * Represents a semicolon... or an ampersand, on Windows. - * @ignore - */ -const shellStringSemicolon = { - [formatSymbol](formatter) { - return formatter.statementSeparator; - }, - [preformatSymbol](context) { - context.seq(); - } -}; - -const PLACEHOLDER = {}; -const parse = memoize(templateSpans => { - // These are the token types our DSL can recognize. Their values won't escape - // this function. - const TOKEN_TEXT = 0; - const TOKEN_QUOTE = 1; - const TOKEN_SEMI = 2; - const TOKEN_UNQUOTED = 3; - const TOKEN_SPACE = 4; - const TOKEN_REDIRECT = 5; - const result = []; - let placeholderCount = 0; - let prefix = null; - let onlyPrefixOnce = false; - let contents = []; - let quote = 0; - const lastSpan = templateSpans.length - 1; - for (let spanIndex = 0; spanIndex <= lastSpan; spanIndex++) { - const templateSpan = templateSpans[spanIndex]; - const posEnd = templateSpan.length; - let tokenStart = 0; - if (spanIndex) { - placeholderCount++; - contents.push(PLACEHOLDER); - } - // For each span, we first do a recognizing pass in which we use regular - // expressions to identify the positions of tokens in the text, and then - // a second pass that actually splits the text into the minimum number of - // substrings necessary. - const recognized = []; // [type1, index1, type2, index2...] - let firstWordBreak = -1; - let lastWordBreak = -1; - { - let pos = 0, - match; - while (pos < posEnd) { - if (quote) { - if (match = execFrom(quote === CHAR_SQUO ? reQuotation1 : reQuotation2, templateSpan, pos)) { - recognized.push(TOKEN_TEXT, pos); - pos += match[0].length; - } - if (pos < posEnd) { - recognized.push(TOKEN_QUOTE, pos++); - quote = 0; - } - } else { - if (match = execFrom(reRedirectOrSpace, templateSpan, pos)) { - firstWordBreak < 0 && (firstWordBreak = pos); - lastWordBreak = pos; - recognized.push(match[1] ? TOKEN_REDIRECT : TOKEN_SPACE, pos); - pos += match[0].length; - } - if (match = execFrom(reText, templateSpan, pos)) { - const setBreaks = match[1] != null; - setBreaks && firstWordBreak < 0 && (firstWordBreak = pos); - recognized.push(setBreaks ? TOKEN_UNQUOTED : TOKEN_TEXT, pos); - pos += match[0].length; - setBreaks && (lastWordBreak = pos); - } - const char = templateSpan.charCodeAt(pos); - if (char === CHAR_SEMI) { - firstWordBreak < 0 && (firstWordBreak = pos); - recognized.push(TOKEN_SEMI, pos++); - lastWordBreak = pos; - } else if (char === CHAR_SQUO || char === CHAR_DQUO) { - recognized.push(TOKEN_QUOTE, pos++); - quote = char; - } - } - } - } - // Word breaks are only important if they separate words with placeholders, - // so we can ignore the first/last break if this is the first/last span. - spanIndex === 0 && (firstWordBreak = -1); - spanIndex === lastSpan && (lastWordBreak = posEnd); - // Here begins the second pass mentioned above. This loop runs one more - // iteration than there are tokens in recognized, because it handles tokens - // on a one-iteration delay; hence the i <= iEnd instead of i < iEnd. - const iEnd = recognized.length; - for (let i = 0, type = -1; i <= iEnd; i += 2) { - let typeNext = -1, - pos; - if (i === iEnd) { - pos = posEnd; - } else { - typeNext = recognized[i]; - pos = recognized[i + 1]; - // If the next token is space or redirect, but there's another word - // break in this span, then we can handle that token the same way we - // would handle unquoted text because it isn't being attached to a - // placeholder. - typeNext >= TOKEN_SPACE && pos !== lastWordBreak && (typeNext = TOKEN_UNQUOTED); - } - const breakHere = pos === firstWordBreak || pos === lastWordBreak; - if (pos && (breakHere || typeNext !== type)) { - let value = type === TOKEN_QUOTE ? null : type === TOKEN_SEMI ? shellStringSemicolon : templateSpan.substring(tokenStart, pos); - if (type >= TOKEN_SEMI) { - // This branch handles semicolons, unquoted text, spaces, and - // redirects. shellStringSemicolon is already a formatSymbol object; - // the rest need to be wrapped. - type === TOKEN_SEMI || (value = new ShellStringUnquoted(value)); - // We don't need to check placeholderCount here like we do below; - // that's only relevant during the first word break of the span, and - // because this iteration of the loop is processing the token that - // was checked for breaks in the previous iteration, it will have - // already been handled. For the same reason, prefix is guaranteed to - // be null. - if (contents.length) { - result.push(new ShellStringText(contents, null)); - contents = []; - } - // Only spaces and redirects become prefixes, but not if they've been - // rewritten to unquoted above. - if (type >= TOKEN_SPACE) { - prefix = value; - onlyPrefixOnce = type === TOKEN_SPACE; - } else { - result.push(value); - } - } else { - contents.push(value); - } - tokenStart = pos; - } - if (breakHere) { - if (placeholderCount) { - result.push({ - contents, - placeholderCount, - prefix, - onlyPrefixOnce - }); - } else { - // There's no prefix to handle in this branch; a prefix prior to this - // span would mean placeholderCount > 0, and a prefix in this span - // can't be created because spaces and redirects get rewritten to - // unquoted before the last word break. - contents.length && result.push(new ShellStringText(contents, null)); - } - placeholderCount = 0; - prefix = null; - onlyPrefixOnce = false; - contents = []; - } - type = typeNext; - } - } - if (quote) { - throw new SyntaxError(`String is missing a ${String.fromCharCode(quote)} character`); - } - return result; -}); -const CHAR_SEMI = ';'.charCodeAt(); -const CHAR_SQUO = "'".charCodeAt(); -const CHAR_DQUO = '"'.charCodeAt(); -const reQuotation1 = sticky("[^']+"); -const reQuotation2 = sticky('[^"]+'); -const reText = sticky('[^\\s"#$&\'();<>\\\\`|]+|([#$&()\\\\`|]+)'); -const reRedirectOrSpace = sticky('(\\s*\\d*[<>]+\\s*)|\\s+'); - -class BitSet { - constructor() { - this.vector = new Int32Array(1); - } - has(n) { - return (this.vector[n >>> 5] & 1 << n) !== 0; - } - add(n) { - const i = n >>> 5, - requiredLength = i + 1; - let vector = this.vector, - _vector = vector, - length = _vector.length; - if (requiredLength > length) { - while (requiredLength > (length *= 2)); - const oldValues = vector; - vector = new Int32Array(length); - vector.set(oldValues); - this.vector = vector; - } - vector[i] |= 1 << n; - } -} - -function evaluate(template, values) { - values = values.map(toStringishArray); - const children = []; - let valuesStart = 0; - for (let i = 0, iMax = template.length; i < iMax; i++) { - const word = template[i]; - if (formatSymbol in word) { - children.push(word); - continue; - } - const contents = word.contents, - placeholderCount = word.placeholderCount, - prefix = word.prefix, - onlyPrefixOnce = word.onlyPrefixOnce; - const kMax = contents.length; - const valuesEnd = valuesStart + placeholderCount; - const tuples = cartesianProduct(values, valuesStart, valuesEnd); - valuesStart = valuesEnd; - for (let j = 0, jMax = tuples.length; j < jMax; j++) { - const needSpace = j > 0; - const tuple = tuples[j]; - (needSpace || prefix) && children.push(needSpace && (onlyPrefixOnce || !prefix) ? unquotedSpace : prefix); - let interpolatedContents = []; - let untested = null; - let quoting = false; - let tupleIndex = 0; - for (let k = 0; k < kMax; k++) { - const content = contents[k]; - if (content === PLACEHOLDER) { - const value = tuple[tupleIndex++]; - if (quoting) { - interpolatedContents.push(value); - } else { - if (isObject(value) && formatSymbol in value) { - if (interpolatedContents.length) { - children.push(new ShellStringText(interpolatedContents, untested)); - interpolatedContents = []; - untested = null; - } - children.push(value); - } else { - (untested || (untested = new BitSet())).add(interpolatedContents.length); - interpolatedContents.push(value); - } - } - } else { - interpolatedContents.push(content); - content === null && (quoting = !quoting); - } - } - if (interpolatedContents.length) { - children.push(new ShellStringText(interpolatedContents, untested)); - } - } - } - return children; -} -const primToStringish = value => value == null ? '' + value : value; -function toStringishArray(value) { - let array; - switch (true) { - default: - if (isObject(value)) { - if (Array.isArray(value)) { - array = value; - break; - } - if (Symbol.iterator in value) { - array = Array.from(value); - break; - } - } - array = [value]; - } - return array.map(primToStringish); -} -function cartesianProduct(arrs, start, end) { - const size = end - start; - let resultLength = 1; - for (let i = start; i < end; i++) { - resultLength *= arrs[i].length; - } - if (resultLength > 1e6) { - throw new RangeError("Far too many elements to interpolate"); - } - const result = new Array(resultLength); - const indices = new Array(size).fill(0); - for (let i = 0; i < resultLength; i++) { - const value = result[i] = new Array(size); - for (let j = 0; j < size; j++) { - value[j] = arrs[j + start][indices[j]]; - } - for (let j = size - 1; j >= 0; j--) { - if (++indices[j] < arrs[j + start].length) break; - indices[j] = 0; - } - } - return result; -} -const unquotedSpace = new ShellStringUnquoted(' '); - -/** - * A ShellString represents a shell command after it has been interpolated, but - * before it has been formatted for a particular platform. ShellStrings are - * useful if you want to prepare a command for a different platform than the - * current one, for instance. - * - * To create a ShellString, use `ShellString.sh` the same way you would use - * top-level `sh`. - */ -class ShellString { - /** @hideconstructor */ - constructor(children) { - this.children = children; - } - /** - * `ShellString.sh` is a template tag just like `sh`; the only difference is - * that this function returns a ShellString which has not yet been formatted - * into a String. - * @returns {ShellString} - * @function sh - * @static - * @memberof ShellString - */ - static sh(templateSpans) { - for (var _len = arguments.length, values = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - values[_key - 1] = arguments[_key]; - } - return new ShellString(evaluate(parse(templateSpans), values)); - } - /** - * A method to format a ShellString into a regular String formatted for a - * particular platform. - * - * @param {String} [platform] a value that `process.platform` might take: - * `'win32'`, `'linux'`, etc.; determines how the string is to be formatted. - * When omitted, effectively the same as `process.platform`. - * @returns {String} - */ - toString(platform) { - return this[formatSymbol](Formatter.for(platform)); - } - [formatSymbol](formatter) { - let context = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : formatter.createContext(this); - return this.children.map(child => child[formatSymbol](formatter, context)).join(''); - } - [preformatSymbol](context) { - const children = this.children; - for (let i = 0, iMax = children.length; i < iMax; i++) { - const child = children[i]; - if (preformatSymbol in child) { - child[preformatSymbol](context); - } - } - } -} - -/** - * A Windows-specific version of {@link quoteForShell}. - * @param {String} text to be quoted - * @param {Boolean} [forceQuote] whether to always add quotes even if the string - * is already safe. Defaults to `false`. - */ - -/** - * A Unix-specific version of {@link quoteForShell}. - * @param {String} text to be quoted - * @param {Boolean} [forceQuote] whether to always add quotes even if the string - * is already safe. Defaults to `false`. - */ - -/** - * Quotes a string for injecting into a shell command. - * - * This function is exposed for some hypothetical case when the `sh` DSL simply - * won't do; `sh` is expected to be the more convenient option almost always. - * Compare: - * - * ```javascript - * console.log('cmd' + args.map(a => ' ' + quoteForShell(a)).join('')); - * console.log(sh`cmd ${args}`); // same as above - * - * console.log('cmd' + args.map(a => ' ' + quoteForShell(a, true)).join('')); - * console.log(sh`cmd "${args}"`); // same as above - * ``` - * - * Additionally, on Windows, `sh` checks the entire command string for pipes, - * which subtly change how arguments need to be quoted. If your commands may - * involve pipes, you are strongly encouraged to use `sh` and not try to roll - * your own with `quoteForShell`. - * - * @param {String} text to be quoted - * @param {Boolean} [forceQuote] whether to always add quotes even if the string - * is already safe. Defaults to `false`. - * @param {String} [platform] a value that `process.platform` might take: - * `'win32'`, `'linux'`, etc.; determines how the string is to be formatted. - * When omitted, effectively the same as `process.platform`. - * - * @returns {String} a string that is safe for the current (or specified) - * platform. - */ -function quoteForShell(text, forceQuote, platform) { - return Formatter.for(platform).quote(text, forceQuote); -} - -/** - * A string template tag for safely constructing cross-platform shell commands. - * - * An `sh` template is not actually treated as a literal string to be - * interpolated; instead, it is a tiny DSL designed to make working with shell - * strings safe, simple, and straightforward. To get started quickly, see the - * examples below. {@link #the-sh-dsl More detailed documentation} is available - * further down. - * - * @name sh - * @example - * const title = '"this" & "that"'; - * sh`script --title=${title}`; // => "script '--title=\"this\" & \"that\"'" - * // Note: these examples show results for non-Windows platforms. - * // On Windows, the above would instead be - * // 'script ^^^"--title=\\^^^"this\\^^^" ^^^& \\^^^"that\\^^^"^^^"'. - * - * const names = ['file1', 'file 2']; - * sh`rimraf ${names}.txt`; // => "rimraf file1.txt 'file 2.txt'" - * - * const cmd1 = ['cat', 'file 1.txt', 'file 2.txt']; - * const cmd2 = ['use-input', '-abc']; - * sh`${cmd1}|${cmd2}`; // => "cat 'file 1.txt' 'file 2.txt'|use-input -abc" - * - * @returns {String} - a string formatted for the platform Node is currently - * running on. - */ -const sh = function () { - return ShellString.sh.apply(ShellString, arguments).toString(); -}; - -/** - * This function permits raw strings to be interpolated into a `sh` template. - * - * **IMPORTANT**: If you're using Puka due to security concerns, make sure you - * don't pass any untrusted content to `unquoted`. This may be obvious, but - * stray punctuation in an `unquoted` section can compromise the safety of the - * entire shell command. - * - * @param value - any value (it will be treated as a string) - * - * @example - * const both = true; - * sh`foo ${unquoted(both ? '&&' : '||')} bar`; // => 'foo && bar' - */ -const unquoted = value => new ShellStringUnquoted(value); - -exports.Formatter = Formatter; -exports.ShellString = ShellString; -exports.ShellStringText = ShellStringText; -exports.ShellStringUnquoted = ShellStringUnquoted; -exports.quoteForCmd = quoteForCmd; -exports.quoteForSh = quoteForSh; -exports.quoteForShell = quoteForShell; -exports.sh = sh; -exports.shellStringSemicolon = shellStringSemicolon; -exports.formatSymbol = formatSymbol; -exports.preformatSymbol = preformatSymbol; -exports.unquoted = unquoted; diff --git a/deps/npm/node_modules/puka/package.json b/deps/npm/node_modules/puka/package.json deleted file mode 100644 index 41798dc249..0000000000 --- a/deps/npm/node_modules/puka/package.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "puka", - "version": "1.0.1", - "description": "A cross-platform library for safely passing strings through shells", - "keywords": [ - "args", - "arguments", - "cmd", - "command", - "command-line", - "cross-platform", - "escape", - "escaping", - "exec", - "linux", - "mac", - "macos", - "osx", - "quote", - "quoting", - "sh", - "shell", - "spawn", - "unix", - "win", - "win32", - "windows" - ], - "homepage": "https://gitlab.com/rhendric/puka", - "bugs": "https://gitlab.com/rhendric/puka/issues", - "license": "MIT", - "author": "Ryan Hendrickson <ryan.hendrickson@alum.mit.edu>", - "repository": "gitlab:rhendric/puka", - "dependencies": {}, - "engines": { - "node": ">=4" - } -}
\ No newline at end of file diff --git a/deps/npm/node_modules/semver/package.json b/deps/npm/node_modules/semver/package.json index d4043d38a1..4e1154195a 100644 --- a/deps/npm/node_modules/semver/package.json +++ b/deps/npm/node_modules/semver/package.json @@ -1,6 +1,6 @@ { "name": "semver", - "version": "7.3.4", + "version": "7.3.5", "description": "The semantic version parser used by npm.", "main": "index.js", "scripts": { diff --git a/deps/npm/node_modules/semver/ranges/subset.js b/deps/npm/node_modules/semver/ranges/subset.js index bb7d15fe26..532fd1364c 100644 --- a/deps/npm/node_modules/semver/ranges/subset.js +++ b/deps/npm/node_modules/semver/ranges/subset.js @@ -1,20 +1,28 @@ const Range = require('../classes/range.js') -const { ANY } = require('../classes/comparator.js') +const Comparator = require('../classes/comparator.js') +const { ANY } = Comparator const satisfies = require('../functions/satisfies.js') const compare = require('../functions/compare.js') // Complex range `r1 || r2 || ...` is a subset of `R1 || R2 || ...` iff: -// - Every simple range `r1, r2, ...` is a subset of some `R1, R2, ...` +// - Every simple range `r1, r2, ...` is a null set, OR +// - Every simple range `r1, r2, ...` which is not a null set is a subset of +// some `R1, R2, ...` // // Simple range `c1 c2 ...` is a subset of simple range `C1 C2 ...` iff: // - If c is only the ANY comparator // - If C is only the ANY comparator, return true -// - Else return false +// - Else if in prerelease mode, return false +// - else replace c with `[>=0.0.0]` +// - If C is only the ANY comparator +// - if in prerelease mode, return true +// - else replace C with `[>=0.0.0]` // - Let EQ be the set of = comparators in c // - If EQ is more than one, return true (null set) // - Let GT be the highest > or >= comparator in c // - Let LT be the lowest < or <= comparator in c // - If GT and LT, and GT.semver > LT.semver, return true (null set) +// - If any C is a = range, and GT or LT are set, return false // - If EQ // - If GT, and EQ does not satisfy GT, return true (null set) // - If LT, and EQ does not satisfy LT, return true (null set) @@ -23,13 +31,16 @@ const compare = require('../functions/compare.js') // - If GT // - If GT.semver is lower than any > or >= comp in C, return false // - If GT is >=, and GT.semver does not satisfy every C, return false +// - If GT.semver has a prerelease, and not in prerelease mode +// - If no C has a prerelease and the GT.semver tuple, return false // - If LT // - If LT.semver is greater than any < or <= comp in C, return false // - If LT is <=, and LT.semver does not satisfy every C, return false -// - If any C is a = range, and GT or LT are set, return false +// - If GT.semver has a prerelease, and not in prerelease mode +// - If no C has a prerelease and the LT.semver tuple, return false // - Else return true -const subset = (sub, dom, options) => { +const subset = (sub, dom, options = {}) => { if (sub === dom) return true @@ -58,8 +69,21 @@ const simpleSubset = (sub, dom, options) => { if (sub === dom) return true - if (sub.length === 1 && sub[0].semver === ANY) - return dom.length === 1 && dom[0].semver === ANY + if (sub.length === 1 && sub[0].semver === ANY) { + if (dom.length === 1 && dom[0].semver === ANY) + return true + else if (options.includePrerelease) + sub = [ new Comparator('>=0.0.0-0') ] + else + sub = [ new Comparator('>=0.0.0') ] + } + + if (dom.length === 1 && dom[0].semver === ANY) { + if (options.includePrerelease) + return true + else + dom = [ new Comparator('>=0.0.0') ] + } const eqSet = new Set() let gt, lt @@ -102,10 +126,32 @@ const simpleSubset = (sub, dom, options) => { let higher, lower let hasDomLT, hasDomGT + // if the subset has a prerelease, we need a comparator in the superset + // with the same tuple and a prerelease, or it's not a subset + let needDomLTPre = lt && + !options.includePrerelease && + lt.semver.prerelease.length ? lt.semver : false + let needDomGTPre = gt && + !options.includePrerelease && + gt.semver.prerelease.length ? gt.semver : false + // exception: <1.2.3-0 is the same as <1.2.3 + if (needDomLTPre && needDomLTPre.prerelease.length === 1 && + lt.operator === '<' && needDomLTPre.prerelease[0] === 0) { + needDomLTPre = false + } + for (const c of dom) { hasDomGT = hasDomGT || c.operator === '>' || c.operator === '>=' hasDomLT = hasDomLT || c.operator === '<' || c.operator === '<=' if (gt) { + if (needDomGTPre) { + if (c.semver.prerelease && c.semver.prerelease.length && + c.semver.major === needDomGTPre.major && + c.semver.minor === needDomGTPre.minor && + c.semver.patch === needDomGTPre.patch) { + needDomGTPre = false + } + } if (c.operator === '>' || c.operator === '>=') { higher = higherGT(gt, c, options) if (higher === c && higher !== gt) @@ -114,6 +160,14 @@ const simpleSubset = (sub, dom, options) => { return false } if (lt) { + if (needDomLTPre) { + if (c.semver.prerelease && c.semver.prerelease.length && + c.semver.major === needDomLTPre.major && + c.semver.minor === needDomLTPre.minor && + c.semver.patch === needDomLTPre.patch) { + needDomLTPre = false + } + } if (c.operator === '<' || c.operator === '<=') { lower = lowerLT(lt, c, options) if (lower === c && lower !== lt) @@ -134,6 +188,12 @@ const simpleSubset = (sub, dom, options) => { if (lt && hasDomGT && !gt && gtltComp !== 0) return false + // we needed a prerelease range in a specific tuple, but didn't get one + // then this isn't a subset. eg >=1.2.3-pre is not a subset of >=1.0.0, + // because it includes prereleases in the 1.2.3 tuple + if (needDomGTPre || needDomLTPre) + return false + return true } diff --git a/deps/npm/package.json b/deps/npm/package.json index afd3b36cb0..c4b10a831b 100644 --- a/deps/npm/package.json +++ b/deps/npm/package.json @@ -1,5 +1,5 @@ { - "version": "7.6.3", + "version": "7.7.0", "name": "npm", "description": "a package manager for JavaScript", "keywords": [ @@ -42,16 +42,16 @@ "./package.json": "./package.json" }, "dependencies": { - "@npmcli/arborist": "^2.2.8", + "@npmcli/arborist": "^2.2.9", "@npmcli/ci-detect": "^1.2.0", - "@npmcli/config": "^1.2.9", - "@npmcli/run-script": "^1.8.3", + "@npmcli/config": "^2.0.0", + "@npmcli/run-script": "^1.8.4", "abbrev": "~1.1.1", "ansicolors": "~0.3.2", "ansistyles": "~0.1.3", "archy": "~1.0.0", "byte-size": "^7.0.1", - "cacache": "^15.0.5", + "cacache": "^15.0.6", "chalk": "^4.1.0", "chownr": "^2.0.0", "cli-columns": "^3.1.2", @@ -59,7 +59,7 @@ "columnify": "~1.5.4", "glob": "^7.1.4", "graceful-fs": "^4.2.6", - "hosted-git-info": "^3.0.8", + "hosted-git-info": "^4.0.1", "ini": "^2.0.0", "init-package-json": "^2.0.2", "is-cidr": "^4.0.2", @@ -74,7 +74,7 @@ "libnpmpublish": "^4.0.0", "libnpmsearch": "^3.1.0", "libnpmteam": "^2.0.2", - "libnpmversion": "^1.0.11", + "libnpmversion": "^1.0.12", "make-fetch-happen": "^8.0.14", "minipass": "^3.1.3", "minipass-pipeline": "^1.2.4", @@ -84,14 +84,14 @@ "node-gyp": "^7.1.2", "nopt": "^5.0.0", "npm-audit-report": "^2.1.4", - "npm-package-arg": "^8.1.1", - "npm-pick-manifest": "^6.1.0", + "npm-package-arg": "^8.1.2", + "npm-pick-manifest": "^6.1.1", "npm-profile": "^5.0.2", "npm-registry-fetch": "^9.0.0", "npm-user-validate": "^1.0.1", "npmlog": "~4.1.2", "opener": "^1.5.2", - "pacote": "^11.3.0", + "pacote": "^11.3.1", "parse-conflict-json": "^1.1.1", "qrcode-terminal": "^0.12.0", "read": "~1.0.7", @@ -99,7 +99,7 @@ "read-package-json-fast": "^2.0.2", "readdir-scoped-modules": "^1.1.0", "rimraf": "^3.0.2", - "semver": "^7.3.4", + "semver": "^7.3.5", "ssri": "^8.0.1", "tar": "^6.1.0", "text-table": "~0.2.0", @@ -180,17 +180,17 @@ "devDependencies": { "@mdx-js/mdx": "^1.6.22", "cmark-gfm": "^0.8.5", - "eslint": "^7.21.0", + "eslint": "^7.22.0", "eslint-plugin-import": "^2.22.1", "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^4.3.1", "eslint-plugin-standard": "^5.0.0", - "jsdom": "^16.4.0", + "jsdom": "^16.5.1", "licensee": "^8.1.0", "marked-man": "^0.7.0", "require-inject": "^1.4.4", "tap": "^14.11.0", - "yaml": "^1.10.0" + "yaml": "^1.10.2" }, "scripts": { "dumpconf": "env | grep npm | sort | uniq", diff --git a/deps/npm/tap-snapshots/test-lib-dist-tag.js-TAP.test.js b/deps/npm/tap-snapshots/test-lib-dist-tag.js-TAP.test.js index 89a87ae64e..06936795bc 100644 --- a/deps/npm/tap-snapshots/test-lib-dist-tag.js-TAP.test.js +++ b/deps/npm/tap-snapshots/test-lib-dist-tag.js-TAP.test.js @@ -8,6 +8,8 @@ exports[`test/lib/dist-tag.js TAP add missing args > should exit usage error message 1`] = ` npm dist-tag +Modify package distribution tags + Usage: npm dist-tag add <pkg>@<version> [<tag>] npm dist-tag rm <pkg> <tag> @@ -21,6 +23,8 @@ Run "npm help dist-tag" for more info exports[`test/lib/dist-tag.js TAP add missing pkg name > should exit usage error message 1`] = ` npm dist-tag +Modify package distribution tags + Usage: npm dist-tag add <pkg>@<version> [<tag>] npm dist-tag rm <pkg> <tag> @@ -43,6 +47,8 @@ dist-tag add 1.0.0 to @scoped/another@7.7.7 exports[`test/lib/dist-tag.js TAP borked cmd usage > should show usage error 1`] = ` npm dist-tag +Modify package distribution tags + Usage: npm dist-tag add <pkg>@<version> [<tag>] npm dist-tag rm <pkg> <tag> @@ -62,6 +68,8 @@ latest: 1.0.0 exports[`test/lib/dist-tag.js TAP ls on missing name in current package > should throw usage error message 1`] = ` npm dist-tag +Modify package distribution tags + Usage: npm dist-tag add <pkg>@<version> [<tag>] npm dist-tag rm <pkg> <tag> @@ -111,6 +119,8 @@ exports[`test/lib/dist-tag.js TAP remove existing tag > should return success ms exports[`test/lib/dist-tag.js TAP remove missing pkg name > should exit usage error message 1`] = ` npm dist-tag +Modify package distribution tags + Usage: npm dist-tag add <pkg>@<version> [<tag>] npm dist-tag rm <pkg> <tag> diff --git a/deps/npm/tap-snapshots/test-lib-publish.js-TAP.test.js b/deps/npm/tap-snapshots/test-lib-publish.js-TAP.test.js index 97ce7a7733..172ed5b29f 100644 --- a/deps/npm/tap-snapshots/test-lib-publish.js-TAP.test.js +++ b/deps/npm/tap-snapshots/test-lib-publish.js-TAP.test.js @@ -8,8 +8,13 @@ exports[`test/lib/publish.js TAP shows usage with wrong set of arguments > should print usage 1`] = ` npm publish +Publish a package + Usage: -npm publish [<folder>] [--tag <tag>] [--access <public|restricted>] [--dry-run] +npm publish [<folder>] + +Options: +[--tag <tag>] [--access <restricted|public>] [--dry-run] Run "npm help publish" for more info ` diff --git a/deps/npm/tap-snapshots/test-lib-utils-config-definition.js-TAP.test.js b/deps/npm/tap-snapshots/test-lib-utils-config-definition.js-TAP.test.js new file mode 100644 index 0000000000..ad506ae8e3 --- /dev/null +++ b/deps/npm/tap-snapshots/test-lib-utils-config-definition.js-TAP.test.js @@ -0,0 +1,264 @@ +/* IMPORTANT + * This snapshot file is auto-generated, but designed for humans. + * It should be checked into source control and tracked carefully. + * Re-generate by setting TAP_SNAPSHOT=1 and running tests. + * Make sure to inspect the output below. Do not ignore changes! + */ +'use strict' +exports[`test/lib/utils/config/definition.js TAP basic definition > description of deprecated thing 1`] = ` +#### \`deprecated\` + +* Default: A number bigger than 1 +* Type: An expression of a numeric quantity using numerals +* DEPRECATED: do not use this + +it should not be used ever + +not even once. +` + +exports[`test/lib/utils/config/definition.js TAP basic definition > human-readable description 1`] = ` +#### \`key\` + +* Default: "some default value" +* Type: Number or String + +just a test thingie +` + +exports[`test/lib/utils/config/definition.js TAP long description > cols=-1 1`] = ` +#### \`walden\` + +* Default: true +* Type: Boolean + +WHEN I WROTE the +following pages, +or rather the +bulk of them, I +lived alone, in +the woods, a +mile from any +neighbor, in a +house which I +had built +myself, on the +shore of Walden +Pond, in +Concord, +Massachusetts, +and earned my +living by the +labor of my +hands only. I +lived there two +years and two +months. At +present I am a +sojourner in +civilized life +again. + +I should not +obtrude my +affairs so much +on the notice of +my readers if +very particular +inquiries had +not been made by +my townsmen +concerning my +mode of life, +which some would +call +impertinent, +though they do +not appear to me +at all +impertinent, +but, considering +the +circumstances, +very natural and +pertinent. + +\`\`\` +this.is('a', { + code: 'sample', +}) + +with (multiple) { + blocks() +} +\`\`\` + +` + +exports[`test/lib/utils/config/definition.js TAP long description > cols=0 1`] = ` +#### \`walden\` + +* Default: true +* Type: Boolean + +WHEN I WROTE the +following pages, +or rather the +bulk of them, I +lived alone, in +the woods, a +mile from any +neighbor, in a +house which I +had built +myself, on the +shore of Walden +Pond, in +Concord, +Massachusetts, +and earned my +living by the +labor of my +hands only. I +lived there two +years and two +months. At +present I am a +sojourner in +civilized life +again. + +I should not +obtrude my +affairs so much +on the notice of +my readers if +very particular +inquiries had +not been made by +my townsmen +concerning my +mode of life, +which some would +call +impertinent, +though they do +not appear to me +at all +impertinent, +but, considering +the +circumstances, +very natural and +pertinent. + +\`\`\` +this.is('a', { + code: 'sample', +}) + +with (multiple) { + blocks() +} +\`\`\` + +` + +exports[`test/lib/utils/config/definition.js TAP long description > cols=40 1`] = ` +#### \`walden\` + +* Default: true +* Type: Boolean + +WHEN I WROTE the following pages, or +rather the bulk of them, I lived +alone, in the woods, a mile from any +neighbor, in a house which I had +built myself, on the shore of Walden +Pond, in Concord, Massachusetts, and +earned my living by the labor of my +hands only. I lived there two years +and two months. At present I am a +sojourner in civilized life again. + +I should not obtrude my affairs so +much on the notice of my readers if +very particular inquiries had not +been made by my townsmen concerning +my mode of life, which some would +call impertinent, though they do not +appear to me at all impertinent, +but, considering the circumstances, +very natural and pertinent. + +\`\`\` +this.is('a', { + code: 'sample', +}) + +with (multiple) { + blocks() +} +\`\`\` + +` + +exports[`test/lib/utils/config/definition.js TAP long description > cols=9000 1`] = ` +#### \`walden\` + +* Default: true +* Type: Boolean + +WHEN I WROTE the following pages, or rather the bulk of them, I lived alone, +in the woods, a mile from any neighbor, in a house which I had built myself, +on the shore of Walden Pond, in Concord, Massachusetts, and earned my living +by the labor of my hands only. I lived there two years and two months. At +present I am a sojourner in civilized life again. + +I should not obtrude my affairs so much on the notice of my readers if very +particular inquiries had not been made by my townsmen concerning my mode of +life, which some would call impertinent, though they do not appear to me at +all impertinent, but, considering the circumstances, very natural and +pertinent. + +\`\`\` +this.is('a', { + code: 'sample', +}) + +with (multiple) { + blocks() +} +\`\`\` + +` + +exports[`test/lib/utils/config/definition.js TAP long description > cols=NaN 1`] = ` +#### \`walden\` + +* Default: true +* Type: Boolean + +WHEN I WROTE the following pages, or rather the bulk of them, I lived alone, +in the woods, a mile from any neighbor, in a house which I had built myself, +on the shore of Walden Pond, in Concord, Massachusetts, and earned my living +by the labor of my hands only. I lived there two years and two months. At +present I am a sojourner in civilized life again. + +I should not obtrude my affairs so much on the notice of my readers if very +particular inquiries had not been made by my townsmen concerning my mode of +life, which some would call impertinent, though they do not appear to me at +all impertinent, but, considering the circumstances, very natural and +pertinent. + +\`\`\` +this.is('a', { + code: 'sample', +}) + +with (multiple) { + blocks() +} +\`\`\` + +` diff --git a/deps/npm/tap-snapshots/test-lib-utils-config-definitions.js-TAP.test.js b/deps/npm/tap-snapshots/test-lib-utils-config-definitions.js-TAP.test.js new file mode 100644 index 0000000000..2ed810da8a --- /dev/null +++ b/deps/npm/tap-snapshots/test-lib-utils-config-definitions.js-TAP.test.js @@ -0,0 +1,156 @@ +/* IMPORTANT + * This snapshot file is auto-generated, but designed for humans. + * It should be checked into source control and tracked carefully. + * Re-generate by setting TAP_SNAPSHOT=1 and running tests. + * Make sure to inspect the output below. Do not ignore changes! + */ +'use strict' +exports[`test/lib/utils/config/definitions.js TAP > all config keys 1`] = ` +Array [ + "_auth", + "access", + "all", + "allow-same-version", + "also", + "always-auth", + "audit", + "audit-level", + "auth-type", + "before", + "bin-links", + "browser", + "ca", + "cache", + "cache-max", + "cache-min", + "cafile", + "call", + "cert", + "ci-name", + "cidr", + "color", + "commit-hooks", + "depth", + "description", + "diff", + "diff-ignore-all-space", + "diff-name-only", + "diff-no-prefix", + "diff-dst-prefix", + "diff-src-prefix", + "diff-text", + "diff-unified", + "dry-run", + "editor", + "engine-strict", + "fetch-retries", + "fetch-retry-factor", + "fetch-retry-maxtimeout", + "fetch-retry-mintimeout", + "fetch-timeout", + "force", + "foreground-scripts", + "format-package-lock", + "fund", + "git", + "git-tag-version", + "global", + "global-style", + "globalconfig", + "heading", + "https-proxy", + "if-present", + "ignore-scripts", + "include", + "include-staged", + "init-author-email", + "init-author-name", + "init-author-url", + "init-license", + "init-module", + "init-version", + "init.author.email", + "init.author.name", + "init.author.url", + "init.license", + "init.module", + "init.version", + "json", + "key", + "legacy-bundling", + "legacy-peer-deps", + "link", + "local-address", + "loglevel", + "logs-max", + "long", + "maxsockets", + "message", + "node-options", + "node-version", + "noproxy", + "npm-version", + "offline", + "omit", + "only", + "optional", + "otp", + "package", + "package-lock", + "package-lock-only", + "parseable", + "prefer-offline", + "prefer-online", + "prefix", + "preid", + "production", + "progress", + "proxy", + "read-only", + "rebuild-bundle", + "registry", + "save", + "save-bundle", + "save-dev", + "save-exact", + "save-optional", + "save-peer", + "save-prefix", + "save-prod", + "scope", + "script-shell", + "searchexclude", + "searchlimit", + "searchopts", + "searchstaleness", + "shell", + "shrinkwrap", + "sign-git-commit", + "sign-git-tag", + "sso-poll-frequency", + "sso-type", + "strict-peer-deps", + "strict-ssl", + "tag", + "tag-version-prefix", + "timing", + "tmp", + "umask", + "unicode", + "update-notifier", + "usage", + "user-agent", + "userconfig", + "version", + "versions", + "viewer", + "which", + "workspace", + "workspaces", + "yes", +] +` + +exports[`test/lib/utils/config/definitions.js TAP > all config keys that are shared to flatOptions 1`] = ` +Array [] +` diff --git a/deps/npm/tap-snapshots/test-lib-utils-config-describe-all.js-TAP.test.js b/deps/npm/tap-snapshots/test-lib-utils-config-describe-all.js-TAP.test.js new file mode 100644 index 0000000000..8323e793e0 --- /dev/null +++ b/deps/npm/tap-snapshots/test-lib-utils-config-describe-all.js-TAP.test.js @@ -0,0 +1,1377 @@ +/* IMPORTANT + * This snapshot file is auto-generated, but designed for humans. + * It should be checked into source control and tracked carefully. + * Re-generate by setting TAP_SNAPSHOT=1 and running tests. + * Make sure to inspect the output below. Do not ignore changes! + */ +'use strict' +exports[`test/lib/utils/config/describe-all.js TAP > must match snapshot 1`] = ` +#### \`_auth\` + +* Default: null +* Type: null or String + +A basic-auth string to use when authenticating against the npm registry. + +Warning: This should generally not be set via a command-line option. It is +safer to use a registry-provided authentication bearer token stored in the +~/.npmrc file by running \`npm login\`. + +#### \`access\` + +* Default: 'restricted' for scoped packages, 'public' for unscoped packages +* Type: null, "restricted", or "public" + +When publishing scoped packages, the access level defaults to \`restricted\`. +If you want your scoped package to be publicly viewable (and installable) +set \`--access=public\`. The only valid values for \`access\` are \`public\` and +\`restricted\`. Unscoped packages _always_ have an access level of \`public\`. + +#### \`all\` + +* Default: false +* Type: Boolean + +When running \`npm outdated\` and \`npm ls\`, setting \`--all\` will show all +outdated or installed packages, rather than only those directly depended +upon by the current project. + +#### \`allow-same-version\` + +* Default: false +* Type: Boolean + +Prevents throwing an error when \`npm version\` is used to set the new version +to the same value as the current version. + +#### \`always-auth\` + +* Default: false +* Type: Boolean + +Force npm to always require authentication when accessing the registry, even +for \`GET\` requests. + +#### \`audit\` + +* Default: true +* Type: Boolean + +When "true" submit audit reports alongside \`npm install\` runs to the default +registry and all registries configured for scopes. See the documentation for +[\`npm audit\`](/commands/npm-audit) for details on what is submitted. + +#### \`audit-level\` + +* Default: null +* Type: "low", "moderate", "high", "critical", "none", or null + +The minimum level of vulnerability for \`npm audit\` to exit with a non-zero +exit code. + +#### \`before\` + +* Default: null +* Type: null or Date + +If passed to \`npm install\`, will rebuild the npm tree such that only +versions that were available **on or before** the \`--before\` time get +installed. If there's no versions available for the current set of direct +dependencies, the command will error. + +If the requested version is a \`dist-tag\` and the given tag does not pass the +\`--before\` filter, the most recent version less than or equal to that tag +will be used. For example, \`foo@latest\` might install \`foo@1.2\` even though +\`latest\` is \`2.0\`. + +#### \`bin-links\` + +* Default: true +* Type: Boolean + +Tells npm to create symlinks (or \`.cmd\` shims on Windows) for package +executables. + +Set to false to have it not do this. This can be used to work around the +fact that some file systems don't support symlinks, even on ostensibly Unix +systems. + +#### \`browser\` + +* Default: OS X: \`"open"\`, Windows: \`"start"\`, Others: \`"xdg-open"\` +* Type: null, Boolean, or String + +The browser that is called by npm commands to open websites. + +Set to \`false\` to suppress browser behavior and instead print urls to +terminal. + +Set to \`true\` to use default system URL opener. + +#### \`ca\` + +* Default: null +* Type: null or String (can be set multiple times) + +The Certificate Authority signing certificate that is trusted for SSL +connections to the registry. Values should be in PEM format (Windows calls +it "Base-64 encoded X.509 (.CER)") with newlines replaced by the string +"\\n". For example: + +\`\`\`ini +ca="-----BEGIN CERTIFICATE-----\\nXXXX\\nXXXX\\n-----END CERTIFICATE-----" +\`\`\` + +Set to \`null\` to only allow "known" registrars, or to a specific CA cert to +trust only that specific signing authority. + +Multiple CAs can be trusted by specifying an array of certificates: + +\`\`\`ini +ca[]="..." +ca[]="..." +\`\`\` + +See also the \`strict-ssl\` config. + +#### \`cache\` + +* Default: Windows: \`%LocalAppData%\\npm-cache\`, Posix: \`~/.npm\` +* Type: Path + +The location of npm's cache directory. See [\`npm +cache\`](/commands/npm-cache) + +#### \`cafile\` + +* Default: null +* Type: Path + +A path to a file containing one or multiple Certificate Authority signing +certificates. Similar to the \`ca\` setting, but allows for multiple CA's, as +well as for the CA information to be stored in a file on disk. + +#### \`call\` + +* Default: "" +* Type: String + +Optional companion option for \`npm exec\`, \`npx\` that allows for specifying a +custom command to be run along with the installed packages. + +\`\`\`bash +npm exec --package yo --package generator-node --call "yo node" +\`\`\` + + +#### \`cert\` + +* Default: null +* Type: null or String + +A client certificate to pass when accessing the registry. Values should be +in PEM format (Windows calls it "Base-64 encoded X.509 (.CER)") with +newlines replaced by the string "\\n". For example: + +\`\`\`ini +cert="-----BEGIN CERTIFICATE-----\\nXXXX\\nXXXX\\n-----END CERTIFICATE-----" +\`\`\` + +It is _not_ the path to a certificate file (and there is no "certfile" +option). + +#### \`ci-name\` + +* Default: The name of the current CI system, or \`null\` when not on a known CI + platform. +* Type: null or String + +The name of a continuous integration system. If not set explicitly, npm will +detect the current CI environment using the +[\`@npmcli/ci-detect\`](http://npm.im/@npmcli/ci-detect) module. + +#### \`cidr\` + +* Default: null +* Type: null or String (can be set multiple times) + +This is a list of CIDR address to be used when configuring limited access +tokens with the \`npm token create\` command. + +#### \`color\` + +* Default: true unless the NO_COLOR environ is set to something other than '0' +* Type: "always" or Boolean + +If false, never shows colors. If \`"always"\` then always shows colors. If +true, then only prints color codes for tty file descriptors. + +#### \`commit-hooks\` + +* Default: true +* Type: Boolean + +Run git commit hooks when using the \`npm version\` command. + +#### \`depth\` + +* Default: \`Infinity\` if \`--all\` is set, otherwise \`1\` +* Type: null or Number + +The depth to go when recursing packages for \`npm ls\`. + +If not set, \`npm ls\` will show only the immediate dependencies of the root +project. If \`--all\` is set, then npm will show all dependencies by default. + +#### \`description\` + +* Default: true +* Type: Boolean + +Show the description in \`npm search\` + +#### \`diff\` + +* Default: +* Type: String (can be set multiple times) + +Define arguments to compare in \`npm diff\`. + +#### \`diff-dst-prefix\` + +* Default: "b/" +* Type: String + +Destination prefix to be used in \`npm diff\` output. + +#### \`diff-ignore-all-space\` + +* Default: false +* Type: Boolean + +Ignore whitespace when comparing lines in \`npm diff\`. + +#### \`diff-name-only\` + +* Default: false +* Type: Boolean + +Prints only filenames when using \`npm diff\`. + +#### \`diff-no-prefix\` + +* Default: false +* Type: Boolean + +Do not show any source or destination prefix in \`npm diff\` output. + +Note: this causes \`npm diff\` to ignore the \`--diff-src-prefix\` and +\`--diff-dst-prefix\` configs. + +#### \`diff-src-prefix\` + +* Default: "a/" +* Type: String + +Source prefix to be used in \`npm diff\` output. + +#### \`diff-text\` + +* Default: false +* Type: Boolean + +Treat all files as text in \`npm diff\`. + +#### \`diff-unified\` + +* Default: 3 +* Type: Number + +The number of lines of context to print in \`npm diff\`. + +#### \`dry-run\` + +* Default: false +* Type: Boolean + +Indicates that you don't want npm to make any changes and that it should +only report what it would have done. This can be passed into any of the +commands that modify your local installation, eg, \`install\`, \`update\`, +\`dedupe\`, \`uninstall\`, as well as \`pack\` and \`publish\`. + +Note: This is NOT honored by other network related commands, eg \`dist-tags\`, +\`owner\`, etc. + +#### \`editor\` + +* Default: The EDITOR or VISUAL environment variables, or 'notepad.exe' on + Windows, or 'vim' on Unix systems +* Type: String + +The command to run for \`npm edit\` and \`npm config edit\`. + +#### \`engine-strict\` + +* Default: false +* Type: Boolean + +If set to true, then npm will stubbornly refuse to install (or even consider +installing) any package that claims to not be compatible with the current +Node.js version. + +This can be overridden by setting the \`--force\` flag. + +#### \`fetch-retries\` + +* Default: 2 +* Type: Number + +The "retries" config for the \`retry\` module to use when fetching packages +from the registry. + +npm will retry idempotent read requests to the registry in the case of +network failures or 5xx HTTP errors. + +#### \`fetch-retry-factor\` + +* Default: 10 +* Type: Number + +The "factor" config for the \`retry\` module to use when fetching packages. + +#### \`fetch-retry-maxtimeout\` + +* Default: 60000 (1 minute) +* Type: Number + +The "maxTimeout" config for the \`retry\` module to use when fetching +packages. + +#### \`fetch-retry-mintimeout\` + +* Default: 10000 (10 seconds) +* Type: Number + +The "minTimeout" config for the \`retry\` module to use when fetching +packages. + +#### \`fetch-timeout\` + +* Default: 300000 (5 minutes) +* Type: Number + +The maximum amount of time to wait for HTTP requests to complete. + +#### \`force\` + +* Default: false +* Type: Boolean + +Removes various protections against unfortunate side effects, common +mistakes, unnecessary performance degradation, and malicious input. + +* Allow clobbering non-npm files in global installs. +* Allow the \`npm version\` command to work on an unclean git repository. +* Allow deleting the cache folder with \`npm cache clean\`. +* Allow installing packages that have an \`engines\` declaration requiring a + different version of npm. +* Allow installing packages that have an \`engines\` declaration requiring a + different version of \`node\`, even if \`--engine-strict\` is enabled. +* Allow \`npm audit fix\` to install modules outside your stated dependency + range (including SemVer-major changes). +* Allow unpublishing all versions of a published package. +* Allow conflicting peerDependencies to be installed in the root project. + +If you don't have a clear idea of what you want to do, it is strongly +recommended that you do not use this option! + +#### \`foreground-scripts\` + +* Default: false +* Type: Boolean + +Run all build scripts (ie, \`preinstall\`, \`install\`, and \`postinstall\`) +scripts for installed packages in the foreground process, sharing standard +input, output, and error with the main npm process. + +Note that this will generally make installs run slower, and be much noisier, +but can be useful for debugging. + +#### \`format-package-lock\` + +* Default: true +* Type: Boolean + +Format \`package-lock.json\` or \`npm-shrinkwrap.json\` as a human readable +file. + +#### \`fund\` + +* Default: true +* Type: Boolean + +When "true" displays the message at the end of each \`npm install\` +acknowledging the number of dependencies looking for funding. See [\`npm +fund\`](/commands/npm-fund) for details. + +#### \`git\` + +* Default: "git" +* Type: String + +The command to use for git commands. If git is installed on the computer, +but is not in the \`PATH\`, then set this to the full path to the git binary. + +#### \`git-tag-version\` + +* Default: true +* Type: Boolean + +Tag the commit when using the \`npm version\` command. + +#### \`global\` + +* Default: false +* Type: Boolean + +Operates in "global" mode, so that packages are installed into the \`prefix\` +folder instead of the current working directory. See +[folders](/configuring-npm/folders) for more on the differences in behavior. + +* packages are installed into the \`{prefix}/lib/node_modules\` folder, instead + of the current working directory. +* bin files are linked to \`{prefix}/bin\` +* man pages are linked to \`{prefix}/share/man\` + +#### \`global-style\` + +* Default: false +* Type: Boolean + +Causes npm to install the package into your local \`node_modules\` folder with +the same layout it uses with the global \`node_modules\` folder. Only your +direct dependencies will show in \`node_modules\` and everything they depend +on will be flattened in their \`node_modules\` folders. This obviously will +eliminate some deduping. If used with \`legacy-bundling\`, \`legacy-bundling\` +will be preferred. + +#### \`globalconfig\` + +* Default: The global --prefix setting plus 'etc/npmrc'. For example, + '/usr/local/etc/npmrc' +* Type: Path + +The config file to read for global config options. + +#### \`heading\` + +* Default: "npm" +* Type: String + +The string that starts all the debugging log output. + +#### \`https-proxy\` + +* Default: null +* Type: null or URL + +A proxy to use for outgoing https requests. If the \`HTTPS_PROXY\` or +\`https_proxy\` or \`HTTP_PROXY\` or \`http_proxy\` environment variables are set, +proxy settings will be honored by the underlying \`make-fetch-happen\` +library. + +#### \`if-present\` + +* Default: false +* Type: Boolean + +If true, npm will not exit with an error code when \`run-script\` is invoked +for a script that isn't defined in the \`scripts\` section of \`package.json\`. +This option can be used when it's desirable to optionally run a script when +it's present and fail if the script fails. This is useful, for example, when +running scripts that may only apply for some builds in an otherwise generic +CI setup. + +#### \`ignore-scripts\` + +* Default: false +* Type: Boolean + +If true, npm does not run scripts specified in package.json files. + +#### \`include\` + +* Default: +* Type: "prod", "dev", "optional", or "peer" (can be set multiple times) + +Option that allows for defining which types of dependencies to install. + +This is the inverse of \`--omit=<type>\`. + +Dependency types specified in \`--include\` will not be omitted, regardless of +the order in which omit/include are specified on the command-line. + +#### \`include-staged\` + +* Default: false +* Type: Boolean + +Allow installing "staged" published packages, as defined by [npm RFC PR +#92](https://github.com/npm/rfcs/pull/92). + +This is experimental, and not implemented by the npm public registry. + +#### \`init-author-email\` + +* Default: "" +* Type: String + +The value \`npm init\` should use by default for the package author's email. + +#### \`init-author-name\` + +* Default: "" +* Type: String + +The value \`npm init\` should use by default for the package author's name. + +#### \`init-author-url\` + +* Default: "" +* Type: "" or URL + +The value \`npm init\` should use by default for the package author's +homepage. + +#### \`init-license\` + +* Default: "ISC" +* Type: String + +The value \`npm init\` should use by default for the package license. + +#### \`init-module\` + +* Default: "~/.npm-init.js" +* Type: Path + +A module that will be loaded by the \`npm init\` command. See the +documentation for the +[init-package-json](https://github.com/npm/init-package-json) module for +more information, or [npm init](/commands/npm-init). + +#### \`init-version\` + +* Default: "1.0.0" +* Type: SemVer string + +The value that \`npm init\` should use by default for the package version +number, if not already set in package.json. + +#### \`json\` + +* Default: false +* Type: Boolean + +Whether or not to output JSON data, rather than the normal output. + +This feature is currently experimental, and the output data structures for +many commands is either not implemented in JSON yet, or subject to change. +Only the output from \`npm ls --json\` and \`npm search --json\` are currently +valid. + +#### \`key\` + +* Default: null +* Type: null or String + +A client key to pass when accessing the registry. Values should be in PEM +format with newlines replaced by the string "\\n". For example: + +\`\`\`ini +key="-----BEGIN PRIVATE KEY-----\\nXXXX\\nXXXX\\n-----END PRIVATE KEY-----" +\`\`\` + +It is _not_ the path to a key file (and there is no "keyfile" option). + +#### \`legacy-bundling\` + +* Default: false +* Type: Boolean + +Causes npm to install the package such that versions of npm prior to 1.4, +such as the one included with node 0.8, can install the package. This +eliminates all automatic deduping. If used with \`global-style\` this option +will be preferred. + +#### \`legacy-peer-deps\` + +* Default: false +* Type: Boolean + +Causes npm to completely ignore \`peerDependencies\` when building a package +tree, as in npm versions 3 through 6. + +If a package cannot be installed because of overly strict \`peerDependencies\` +that collide, it provides a way to move forward resolving the situation. + +This differs from \`--omit=peer\`, in that \`--omit=peer\` will avoid unpacking +\`peerDependencies\` on disk, but will still design a tree such that +\`peerDependencies\` _could_ be unpacked in a correct place. + +Use of \`legacy-peer-deps\` is not recommended, as it will not enforce the +\`peerDependencies\` contract that meta-dependencies may rely on. + +#### \`link\` + +* Default: false +* Type: Boolean + +If true, then local installs will link if there is a suitable globally +installed package. + +Note that this means that local installs can cause things to be installed +into the global space at the same time. The link is only done if one of the +two conditions are met: + +* The package is not already installed globally, or +* the globally installed version is identical to the version that is being + installed locally. + +#### \`local-address\` + +* Default: null +* Type: IP Address + +The IP address of the local interface to use when making connections to the +npm registry. Must be IPv4 in versions of Node prior to 0.12. + +#### \`loglevel\` + +* Default: "notice" +* Type: "silent", "error", "warn", "notice", "http", "timing", "info", + "verbose", or "silly" + +What level of logs to report. On failure, *all* logs are written to +\`npm-debug.log\` in the current working directory. + +Any logs of a higher level than the setting are shown. The default is +"notice". + +#### \`logs-max\` + +* Default: 10 +* Type: Number + +The maximum number of log files to store. + +#### \`long\` + +* Default: false +* Type: Boolean + +Show extended information in \`npm ls\` and \`npm search\`. + +#### \`maxsockets\` + +* Default: Infinity +* Type: Number + +The maximum number of connections to use per origin (protocol/host/port +combination). + +#### \`message\` + +* Default: "%s" +* Type: String + +Commit message which is used by \`npm version\` when creating version commit. + +Any "%s" in the message will be replaced with the version number. + +#### \`node-options\` + +* Default: null +* Type: null or String + +Options to pass through to Node.js via the \`NODE_OPTIONS\` environment +variable. This does not impact how npm itself is executed but it does impact +how lifecycle scripts are called. + +#### \`node-version\` + +* Default: Node.js \`process.version\` value +* Type: SemVer string + +The node version to use when checking a package's \`engines\` setting. + +#### \`noproxy\` + +* Default: The value of the NO_PROXY environment variable +* Type: String (can be set multiple times) + +Domain extensions that should bypass any proxies. + +Also accepts a comma-delimited string. + +#### \`npm-version\` + +* Default: Output of \`npm --version\` +* Type: SemVer string + +The npm version to use when checking a package's \`engines\` setting. + +#### \`offline\` + +* Default: false +* Type: Boolean + +Force offline mode: no network requests will be done during install. To +allow the CLI to fill in missing cache data, see \`--prefer-offline\`. + +#### \`omit\` + +* Default: 'dev' if the NODE_ENV environment variable is set to 'production', + otherwise empty. +* Type: "dev", "optional", or "peer" (can be set multiple times) + +Dependency types to omit from the installation tree on disk. + +Note that these dependencies _are_ still resolved and added to the +\`package-lock.json\` or \`npm-shrinkwrap.json\` file. They are just not +physically installed on disk. + +If a package type appears in both the \`--include\` and \`--omit\` lists, then +it will be included. + +If the resulting omit list includes \`'dev'\`, then the \`NODE_ENV\` environment +variable will be set to \`'production'\` for all lifecycle scripts. + +#### \`otp\` + +* Default: null +* Type: null or String + +This is a one-time password from a two-factor authenticator. It's needed +when publishing or changing package permissions with \`npm access\`. + +If not set, and a registry response fails with a challenge for a one-time +password, npm will prompt on the command line for one. + +#### \`package\` + +* Default: +* Type: String (can be set multiple times) + +The package to install for [\`npm exec\`](/commands/npm-exec) + +#### \`package-lock\` + +* Default: true +* Type: Boolean + +If set to false, then ignore \`package-lock.json\` files when installing. This +will also prevent _writing_ \`package-lock.json\` if \`save\` is true. + +When package package-locks are disabled, automatic pruning of extraneous +modules will also be disabled. To remove extraneous modules with +package-locks disabled use \`npm prune\`. + +#### \`package-lock-only\` + +* Default: false +* Type: Boolean + +If set to true, it will update only the \`package-lock.json\`, instead of +checking \`node_modules\` and downloading dependencies. + +#### \`parseable\` + +* Default: false +* Type: Boolean + +Output parseable results from commands that write to standard output. For +\`npm search\`, this will be tab-separated table format. + +#### \`prefer-offline\` + +* Default: false +* Type: Boolean + +If true, staleness checks for cached data will be bypassed, but missing data +will be requested from the server. To force full offline mode, use +\`--offline\`. + +#### \`prefer-online\` + +* Default: false +* Type: Boolean + +If true, staleness checks for cached data will be forced, making the CLI +look for updates immediately even for fresh package data. + +#### \`prefix\` + +* Default: In global mode, the folder where the node executable is installed. + In local mode, the nearest parent folder containing either a package.json + file or a node_modules folder. +* Type: Path + +The location to install global items. If set on the command line, then it +forces non-global commands to run in the specified folder. + +#### \`preid\` + +* Default: "" +* Type: String + +The "prerelease identifier" to use as a prefix for the "prerelease" part of +a semver. Like the \`rc\` in \`1.2.0-rc.8\`. + +#### \`progress\` + +* Default: \`true\` unless running in a known CI system +* Type: Boolean + +When set to \`true\`, npm will display a progress bar during time intensive +operations, if \`process.stderr\` is a TTY. + +Set to \`false\` to suppress the progress bar. + +#### \`proxy\` + +* Default: null +* Type: null, false, or URL + +A proxy to use for outgoing http requests. If the \`HTTP_PROXY\` or +\`http_proxy\` environment variables are set, proxy settings will be honored +by the underlying \`request\` library. + +#### \`read-only\` + +* Default: false +* Type: Boolean + +This is used to mark a token as unable to publish when configuring limited +access tokens with the \`npm token create\` command. + +#### \`rebuild-bundle\` + +* Default: true +* Type: Boolean + +Rebuild bundled dependencies after installation. + +#### \`registry\` + +* Default: "https://registry.npmjs.org/" +* Type: URL + +The base URL of the npm registry. + +#### \`save\` + +* Default: true +* Type: Boolean + +Save installed packages to a package.json file as dependencies. + +When used with the \`npm rm\` command, removes the dependency from +package.json. + +#### \`save-bundle\` + +* Default: false +* Type: Boolean + +If a package would be saved at install time by the use of \`--save\`, +\`--save-dev\`, or \`--save-optional\`, then also put it in the +\`bundleDependencies\` list. + +Ignore if \`--save-peer\` is set, since peerDependencies cannot be bundled. + +#### \`save-dev\` + +* Default: false +* Type: Boolean + +Save installed packages to a package.json file as \`devDependencies\`. + +#### \`save-exact\` + +* Default: false +* Type: Boolean + +Dependencies saved to package.json will be configured with an exact version +rather than using npm's default semver range operator. + +#### \`save-optional\` + +* Default: false +* Type: Boolean + +Save installed packages to a package.json file as \`optionalDependencies\`. + +#### \`save-peer\` + +* Default: false +* Type: Boolean + +Save installed packages. to a package.json file as \`peerDependencies\` + +#### \`save-prefix\` + +* Default: "^" +* Type: String + +Configure how versions of packages installed to a package.json file via +\`--save\` or \`--save-dev\` get prefixed. + +For example if a package has version \`1.2.3\`, by default its version is set +to \`^1.2.3\` which allows minor upgrades for that package, but after \`npm +config set save-prefix='~'\` it would be set to \`~1.2.3\` which only allows +patch upgrades. + +#### \`save-prod\` + +* Default: false +* Type: Boolean + +Save installed packages into \`dependencies\` specifically. This is useful if +a package already exists in \`devDependencies\` or \`optionalDependencies\`, but +you want to move it to be a non-optional production dependency. + +This is the default behavior if \`--save\` is true, and neither \`--save-dev\` +or \`--save-optional\` are true. + +#### \`scope\` + +* Default: the scope of the current project, if any, or "" +* Type: String + +Associate an operation with a scope for a scoped registry. + +Useful when logging in to a private registry for the first time: + +\`\`\`bash +npm login --scope=@mycorp --registry=https://registry.mycorp.com +\`\`\` + +This will cause \`@mycorp\` to be mapped to the registry for future +installation of packages specified according to the pattern +\`@mycorp/package\`. + +#### \`script-shell\` + +* Default: '/bin/sh' on POSIX systems, 'cmd.exe' on Windows +* Type: null or String + +The shell to use for scripts run with the \`npm run\` command. + +#### \`searchexclude\` + +* Default: "" +* Type: String + +Space-separated options that limit the results from search. + +#### \`searchlimit\` + +* Default: 20 +* Type: Number + +Number of items to limit search results to. Will not apply at all to legacy +searches. + +#### \`searchopts\` + +* Default: "" +* Type: String + +Space-separated options that are always passed to search. + +#### \`searchstaleness\` + +* Default: 900 +* Type: Number + +The age of the cache, in seconds, before another registry request is made if +using legacy search endpoint. + +#### \`shell\` + +* Default: SHELL environment variable, or "bash" on Posix, or "cmd.exe" on + Windows +* Type: String + +The shell to run for the \`npm explore\` command. + +#### \`sign-git-commit\` + +* Default: false +* Type: Boolean + +If set to true, then the \`npm version\` command will commit the new package +version using \`-S\` to add a signature. + +Note that git requires you to have set up GPG keys in your git configs for +this to work properly. + +#### \`sign-git-tag\` + +* Default: false +* Type: Boolean + +If set to true, then the \`npm version\` command will tag the version using +\`-s\` to add a signature. + +Note that git requires you to have set up GPG keys in your git configs for +this to work properly. + +#### \`strict-peer-deps\` + +* Default: false +* Type: Boolean + +If set to \`true\`, and \`--legacy-peer-deps\` is not set, then _any_ +conflicting \`peerDependencies\` will be treated as an install failure, even +if npm could reasonably guess the appropriate resolution based on non-peer +dependency relationships. + +By default, conflicting \`peerDependencies\` deep in the dependency graph will +be resolved using the nearest non-peer dependency specification, even if +doing so will result in some packages receiving a peer dependency outside +the range set in their package's \`peerDependencies\` object. + +When such and override is performed, a warning is printed, explaining the +conflict and the packages involved. If \`--strict-peer-deps\` is set, then +this warning is treated as a failure. + +#### \`strict-ssl\` + +* Default: true +* Type: Boolean + +Whether or not to do SSL key validation when making requests to the registry +via https. + +See also the \`ca\` config. + +#### \`tag\` + +* Default: "latest" +* Type: String + +If you ask npm to install a package and don't tell it a specific version, +then it will install the specified tag. + +Also the tag that is added to the package@version specified by the \`npm tag\` +command, if no explicit tag is given. + +#### \`tag-version-prefix\` + +* Default: "v" +* Type: String + +If set, alters the prefix used when tagging a new version when performing a +version increment using \`npm-version\`. To remove the prefix altogether, set +it to the empty string: \`""\`. + +Because other tools may rely on the convention that npm version tags look +like \`v1.0.0\`, _only use this property if it is absolutely necessary_. In +particular, use care when overriding this setting for public packages. + +#### \`timing\` + +* Default: false +* Type: Boolean + +If true, writes an \`npm-debug\` log to \`_logs\` and timing information to +\`_timing.json\`, both in your cache, even if the command completes +successfully. \`_timing.json\` is a newline delimited list of JSON objects. + +You can quickly view it with this [json](https://npm.im/json) command line: +\`npm exec -- json -g < ~/.npm/_timing.json\`. + +#### \`umask\` + +* Default: 0 +* Type: Octal numeric string in range 0000..0777 (0..511) + +The "umask" value to use when setting the file creation mode on files and +folders. + +Folders and executables are given a mode which is \`0o777\` masked against +this value. Other files are given a mode which is \`0o666\` masked against +this value. + +Note that the underlying system will _also_ apply its own umask value to +files and folders that are created, and npm does not circumvent this, but +rather adds the \`--umask\` config to it. + +Thus, the effective default umask value on most POSIX systems is 0o22, +meaning that folders and executables are created with a mode of 0o755 and +other files are created with a mode of 0o644. + +#### \`unicode\` + +* Default: false on windows, true on mac/unix systems with a unicode locale, + as defined by the LC_ALL, LC_CTYPE, or LANG environment variables. +* Type: Boolean + +When set to true, npm uses unicode characters in the tree output. When +false, it uses ascii characters instead of unicode glyphs. + +#### \`update-notifier\` + +* Default: true +* Type: Boolean + +Set to false to suppress the update notification when using an older version +of npm than the latest. + +#### \`usage\` + +* Default: false +* Type: Boolean + +Show short usage output about the command specified. + +#### \`user-agent\` + +* Default: "npm/{npm-version} node/{node-version} {platform} {arch} {ci}" +* Type: String + +Sets the User-Agent request header. The following fields are replaced with +their actual counterparts: + +* \`{npm-version}\` - The npm version in use +* \`{node-version}\` - The Node.js version in use +* \`{platform}\` - The value of \`process.platform\` +* \`{arch}\` - The value of \`process.arch\` +* \`{ci}\` - The value of the \`ci-name\` config, if set, prefixed with \`ci/\`, or + an empty string if \`ci-name\` is empty. + +#### \`userconfig\` + +* Default: "~/.npmrc" +* Type: Path + +The location of user-level configuration settings. + +This may be overridden by the \`npm_config_userconfig\` environment variable +or the \`--userconfig\` command line option, but may _not_ be overridden by +settings in the \`globalconfig\` file. + +#### \`version\` + +* Default: false +* Type: Boolean + +If true, output the npm version and exit successfully. + +Only relevant when specified explicitly on the command line. + +#### \`versions\` + +* Default: false +* Type: Boolean + +If true, output the npm version as well as node's \`process.versions\` map and +the version in the current working directory's \`package.json\` file if one +exists, and exit successfully. + +Only relevant when specified explicitly on the command line. + +#### \`viewer\` + +* Default: "man" on Posix, "browser" on Windows +* Type: String + +The program to use to view help content. + +Set to \`"browser"\` to view html help content in the default web browser. + +#### \`which\` + +* Default: null +* Type: null or Number + +If there are multiple funding sources, which 1-indexed source URL to open. + +#### \`workspace\` + +* Default: +* Type: String (can be set multiple times) + +Enable running a command in the context of the configured workspaces of the +current project while filtering by running only the workspaces defined by +this configuration option. + +Valid values for the \`workspace\` config are either: - Workspace names - Path +to a workspace directory - Path to a parent workspace directory (will result +to selecting all of the nested workspaces) + +#### \`workspaces\` + +* Default: false +* Type: Boolean + +Enable running a command in the context of **all** the configured +workspaces. + +#### \`yes\` + +* Default: null +* Type: null or Boolean + +Automatically answer "yes" to any prompts that npm might print on the +command line. + +#### \`also\` + +* Default: null +* Type: null, "dev", or "development" +* DEPRECATED: Please use --include=dev instead. + +When set to \`dev\` or \`development\`, this is an alias for \`--include=dev\`. + +#### \`auth-type\` + +* Default: "legacy" +* Type: "legacy", "sso", "saml", or "oauth" +* DEPRECATED: This method of SSO/SAML/OAuth is deprecated and will be removed + in a future version of npm in favor of web-based login. + +What authentication strategy to use with \`adduser\`/\`login\`. + +#### \`cache-max\` + +* Default: Infinity +* Type: Number +* DEPRECATED: This option has been deprecated in favor of \`--prefer-online\` + +\`--cache-max=0\` is an alias for \`--prefer-online\` + +#### \`cache-min\` + +* Default: 0 +* Type: Number +* DEPRECATED: This option has been deprecated in favor of \`--prefer-offline\`. + +\`--cache-min=9999 (or bigger)\` is an alias for \`--prefer-offline\`. + +#### \`init.author.email\` + +* Default: "" +* Type: String +* DEPRECATED: Use \`--init-author-email\` instead. + +Alias for \`--init-author-email\` + +#### \`init.author.name\` + +* Default: "" +* Type: String +* DEPRECATED: Use \`--init-author-name\` instead. + +Alias for \`--init-author-name\` + +#### \`init.author.url\` + +* Default: "" +* Type: "" or URL +* DEPRECATED: Use \`--init-author-url\` instead. + +Alias for \`--init-author-url\` + +#### \`init.license\` + +* Default: "ISC" +* Type: String +* DEPRECATED: Use \`--init-license\` instead. + +Alias for \`--init-license\` + +#### \`init.module\` + +* Default: "~/.npm-init.js" +* Type: Path +* DEPRECATED: Use \`--init-module\` instead. + +Alias for \`--init-module\` + +#### \`init.version\` + +* Default: "1.0.0" +* Type: SemVer string +* DEPRECATED: Use \`--init-version\` instead. + +Alias for \`--init-version\` + +#### \`only\` + +* Default: null +* Type: null, "prod", or "production" +* DEPRECATED: Use \`--omit=dev\` to omit dev dependencies from the install. + +When set to \`prod\` or \`production\`, this is an alias for \`--omit=dev\`. + +#### \`optional\` + +* Default: null +* Type: null or Boolean +* DEPRECATED: Use \`--omit=optional\` to exclude optional dependencies, or + \`--include=optional\` to include them. + +Default value does install optional deps unless otherwise omitted. + +Alias for --include=optional or --omit=optional + +#### \`production\` + +* Default: false +* Type: Boolean +* DEPRECATED: Use \`--omit=dev\` instead. + +Alias for \`--omit=dev\` + +#### \`shrinkwrap\` + +* Default: true +* Type: Boolean +* DEPRECATED: Use the --package-lock setting instead. + +Alias for --package-lock + +#### \`sso-poll-frequency\` + +* Default: 500 +* Type: Number +* DEPRECATED: The --auth-type method of SSO/SAML/OAuth will be removed in a + future version of npm in favor of web-based login. + +When used with SSO-enabled \`auth-type\`s, configures how regularly the +registry should be polled while the user is completing authentication. + +#### \`sso-type\` + +* Default: "oauth" +* Type: null, "oauth", or "saml" +* DEPRECATED: The --auth-type method of SSO/SAML/OAuth will be removed in a + future version of npm in favor of web-based login. + +If \`--auth-type=sso\`, the type of SSO type to use. + +#### \`tmp\` + +* Default: The value returned by the Node.js \`os.tmpdir()\` method + <https://nodejs.org/api/os.html#os_os_tmpdir> +* Type: Path +* DEPRECATED: This setting is no longer used. npm stores temporary files in a + special location in the cache, and they are managed by + [\`cacache\`](http://npm.im/cacache). + +Historically, the location where temporary files were stored. No longer +relevant. +` diff --git a/deps/npm/tap-snapshots/test-lib-utils-config-index.js-TAP.test.js b/deps/npm/tap-snapshots/test-lib-utils-config-index.js-TAP.test.js new file mode 100644 index 0000000000..1e5ca23245 --- /dev/null +++ b/deps/npm/tap-snapshots/test-lib-utils-config-index.js-TAP.test.js @@ -0,0 +1,133 @@ +/* IMPORTANT + * This snapshot file is auto-generated, but designed for humans. + * It should be checked into source control and tracked carefully. + * Re-generate by setting TAP_SNAPSHOT=1 and running tests. + * Make sure to inspect the output below. Do not ignore changes! + */ +'use strict' +exports[`test/lib/utils/config/index.js TAP > shorthands 1`] = ` +Object { + "?": Array [ + "--usage", + ], + "a": Array [ + "--all", + ], + "B": Array [ + "--save-bundle", + ], + "c": Array [ + "--call", + ], + "C": Array [ + "--prefix", + ], + "d": Array [ + "--loglevel", + "info", + ], + "D": Array [ + "--save-dev", + ], + "dd": Array [ + "--loglevel", + "verbose", + ], + "ddd": Array [ + "--loglevel", + "silly", + ], + "desc": Array [ + "--description", + ], + "E": Array [ + "--save-exact", + ], + "enjoy-by": Array [ + "--before", + ], + "f": Array [ + "--force", + ], + "g": Array [ + "--global", + ], + "h": Array [ + "--usage", + ], + "H": Array [ + "--usage", + ], + "help": Array [ + "--usage", + ], + "l": Array [ + "--long", + ], + "local": Array [ + "--no-global", + ], + "m": Array [ + "--message", + ], + "n": Array [ + "--no-yes", + ], + "no": Array [ + "--no-yes", + ], + "O": Array [ + "--save-optional", + ], + "p": Array [ + "--parseable", + ], + "P": Array [ + "--save-prod", + ], + "porcelain": Array [ + "--parseable", + ], + "q": Array [ + "--loglevel", + "warn", + ], + "quiet": Array [ + "--loglevel", + "warn", + ], + "readonly": Array [ + "--read-only", + ], + "reg": Array [ + "--registry", + ], + "s": Array [ + "--loglevel", + "silent", + ], + "S": Array [ + "--save", + ], + "silent": Array [ + "--loglevel", + "silent", + ], + "v": Array [ + "--version", + ], + "verbose": Array [ + "--loglevel", + "verbose", + ], + "w": Array [ + "--workspace", + ], + "ws": Array [ + "--workspaces", + ], + "y": Array [ + "--yes", + ], +} +` 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 deleted file mode 100644 index 39927e600e..0000000000 --- a/deps/npm/tap-snapshots/test-lib-utils-config.js-TAP.test.js +++ /dev/null @@ -1,1110 +0,0 @@ -/* IMPORTANT - * This snapshot file is auto-generated, but designed for humans. - * It should be checked into source control and tracked carefully. - * Re-generate by setting TAP_SNAPSHOT=1 and running tests. - * Make sure to inspect the output below. Do not ignore changes! - */ -'use strict' -exports[`test/lib/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, - "also": null, - "always-auth": false, - "audit": true, - "audit-level": null, - "auth-type": "legacy", - "before": null, - "bin-links": true, - "browser": null, - "ca": null, - "cache": "{CACHE DIR} npm-cache", - "cache-lock-retries": 10, - "cache-lock-stale": 60000, - "cache-lock-wait": 10000, - "cache-max": null, - "cache-min": 10, - "cafile": null, - "call": "", - "cert": null, - "ci-name": null, - "cidr": null, - "color": true, - "commit-hooks": true, - "depth": null, - "description": true, - "dev": false, - "diff": Array [], - "diff-dst-prefix": "", - "diff-ignore-all-space": false, - "diff-name-only": false, - "diff-no-prefix": false, - "diff-src-prefix": "", - "diff-text": false, - "diff-unified": null, - "dry-run": false, - "editor": "vim", - "engine-strict": false, - "fetch-retries": 2, - "fetch-retry-factor": 10, - "fetch-retry-maxtimeout": 60000, - "fetch-retry-mintimeout": 10000, - "fetch-timeout": 300000, - "force": false, - "foreground-script": false, - "format-package-lock": true, - "fund": true, - "git": "git", - "git-tag-version": true, - "global": false, - "global-style": false, - "heading": "npm", - "https-proxy": null, - "if-present": false, - "ignore-prepublish": false, - "ignore-scripts": false, - "include": Array [], - "include-staged": false, - "init-author-email": "", - "init-author-name": "", - "init-author-url": "", - "init-license": "ISC", - "init-module": "~/.npm-init.js", - "init-version": "1.0.0", - "init.author.email": "", - "init.author.name": "", - "init.author.url": "", - "init.license": "ISC", - "init.module": "~/.npm-init.js", - "init.version": "1.0.0", - "json": false, - "key": null, - "legacy-bundling": false, - "legacy-peer-deps": false, - "link": false, - "local-address": undefined, - "loglevel": "notice", - "logs-max": 10, - "long": false, - "maxsockets": 50, - "message": "%s", - "node-options": null, - "node-version": "v14.8.0", - "noproxy": null, - "npm-version": "7.0.0", - "offline": false, - "omit": Array [], - "only": null, - "optional": true, - "otp": null, - "package": Array [], - "package-lock": true, - "package-lock-only": false, - "parseable": false, - "prefer-offline": false, - "prefer-online": false, - "preid": "", - "production": false, - "progress": true, - "proxy": null, - "read-only": false, - "rebuild-bundle": true, - "registry": "https://registry.npmjs.org/", - "rollback": true, - "save": true, - "save-bundle": false, - "save-dev": false, - "save-exact": false, - "save-optional": false, - "save-prefix": "^", - "save-prod": false, - "scope": "", - "script-shell": null, - "scripts-prepend-node-path": "warn-only", - "searchexclude": null, - "searchlimit": 20, - "searchopts": "", - "searchstaleness": 900, - "shell": "cmd.exe", - "shrinkwrap": true, - "sign-git-commit": false, - "sign-git-tag": false, - "sso-poll-frequency": 500, - "sso-type": "oauth", - "strict-peer-deps": false, - "strict-ssl": true, - "tag": "latest", - "tag-version-prefix": "v", - "timing": false, - "tmp": "/tmp", - "umask": 0, - "unicode": true, - "update-notifier": true, - "usage": false, - "user-agent": "npm/{npm-version} node/{node-version} {platform} {arch} {ci}", - "userconfig": "~/.npmrc", - "version": false, - "versions": false, - "viewer": "browser", - }, - "shorthands": Object { - "?": Array [ - "--usage", - ], - "a": Array [ - "--all", - ], - "B": Array [ - "--save-bundle", - ], - "c": Array [ - "--call", - ], - "C": Array [ - "--prefix", - ], - "d": Array [ - "--loglevel", - "info", - ], - "D": Array [ - "--save-dev", - ], - "dd": Array [ - "--loglevel", - "verbose", - ], - "ddd": Array [ - "--loglevel", - "silly", - ], - "desc": Array [ - "--description", - ], - "E": Array [ - "--save-exact", - ], - "enjoy-by": Array [ - "--before", - ], - "f": Array [ - "--force", - ], - "g": Array [ - "--global", - ], - "h": Array [ - "--usage", - ], - "H": Array [ - "--usage", - ], - "help": Array [ - "--usage", - ], - "l": Array [ - "--long", - ], - "local": Array [ - "--no-global", - ], - "m": Array [ - "--message", - ], - "n": Array [ - "--no-yes", - ], - "no-desc": Array [ - "--no-description", - ], - "no-reg": Array [ - "--no-registry", - ], - "noreg": Array [ - "--no-registry", - ], - "O": Array [ - "--save-optional", - ], - "p": Array [ - "--parseable", - ], - "P": Array [ - "--save-prod", - ], - "porcelain": Array [ - "--parseable", - ], - "q": Array [ - "--loglevel", - "warn", - ], - "quiet": Array [ - "--loglevel", - "warn", - ], - "readonly": Array [ - "--read-only", - ], - "reg": Array [ - "--registry", - ], - "s": Array [ - "--loglevel", - "silent", - ], - "S": Array [ - "--save", - ], - "silent": Array [ - "--loglevel", - "silent", - ], - "v": Array [ - "--version", - ], - "verbose": Array [ - "--loglevel", - "verbose", - ], - "y": Array [ - "--yes", - ], - }, - "types": Object { - "_auth": Array [ - null, - "{String TYPE}", - ], - "access": Array [ - null, - "restricted", - "public", - ], - "all": "{Boolean TYPE}", - "allow-same-version": "{Boolean TYPE}", - "also": Array [ - null, - "dev", - "development", - ], - "always-auth": "{Boolean TYPE}", - "audit": "{Boolean TYPE}", - "audit-level": Array [ - "low", - "moderate", - "high", - "critical", - "none", - null, - ], - "auth-type": Array [ - "legacy", - "sso", - "saml", - "oauth", - ], - "before": Array [ - null, - "{Date TYPE}", - ], - "bin-links": "{Boolean TYPE}", - "browser": Array [ - null, - "{Boolean TYPE}", - "{String TYPE}", - ], - "ca": Array [ - null, - "{String TYPE}", - "{Array TYPE}", - ], - "cache": "{PATH MODULE}", - "cache-lock-retries": "{Number TYPE}", - "cache-lock-stale": "{Number TYPE}", - "cache-lock-wait": "{Number TYPE}", - "cache-max": "{Number TYPE}", - "cache-min": "{Number TYPE}", - "cafile": "{PATH MODULE}", - "call": "{String TYPE}", - "cert": Array [ - null, - "{String TYPE}", - ], - "ci-name": Array [ - null, - "{String TYPE}", - ], - "cidr": Array [ - null, - "{String TYPE}", - "{Array TYPE}", - ], - "color": Array [ - "always", - "{Boolean TYPE}", - ], - "commit-hooks": "{Boolean TYPE}", - "depth": Array [ - null, - "{Number TYPE}", - ], - "description": "{Boolean TYPE}", - "dev": "{Boolean TYPE}", - "diff": Array [ - "{String TYPE}", - "{Array TYPE}", - ], - "diff-dst-prefix": "{String TYPE}", - "diff-ignore-all-space": "{Boolean TYPE}", - "diff-name-only": "{Boolean TYPE}", - "diff-no-prefix": "{Boolean TYPE}", - "diff-src-prefix": "{String TYPE}", - "diff-text": "{Boolean TYPE}", - "diff-unified": Array [ - null, - "{Number TYPE}", - ], - "dry-run": "{Boolean TYPE}", - "editor": "{String TYPE}", - "engine-strict": "{Boolean TYPE}", - "fetch-retries": "{Number TYPE}", - "fetch-retry-factor": "{Number TYPE}", - "fetch-retry-maxtimeout": "{Number TYPE}", - "fetch-retry-mintimeout": "{Number TYPE}", - "fetch-timeout": "{Number TYPE}", - "force": "{Boolean TYPE}", - "foreground-script": "{Boolean TYPE}", - "format-package-lock": "{Boolean TYPE}", - "fund": "{Boolean TYPE}", - "git": "{String TYPE}", - "git-tag-version": "{Boolean TYPE}", - "global": "{Boolean TYPE}", - "global-style": "{Boolean TYPE}", - "globalconfig": "{PATH MODULE}", - "heading": "{String TYPE}", - "https-proxy": Array [ - null, - "{URL MODULE}", - ], - "if-present": "{Boolean TYPE}", - "ignore-prepublish": "{Boolean TYPE}", - "ignore-scripts": "{Boolean TYPE}", - "include": Array [ - "{Array TYPE}", - "prod", - "dev", - "optional", - "peer", - ], - "include-staged": "{Boolean TYPE}", - "init-author-email": "{String TYPE}", - "init-author-name": "{String TYPE}", - "init-author-url": Array [ - "", - "{URL MODULE}", - ], - "init-license": "{String TYPE}", - "init-module": "{PATH MODULE}", - "init-version": "{SEMVER MODULE}", - "init.author.email": "{String TYPE}", - "init.author.name": "{String TYPE}", - "init.author.url": Array [ - "", - "{URL MODULE}", - ], - "init.license": "{String TYPE}", - "init.module": "{PATH MODULE}", - "init.version": "{SEMVER MODULE}", - "json": "{Boolean TYPE}", - "key": Array [ - null, - "{String TYPE}", - ], - "legacy-bundling": "{Boolean TYPE}", - "legacy-peer-deps": "{Boolean TYPE}", - "link": "{Boolean TYPE}", - "local-address": Array [ - undefined, - ], - "loglevel": Array [ - "silent", - "error", - "warn", - "notice", - "http", - "timing", - "info", - "verbose", - "silly", - ], - "logs-max": "{Number TYPE}", - "long": "{Boolean TYPE}", - "maxsockets": "{Number TYPE}", - "message": "{String TYPE}", - "node-options": Array [ - null, - "{String TYPE}", - ], - "node-version": Array [ - null, - "{SEMVER MODULE}", - ], - "noproxy": Array [ - null, - "{String TYPE}", - "{Array TYPE}", - ], - "npm-version": "{SEMVER MODULE}", - "offline": "{Boolean TYPE}", - "omit": Array [ - "{Array TYPE}", - "dev", - "optional", - "peer", - ], - "only": Array [ - null, - "dev", - "development", - "prod", - "production", - ], - "optional": "{Boolean TYPE}", - "otp": Array [ - null, - "{String TYPE}", - ], - "package": Array [ - "{String TYPE}", - "{Array TYPE}", - ], - "package-lock": "{Boolean TYPE}", - "package-lock-only": "{Boolean TYPE}", - "parseable": "{Boolean TYPE}", - "prefer-offline": "{Boolean TYPE}", - "prefer-online": "{Boolean TYPE}", - "prefix": "{PATH MODULE}", - "preid": "{String TYPE}", - "production": "{Boolean TYPE}", - "progress": "{Boolean TYPE}", - "proxy": Array [ - null, - false, - "{URL MODULE}", - ], - "read-only": "{Boolean TYPE}", - "rebuild-bundle": "{Boolean TYPE}", - "registry": Array [ - null, - "{URL MODULE}", - ], - "rollback": "{Boolean TYPE}", - "save": "{Boolean TYPE}", - "save-bundle": "{Boolean TYPE}", - "save-dev": "{Boolean TYPE}", - "save-exact": "{Boolean TYPE}", - "save-optional": "{Boolean TYPE}", - "save-prefix": "{String TYPE}", - "save-prod": "{Boolean TYPE}", - "scope": "{String TYPE}", - "script-shell": Array [ - null, - "{String TYPE}", - ], - "scripts-prepend-node-path": Array [ - "{Boolean TYPE}", - "auto", - "warn-only", - ], - "searchexclude": Array [ - null, - "{String TYPE}", - ], - "searchlimit": "{Number TYPE}", - "searchopts": "{String TYPE}", - "searchstaleness": "{Number TYPE}", - "shell": "{String TYPE}", - "shrinkwrap": "{Boolean TYPE}", - "sign-git-commit": "{Boolean TYPE}", - "sign-git-tag": "{Boolean TYPE}", - "sso-poll-frequency": "{Number TYPE}", - "sso-type": Array [ - null, - "oauth", - "saml", - ], - "strict-peer-deps": "{Boolean TYPE}", - "strict-ssl": "{Boolean TYPE}", - "tag": "{String TYPE}", - "tag-version-prefix": "{String TYPE}", - "timing": "{Boolean TYPE}", - "tmp": "{PATH MODULE}", - "umask": "{Umask TYPE}", - "unicode": "{Boolean TYPE}", - "update-notifier": "{Boolean TYPE}", - "usage": "{Boolean TYPE}", - "user-agent": "{String TYPE}", - "userconfig": "{PATH MODULE}", - "version": "{Boolean TYPE}", - "versions": "{Boolean TYPE}", - "viewer": "{String TYPE}", - }, -} -` - -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, - "also": null, - "always-auth": false, - "audit": true, - "audit-level": null, - "auth-type": "legacy", - "before": null, - "bin-links": true, - "browser": null, - "ca": null, - "cache": "{CACHE DIR} .npm", - "cache-lock-retries": 10, - "cache-lock-stale": 60000, - "cache-lock-wait": 10000, - "cache-max": null, - "cache-min": 10, - "cafile": null, - "call": "", - "cert": null, - "ci-name": null, - "cidr": null, - "color": true, - "commit-hooks": true, - "depth": null, - "description": true, - "dev": false, - "diff": Array [], - "diff-dst-prefix": "", - "diff-ignore-all-space": false, - "diff-name-only": false, - "diff-no-prefix": false, - "diff-src-prefix": "", - "diff-text": false, - "diff-unified": null, - "dry-run": false, - "editor": "vim", - "engine-strict": false, - "fetch-retries": 2, - "fetch-retry-factor": 10, - "fetch-retry-maxtimeout": 60000, - "fetch-retry-mintimeout": 10000, - "fetch-timeout": 300000, - "force": false, - "foreground-script": false, - "format-package-lock": true, - "fund": true, - "git": "git", - "git-tag-version": true, - "global": false, - "global-style": false, - "heading": "npm", - "https-proxy": null, - "if-present": false, - "ignore-prepublish": false, - "ignore-scripts": false, - "include": Array [], - "include-staged": false, - "init-author-email": "", - "init-author-name": "", - "init-author-url": "", - "init-license": "ISC", - "init-module": "~/.npm-init.js", - "init-version": "1.0.0", - "init.author.email": "", - "init.author.name": "", - "init.author.url": "", - "init.license": "ISC", - "init.module": "~/.npm-init.js", - "init.version": "1.0.0", - "json": false, - "key": null, - "legacy-bundling": false, - "legacy-peer-deps": false, - "link": false, - "local-address": undefined, - "loglevel": "notice", - "logs-max": 10, - "long": false, - "maxsockets": 50, - "message": "%s", - "node-options": null, - "node-version": "v14.8.0", - "noproxy": null, - "npm-version": "7.0.0", - "offline": false, - "omit": Array [], - "only": null, - "optional": true, - "otp": null, - "package": Array [], - "package-lock": true, - "package-lock-only": false, - "parseable": false, - "prefer-offline": false, - "prefer-online": false, - "preid": "", - "production": false, - "progress": true, - "proxy": null, - "read-only": false, - "rebuild-bundle": true, - "registry": "https://registry.npmjs.org/", - "rollback": true, - "save": true, - "save-bundle": false, - "save-dev": false, - "save-exact": false, - "save-optional": false, - "save-prefix": "^", - "save-prod": false, - "scope": "", - "script-shell": null, - "scripts-prepend-node-path": "warn-only", - "searchexclude": null, - "searchlimit": 20, - "searchopts": "", - "searchstaleness": 900, - "shell": "/usr/local/bin/bash", - "shrinkwrap": true, - "sign-git-commit": false, - "sign-git-tag": false, - "sso-poll-frequency": 500, - "sso-type": "oauth", - "strict-peer-deps": false, - "strict-ssl": true, - "tag": "latest", - "tag-version-prefix": "v", - "timing": false, - "tmp": "/tmp", - "umask": 0, - "unicode": true, - "update-notifier": true, - "usage": false, - "user-agent": "npm/{npm-version} node/{node-version} {platform} {arch} {ci}", - "userconfig": "~/.npmrc", - "version": false, - "versions": false, - "viewer": "man", - }, - "shorthands": Object { - "?": Array [ - "--usage", - ], - "a": Array [ - "--all", - ], - "B": Array [ - "--save-bundle", - ], - "c": Array [ - "--call", - ], - "C": Array [ - "--prefix", - ], - "d": Array [ - "--loglevel", - "info", - ], - "D": Array [ - "--save-dev", - ], - "dd": Array [ - "--loglevel", - "verbose", - ], - "ddd": Array [ - "--loglevel", - "silly", - ], - "desc": Array [ - "--description", - ], - "E": Array [ - "--save-exact", - ], - "enjoy-by": Array [ - "--before", - ], - "f": Array [ - "--force", - ], - "g": Array [ - "--global", - ], - "h": Array [ - "--usage", - ], - "H": Array [ - "--usage", - ], - "help": Array [ - "--usage", - ], - "l": Array [ - "--long", - ], - "local": Array [ - "--no-global", - ], - "m": Array [ - "--message", - ], - "n": Array [ - "--no-yes", - ], - "no-desc": Array [ - "--no-description", - ], - "no-reg": Array [ - "--no-registry", - ], - "noreg": Array [ - "--no-registry", - ], - "O": Array [ - "--save-optional", - ], - "p": Array [ - "--parseable", - ], - "P": Array [ - "--save-prod", - ], - "porcelain": Array [ - "--parseable", - ], - "q": Array [ - "--loglevel", - "warn", - ], - "quiet": Array [ - "--loglevel", - "warn", - ], - "readonly": Array [ - "--read-only", - ], - "reg": Array [ - "--registry", - ], - "s": Array [ - "--loglevel", - "silent", - ], - "S": Array [ - "--save", - ], - "silent": Array [ - "--loglevel", - "silent", - ], - "v": Array [ - "--version", - ], - "verbose": Array [ - "--loglevel", - "verbose", - ], - "y": Array [ - "--yes", - ], - }, - "types": Object { - "_auth": Array [ - null, - "{String TYPE}", - ], - "access": Array [ - null, - "restricted", - "public", - ], - "all": "{Boolean TYPE}", - "allow-same-version": "{Boolean TYPE}", - "also": Array [ - null, - "dev", - "development", - ], - "always-auth": "{Boolean TYPE}", - "audit": "{Boolean TYPE}", - "audit-level": Array [ - "low", - "moderate", - "high", - "critical", - "none", - null, - ], - "auth-type": Array [ - "legacy", - "sso", - "saml", - "oauth", - ], - "before": Array [ - null, - "{Date TYPE}", - ], - "bin-links": "{Boolean TYPE}", - "browser": Array [ - null, - "{Boolean TYPE}", - "{String TYPE}", - ], - "ca": Array [ - null, - "{String TYPE}", - "{Array TYPE}", - ], - "cache": "{PATH MODULE}", - "cache-lock-retries": "{Number TYPE}", - "cache-lock-stale": "{Number TYPE}", - "cache-lock-wait": "{Number TYPE}", - "cache-max": "{Number TYPE}", - "cache-min": "{Number TYPE}", - "cafile": "{PATH MODULE}", - "call": "{String TYPE}", - "cert": Array [ - null, - "{String TYPE}", - ], - "ci-name": Array [ - null, - "{String TYPE}", - ], - "cidr": Array [ - null, - "{String TYPE}", - "{Array TYPE}", - ], - "color": Array [ - "always", - "{Boolean TYPE}", - ], - "commit-hooks": "{Boolean TYPE}", - "depth": Array [ - null, - "{Number TYPE}", - ], - "description": "{Boolean TYPE}", - "dev": "{Boolean TYPE}", - "diff": Array [ - "{String TYPE}", - "{Array TYPE}", - ], - "diff-dst-prefix": "{String TYPE}", - "diff-ignore-all-space": "{Boolean TYPE}", - "diff-name-only": "{Boolean TYPE}", - "diff-no-prefix": "{Boolean TYPE}", - "diff-src-prefix": "{String TYPE}", - "diff-text": "{Boolean TYPE}", - "diff-unified": Array [ - null, - "{Number TYPE}", - ], - "dry-run": "{Boolean TYPE}", - "editor": "{String TYPE}", - "engine-strict": "{Boolean TYPE}", - "fetch-retries": "{Number TYPE}", - "fetch-retry-factor": "{Number TYPE}", - "fetch-retry-maxtimeout": "{Number TYPE}", - "fetch-retry-mintimeout": "{Number TYPE}", - "fetch-timeout": "{Number TYPE}", - "force": "{Boolean TYPE}", - "foreground-script": "{Boolean TYPE}", - "format-package-lock": "{Boolean TYPE}", - "fund": "{Boolean TYPE}", - "git": "{String TYPE}", - "git-tag-version": "{Boolean TYPE}", - "global": "{Boolean TYPE}", - "global-style": "{Boolean TYPE}", - "globalconfig": "{PATH MODULE}", - "heading": "{String TYPE}", - "https-proxy": Array [ - null, - "{URL MODULE}", - ], - "if-present": "{Boolean TYPE}", - "ignore-prepublish": "{Boolean TYPE}", - "ignore-scripts": "{Boolean TYPE}", - "include": Array [ - "{Array TYPE}", - "prod", - "dev", - "optional", - "peer", - ], - "include-staged": "{Boolean TYPE}", - "init-author-email": "{String TYPE}", - "init-author-name": "{String TYPE}", - "init-author-url": Array [ - "", - "{URL MODULE}", - ], - "init-license": "{String TYPE}", - "init-module": "{PATH MODULE}", - "init-version": "{SEMVER MODULE}", - "init.author.email": "{String TYPE}", - "init.author.name": "{String TYPE}", - "init.author.url": Array [ - "", - "{URL MODULE}", - ], - "init.license": "{String TYPE}", - "init.module": "{PATH MODULE}", - "init.version": "{SEMVER MODULE}", - "json": "{Boolean TYPE}", - "key": Array [ - null, - "{String TYPE}", - ], - "legacy-bundling": "{Boolean TYPE}", - "legacy-peer-deps": "{Boolean TYPE}", - "link": "{Boolean TYPE}", - "local-address": Array [ - undefined, - "127.0.0.1", - "no place like home", - ], - "loglevel": Array [ - "silent", - "error", - "warn", - "notice", - "http", - "timing", - "info", - "verbose", - "silly", - ], - "logs-max": "{Number TYPE}", - "long": "{Boolean TYPE}", - "maxsockets": "{Number TYPE}", - "message": "{String TYPE}", - "node-options": Array [ - null, - "{String TYPE}", - ], - "node-version": Array [ - null, - "{SEMVER MODULE}", - ], - "noproxy": Array [ - null, - "{String TYPE}", - "{Array TYPE}", - ], - "npm-version": "{SEMVER MODULE}", - "offline": "{Boolean TYPE}", - "omit": Array [ - "{Array TYPE}", - "dev", - "optional", - "peer", - ], - "only": Array [ - null, - "dev", - "development", - "prod", - "production", - ], - "optional": "{Boolean TYPE}", - "otp": Array [ - null, - "{String TYPE}", - ], - "package": Array [ - "{String TYPE}", - "{Array TYPE}", - ], - "package-lock": "{Boolean TYPE}", - "package-lock-only": "{Boolean TYPE}", - "parseable": "{Boolean TYPE}", - "prefer-offline": "{Boolean TYPE}", - "prefer-online": "{Boolean TYPE}", - "prefix": "{PATH MODULE}", - "preid": "{String TYPE}", - "production": "{Boolean TYPE}", - "progress": "{Boolean TYPE}", - "proxy": Array [ - null, - false, - "{URL MODULE}", - ], - "read-only": "{Boolean TYPE}", - "rebuild-bundle": "{Boolean TYPE}", - "registry": Array [ - null, - "{URL MODULE}", - ], - "rollback": "{Boolean TYPE}", - "save": "{Boolean TYPE}", - "save-bundle": "{Boolean TYPE}", - "save-dev": "{Boolean TYPE}", - "save-exact": "{Boolean TYPE}", - "save-optional": "{Boolean TYPE}", - "save-prefix": "{String TYPE}", - "save-prod": "{Boolean TYPE}", - "scope": "{String TYPE}", - "script-shell": Array [ - null, - "{String TYPE}", - ], - "scripts-prepend-node-path": Array [ - "{Boolean TYPE}", - "auto", - "warn-only", - ], - "searchexclude": Array [ - null, - "{String TYPE}", - ], - "searchlimit": "{Number TYPE}", - "searchopts": "{String TYPE}", - "searchstaleness": "{Number TYPE}", - "shell": "{String TYPE}", - "shrinkwrap": "{Boolean TYPE}", - "sign-git-commit": "{Boolean TYPE}", - "sign-git-tag": "{Boolean TYPE}", - "sso-poll-frequency": "{Number TYPE}", - "sso-type": Array [ - null, - "oauth", - "saml", - ], - "strict-peer-deps": "{Boolean TYPE}", - "strict-ssl": "{Boolean TYPE}", - "tag": "{String TYPE}", - "tag-version-prefix": "{String TYPE}", - "timing": "{Boolean TYPE}", - "tmp": "{PATH MODULE}", - "umask": "{Umask TYPE}", - "unicode": "{Boolean TYPE}", - "update-notifier": "{Boolean TYPE}", - "usage": "{Boolean TYPE}", - "user-agent": "{String TYPE}", - "userconfig": "{PATH MODULE}", - "version": "{Boolean TYPE}", - "versions": "{Boolean TYPE}", - "viewer": "{String TYPE}", - }, -} -` 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 deleted file mode 100644 index 47de89e976..0000000000 --- a/deps/npm/tap-snapshots/test-lib-utils-flat-options.js-TAP.test.js +++ /dev/null @@ -1,129 +0,0 @@ -/* IMPORTANT - * This snapshot file is auto-generated, but designed for humans. - * It should be checked into source control and tracked carefully. - * Re-generate by setting TAP_SNAPSHOT=1 and running tests. - * Make sure to inspect the output below. Do not ignore changes! - */ -'use strict' -exports[`test/lib/utils/flat-options.js TAP basic > flat options 1`] = ` -Object { - "_auth": undefined, - "@scope:registry": "@scope:registry", - "//nerf.dart:_authToken": "//nerf.dart:_authToken", - "access": "access", - "all": undefined, - "allowSameVersion": "allow-same-version", - "alwaysAuth": "always-auth", - "audit": "audit", - "auditLevel": "audit-level", - "authType": "auth-type", - "before": "before", - "binLinks": "bin-links", - "browser": "browser", - "ca": "ca", - "cache": "cache/_cacache", - "cafile": "cafile", - "call": "call", - "cert": "cert", - "cidr": "cidr", - "color": true, - "commitHooks": "commit-hooks", - "defaultTag": "tag", - "depth": "depth", - "diff": undefined, - "diffDstPrefix": undefined, - "diffIgnoreAllSpace": undefined, - "diffNameOnly": undefined, - "diffNoPrefix": undefined, - "diffSrcPrefix": undefined, - "diffText": undefined, - "diffUnified": undefined, - "dmode": 511, - "dryRun": "dry-run", - "editor": "editor", - "engineStrict": "engine-strict", - "fmode": 438, - "force": "force", - "foregroundScripts": false, - "formatPackageLock": "format-package-lock", - "fund": "fund", - "git": "git", - "gitTagVersion": "git-tag-version", - "global": "global", - "globalPrefix": "/usr/local", - "globalStyle": "global-style", - "hashAlgorithm": "sha1", - "ignoreScripts": undefined, - "includeStaged": undefined, - "json": undefined, - "key": "key", - "legacyBundling": "legacy-bundling", - "legacyPeerDeps": undefined, - "localPrefix": "/path/to/npm/cli", - "log": Object {}, - "long": undefined, - "message": "message", - "nodeBin": "/path/to/some/node", - "nodeVersion": "1.2.3", - "noProxy": "noproxy", - "npmBin": "/path/to/npm/bin.js", - "npmCommand": null, - "npmSession": "12345", - "npmVersion": "7.6.5", - "offline": "offline", - "omit": Array [], - "otp": "otp", - "package": "package", - "packageLock": true, - "packageLockOnly": "package-lock-only", - "parseable": undefined, - "preferDedupe": undefined, - "preferOffline": "prefer-offline", - "preferOnline": "prefer-online", - "prefix": "/path/to/npm/cli", - "preid": "preid", - "projectScope": "@npmcli", - "proxy": "proxy", - "readOnly": "read-only", - "rebuildBundle": "rebuild-bundle", - "registry": "registry", - "retry": Object { - "factor": "fetch-retry-factor", - "maxTimeout": "fetch-retry-maxtimeout", - "minTimeout": "fetch-retry-mintimeout", - "retries": "fetch-retries", - }, - "save": "save", - "saveBundle": false, - "savePrefix": "", - "saveType": "peerOptional", - "scope": "", - "scriptShell": "script-shell", - "search": Object { - "description": "description", - "exclude": "searchexclude", - "limit": "searchlimit", - "opts": Null Object { - "from": "1", - }, - "staleness": "searchstaleness", - }, - "shell": undefined, - "signGitCommit": "sign-git-commit", - "signGitTag": "sign-git-tag", - "ssoPollFrequency": undefined, - "ssoType": undefined, - "strictPeerDeps": undefined, - "strictSSL": "strict-ssl", - "tag": "tag", - "tagVersionPrefix": "tag-version-prefix", - "timeout": "fetch-timeout", - "tmp": "/tmp", - "umask": 18, - "unicode": undefined, - "userAgent": "user-agent", - "viewer": "viewer", - "which": undefined, - "yes": undefined, -} -` diff --git a/deps/npm/tap-snapshots/test-lib-utils-npm-usage.js-TAP.test.js b/deps/npm/tap-snapshots/test-lib-utils-npm-usage.js-TAP.test.js index 318f3ac173..cf085f1ad5 100644 --- a/deps/npm/tap-snapshots/test-lib-utils-npm-usage.js-TAP.test.js +++ b/deps/npm/tap-snapshots/test-lib-utils-npm-usage.js-TAP.test.js @@ -6,8 +6,9 @@ */ 'use strict' exports[`test/lib/utils/npm-usage.js TAP usage basic usage > must match snapshot 1`] = ` +npm <command> -Usage: npm <command> +Usage: npm install install all the dependencies in your project npm install <foo> add the <foo> dependency to your project @@ -38,55 +39,12 @@ More configuration info: npm help config Configuration fields: npm help 7 config npm@{VERSION} {BASEDIR} - -` - -exports[`test/lib/utils/npm-usage.js TAP usage did you mean? > must match snapshot 1`] = ` - -Usage: npm <command> - -npm install install all the dependencies in your project -npm install <foo> add the <foo> dependency to your project -npm test run this project's tests -npm run <foo> run the script named <foo> -npm <command> -h quick help on <command> -npm -l display usage info for all commands -npm help <term> search for help on <term> -npm help npm more involved overview - -All commands: - - access, adduser, audit, bin, bugs, cache, ci, completion, - config, dedupe, deprecate, diff, dist-tag, docs, doctor, - edit, exec, explain, explore, find-dupes, fund, get, help, - hook, init, install, install-ci-test, install-test, link, - ll, login, logout, ls, org, outdated, owner, pack, ping, - prefix, profile, prune, publish, rebuild, repo, restart, - root, run-script, search, set, set-script, shrinkwrap, star, - stars, start, stop, team, test, token, uninstall, unpublish, - unstar, update, version, view, whoami - -Specify configs in the ini-formatted file: - /some/config/file/.npmrc -or on the command line via: npm <command> --key=value - -More configuration info: npm help config -Configuration fields: npm help 7 config - -npm@{VERSION} {BASEDIR} - -` - -exports[`test/lib/utils/npm-usage.js TAP usage did you mean? > must match snapshot 2`] = ` - -Did you mean one of these? - install - uninstall ` exports[`test/lib/utils/npm-usage.js TAP usage set process.stdout.columns columns=0 > must match snapshot 1`] = ` +npm <command> -Usage: npm <command> +Usage: npm install install all the dependencies in your project npm install <foo> add the <foo> dependency to your project @@ -117,12 +75,12 @@ More configuration info: npm help config Configuration fields: npm help 7 config npm@{VERSION} {BASEDIR} - ` exports[`test/lib/utils/npm-usage.js TAP usage set process.stdout.columns columns=90 > must match snapshot 1`] = ` +npm <command> -Usage: npm <command> +Usage: npm install install all the dependencies in your project npm install <foo> add the <foo> dependency to your project @@ -153,12 +111,12 @@ More configuration info: npm help config Configuration fields: npm help 7 config npm@{VERSION} {BASEDIR} - ` exports[`test/lib/utils/npm-usage.js TAP usage with browser > must match snapshot 1`] = ` +npm <command> -Usage: npm <command> +Usage: npm install install all the dependencies in your project npm install <foo> add the <foo> dependency to your project @@ -189,12 +147,12 @@ More configuration info: npm help config Configuration fields: npm help 7 config npm@{VERSION} {BASEDIR} - ` exports[`test/lib/utils/npm-usage.js TAP usage with long > must match snapshot 1`] = ` +npm <command> -Usage: npm <command> +Usage: npm install install all the dependencies in your project npm install <foo> add the <foo> dependency to your project @@ -209,6 +167,8 @@ All commands: access npm access + Set access level on published packages + Usage: npm access public [<package>] npm access restricted [<package>] @@ -224,8 +184,13 @@ All commands: adduser npm adduser + Add a registry user account + Usage: - npm adduser [--registry=url] [--scope=@orgname] [--always-auth] + npm adduser + + Options: + [--registry <registry>] [--scope <@scope>] [--always-auth] aliases: login, add-user @@ -233,21 +198,32 @@ All commands: audit npm audit + Run a security audit + Usage: - npm audit [--json] [--production] - npm audit fix [--force|--package-lock-only|--dry-run|--production|--only=(dev|prod)] + npm audit [fix] + + Options: + [--dry-run] [-f|--force] [--json] [--package-lock-only] [--production] Run "npm help audit" for more info bin npm bin + Display npm bin folder + Usage: - npm bin [-g] + npm bin + + Options: + [-g|--global] Run "npm help bin" for more info bugs npm bugs + Report bugs for a package in a web browser + Usage: npm bugs [<pkgname>] @@ -257,6 +233,8 @@ All commands: cache npm cache + Manipulates packages cache + Usage: npm cache add <tarball file> npm cache add <folder> @@ -270,6 +248,8 @@ All commands: ci npm ci + Install a project with a clean slate + Usage: npm ci @@ -279,7 +259,7 @@ All commands: completion npm completion - npm command completion script. save to ~/.bashrc or ~/.zshrc + Tab Completion for npm Usage: npm completion @@ -288,6 +268,8 @@ All commands: config npm config + Manage the npm configuration files + Usage: npm config set <key>=<value> [<key>=<value> ...] npm config get [<key> [<key> ...]] @@ -301,6 +283,8 @@ All commands: dedupe npm dedupe + Reduce duplication in the package tree + Usage: npm dedupe @@ -310,6 +294,8 @@ All commands: deprecate npm deprecate + Deprecate a version of a package + Usage: npm deprecate <pkg>[@<version>] <message> @@ -317,6 +303,8 @@ All commands: diff npm diff + The registry diff command + Usage: npm diff [...<paths>] npm diff --diff=<pkg-name> [...<paths>] @@ -328,6 +316,8 @@ All commands: dist-tag npm dist-tag + Modify package distribution tags + Usage: npm dist-tag add <pkg>@<version> [<tag>] npm dist-tag rm <pkg> <tag> @@ -337,12 +327,21 @@ All commands: Run "npm help dist-tag" for more info - docs npm docs [<pkgname> [<pkgname> ...]] + docs npm docs + + Open documentation for a package in a web browser + + Usage: + npm docs [<pkgname> [<pkgname> ...]] alias: home + Run "npm help docs" for more info + doctor npm doctor + Check your npm environment + Usage: npm doctor @@ -350,6 +349,8 @@ All commands: edit npm edit + Edit an installed package + Usage: npm edit <pkg>[/<subpkg>...] @@ -357,7 +358,7 @@ All commands: exec npm exec - Run a command from a local or remote npm package. + Run a command from a local or remote npm package Usage: npm exec -- <pkg>[@<version>] [args...] @@ -371,6 +372,8 @@ All commands: explain npm explain + Explain installed packages + Usage: npm explain <folder | specifier> @@ -380,6 +383,8 @@ All commands: explore npm explore + Browse an installed package + Usage: npm explore <pkg> [ -- <command>] @@ -387,6 +392,8 @@ All commands: find-dupes npm find-dupes + Find duplication in the package tree + Usage: npm find-dupes @@ -394,13 +401,20 @@ All commands: fund npm fund + Retrieve funding information + Usage: - npm fund [--json] [--browser] [--unicode] [[<@scope>/]<pkg> [--which=<fundingSourceNumber>] + npm fund [[<@scope>/]<pkg>] + + Options: + [--json] [--browser|--browser <browser>] [--unicode] [--which <fundingSourceNumber>] Run "npm help fund" for more info get npm get + Get a value from the npm configuration + Usage: npm get [<key> ...] (See \`npm config\`) @@ -408,6 +422,8 @@ All commands: help npm help + Get help on npm + Usage: npm help <term> [<terms..>] @@ -417,6 +433,8 @@ All commands: hook npm hook + Manage registry hooks + Usage: npm hook add <pkg> <url> <secret> [--type=<type>] npm hook ls [pkg] @@ -427,6 +445,8 @@ All commands: init npm init + Create a package.json file + Usage: npm init [--force|-f|--yes|-y|--scope] npm init <@scope> (same as \`npx <@scope>/create\`) @@ -438,6 +458,8 @@ All commands: install npm install + Install a package + Usage: npm install [<@scope>/]<pkg> npm install [<@scope>/]<pkg>@<tag> @@ -448,7 +470,10 @@ All commands: npm install <tarball file> npm install <tarball url> npm install <git:// url> - npm install <github username>/<github project> [--save-prod|--save-dev|--save-optional|--save-peer] [--save-exact] [--no-save] + npm install <github username>/<github project> + + Options: + [-S|--save|--no-save|--save-prod|--save-dev|--save-optional|--save-peer] [-E|--save-exact] aliases: i, in, ins, inst, insta, instal, isnt, isnta, isntal, add @@ -456,6 +481,8 @@ All commands: install-ci-test npm install-ci-test + Install a project with a clean slate and run tests + Usage: npm install-ci-test @@ -465,6 +492,8 @@ All commands: install-test npm install-test + Install package(s) and run tests + Usage: npm install-test [<@scope>/]<pkg> npm install-test [<@scope>/]<pkg>@<tag> @@ -475,7 +504,10 @@ All commands: npm install-test <tarball file> npm install-test <tarball url> npm install-test <git:// url> - npm install-test <github username>/<github project> [--save-prod|--save-dev|--save-optional|--save-peer] [--save-exact] [--no-save] + npm install-test <github username>/<github project> + + Options: + [-S|--save|--no-save|--save-prod|--save-dev|--save-optional|--save-peer] [-E|--save-exact] alias: it @@ -483,6 +515,8 @@ All commands: link npm link + Symlink a package folder + Usage: npm link (in package dir) npm link [<@scope>/]<pkg>[@<version>] @@ -493,6 +527,8 @@ All commands: ll npm ll + List installed packages + Usage: npm ll [[<@scope>/]<pkg> ...] @@ -502,8 +538,13 @@ All commands: login npm adduser + Add a registry user account + Usage: - npm adduser [--registry=url] [--scope=@orgname] [--always-auth] + npm adduser + + Options: + [--registry <registry>] [--scope <@scope>] [--always-auth] aliases: login, add-user @@ -511,13 +552,20 @@ All commands: logout npm logout + Log out of the registry + Usage: - npm logout [--registry=<url>] [--scope=<@scope>] + npm logout + + Options: + [--registry <registry>] [--scope <@scope>] Run "npm help logout" for more info ls npm ls + List installed packages + Usage: npm ls npm ls [[<@scope>/]<pkg> ...] @@ -527,6 +575,8 @@ All commands: org npm org + Manage orgs + Usage: npm org set orgname username [developer | admin | owner] npm org rm orgname username @@ -538,6 +588,8 @@ All commands: outdated npm outdated + Check for outdated packages + Usage: npm outdated [[<@scope>/]<pkg> ...] @@ -545,6 +597,8 @@ All commands: owner npm owner + Manage package owners + Usage: npm owner add <user> [<@scope>/]<pkg> npm owner rm <user> [<@scope>/]<pkg> @@ -556,22 +610,32 @@ All commands: pack npm pack + Create a tarball from a package + Usage: - npm pack [[<@scope>/]<pkg>...] [--dry-run] + npm pack [[<@scope>/]<pkg>...] + + Options: + [--dry-run] Run "npm help pack" for more info ping npm ping - ping registry + Ping npm registry Usage: npm ping + Options: + [--registry <registry>] + Run "npm help ping" for more info prefix npm prefix + Display prefix + Usage: npm prefix [-g] @@ -579,6 +643,8 @@ All commands: profile npm profile + Change settings on your registry profile + Usage: npm profile enable-2fa [auth-only|auth-and-writes] npm profile disable-2fa @@ -589,20 +655,32 @@ All commands: prune npm prune + Remove extraneous packages + Usage: - npm prune [[<@scope>/]<pkg>...] [--production] + npm prune [[<@scope>/]<pkg>...] + + Options: + [--production] Run "npm help prune" for more info publish npm publish + Publish a package + Usage: - npm publish [<folder>] [--tag <tag>] [--access <public|restricted>] [--dry-run] + npm publish [<folder>] + + Options: + [--tag <tag>] [--access <restricted|public>] [--dry-run] Run "npm help publish" for more info rebuild npm rebuild + Rebuild a package + Usage: npm rebuild [[<@scope>/]<name>[@<version>] ...] @@ -612,6 +690,8 @@ All commands: repo npm repo + Open package repository page in the browser + Usage: npm repo [<pkgname> [<pkgname> ...]] @@ -619,6 +699,8 @@ All commands: restart npm restart + Restart a package + Usage: npm restart [-- <args>] @@ -626,13 +708,20 @@ All commands: root npm root + Display npm root + Usage: - npm root [-g] + npm root + + Options: + [-g|--global] Run "npm help root" for more info run-script npm run-script + Run arbitrary package scripts + Usage: npm run-script <command> [-- <args>] @@ -642,8 +731,13 @@ All commands: search npm search + Search for pacakges + Usage: - npm search [-l|--long] [--json] [--parseable] [--no-description] [search terms ...] + npm search [search terms ...] + + Options: + [-l|--long] [--json] [-p|--parseable] [--no-description] aliases: s, se, find @@ -651,6 +745,8 @@ All commands: set npm set + Set a value in the npm configuration + Usage: npm set <key>=<value> [<key>=<value> ...] (See \`npm config\`) @@ -658,6 +754,8 @@ All commands: set-script npm set-script + Set tasks in the scripts section of package.json + Usage: npm set-script [<script>] [<command>] @@ -665,6 +763,8 @@ All commands: shrinkwrap npm shrinkwrap + Lock down dependency versions for publication + Usage: npm shrinkwrap @@ -672,6 +772,8 @@ All commands: star npm star + Mark your favorite packages + Usage: npm star [<pkg>...] @@ -679,6 +781,8 @@ All commands: stars npm stars + View packages marked as favorites + Usage: npm stars [<user>] @@ -686,6 +790,8 @@ All commands: start npm start + Start a package + Usage: npm start [-- <args>] @@ -693,6 +799,8 @@ All commands: stop npm stop + Stop a package + Usage: npm stop [-- <args>] @@ -700,6 +808,8 @@ All commands: team npm team + Manage organization teams and team memberships + Usage: npm team create <scope:team> [--otp <otpcode>] npm team destroy <scope:team> [--otp <otpcode>] @@ -711,6 +821,8 @@ All commands: test npm test + Test a package + Usage: npm test [-- <args>] @@ -720,6 +832,8 @@ All commands: token npm token + Manage your authentication tokens + Usage: npm token list npm token revoke <id|token> @@ -729,8 +843,13 @@ All commands: uninstall npm uninstall + Remove a package + Usage: - npm uninstall [<@scope>/]<pkg>[@<version>]... [-S|--save|--no-save] + npm uninstall [<@scope>/]<pkg>... + + Options: + [-S|--save|--no-save|--save-prod|--save-dev|--save-optional|--save-peer] aliases: un, unlink, remove, rm, r @@ -738,6 +857,8 @@ All commands: unpublish npm unpublish + Remove a package from the registry + Usage: npm unpublish [<@scope>/]<pkg>[@<version>] @@ -745,6 +866,8 @@ All commands: unstar npm unstar + Remove an item from your favorite packages + Usage: npm unstar [<pkg>...] @@ -752,8 +875,13 @@ All commands: update npm update + Update packages + Usage: - npm update [-g] [<pkg>...] + npm update [<pkg>...] + + Options: + [-g|--global] aliases: up, upgrade, udpate @@ -761,6 +889,8 @@ All commands: version npm version + Bump a package version + Usage: npm version [<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease [--preid=<prerelease-id>] | from-git] @@ -770,6 +900,8 @@ All commands: view npm view + View registry info + Usage: npm view [<@scope>/]<pkg>[@<version>] [<field>[.subfield]...] @@ -779,10 +911,13 @@ All commands: whoami npm whoami - prints username according to given registry + Display npm username Usage: - npm whoami [--registry <registry>] + npm whoami + + Options: + [--registry <registry>] Run "npm help whoami" for more info @@ -794,5 +929,4 @@ More configuration info: npm help config Configuration fields: npm help 7 config npm@{VERSION} {BASEDIR} - ` diff --git a/deps/npm/tap-snapshots/test-lib-utils-tar.js-TAP.test.js b/deps/npm/tap-snapshots/test-lib-utils-tar.js-TAP.test.js index 402a0e735a..b0b38de341 100644 --- a/deps/npm/tap-snapshots/test-lib-utils-tar.js-TAP.test.js +++ b/deps/npm/tap-snapshots/test-lib-utils-tar.js-TAP.test.js @@ -20,10 +20,10 @@ bundle-dep name: my-cool-pkg version: 1.0.0 filename: my-cool-pkg-1.0.0.tgz -package size: 222 B +package size: 216 B unpacked size: 101 B -shasum: fe3a2f6064ade3bc21640874530586343f2d832f -integrity: sha512-ehndP8xBQL4yo[...]kWinZ4k1SCqUA== +shasum: a604258e06adecec0b18f48e901c5802f19f7dab +integrity: sha512-fnN6NmI8DerTt[...]6rH17jx7OIFig== bundled deps: 1 bundled files: 0 own files: 2 diff --git a/deps/npm/test/fixtures/mock-npm.js b/deps/npm/test/fixtures/mock-npm.js new file mode 100644 index 0000000000..c47758111f --- /dev/null +++ b/deps/npm/test/fixtures/mock-npm.js @@ -0,0 +1,22 @@ +// Basic npm fixture that you can give a config object that acts like +// npm.config You still need a separate flatOptions but this is the first step +// to eventually just using npm itself + +const mockNpm = (base = {}) => { + const config = base.config || {} + const flatOptions = base.flatOptions || {} + return { + ...base, + flatOptions, + config: { + // for now just set `find` to what config.find should return + // this works cause `find` is not an existing config entry + find: (k) => config[k], + get: (k) => config[k], + set: (k, v) => config[k] = v, + list: [config] + }, + } +} + +module.exports = mockNpm diff --git a/deps/npm/test/lib/audit.js b/deps/npm/test/lib/audit.js index d291ef8794..a25e6b0e27 100644 --- a/deps/npm/test/lib/audit.js +++ b/deps/npm/test/lib/audit.js @@ -1,5 +1,6 @@ const t = require('tap') const requireInject = require('require-inject') +const mockNpm = require('../fixtures/mock-npm') t.test('should audit using Arborist', t => { let ARB_ARGS = null @@ -9,15 +10,15 @@ t.test('should audit using Arborist', t => { let OUTPUT_CALLED = false let ARB_OBJ = null - const npm = { + const npm = mockNpm({ prefix: 'foo', - flatOptions: { + config: { json: false, }, output: () => { OUTPUT_CALLED = true }, - } + }) const Audit = requireInject('../../lib/audit.js', { 'npm-audit-report': () => { AUDIT_REPORT_CALLED = true @@ -65,13 +66,13 @@ t.test('should audit using Arborist', t => { }) t.test('should audit - json', t => { - const npm = { + const npm = mockNpm({ prefix: 'foo', - flatOptions: { + config: { json: true, }, output: () => {}, - } + }) const Audit = requireInject('../../lib/audit.js', { 'npm-audit-report': () => ({ @@ -98,9 +99,12 @@ t.test('report endpoint error', t => { t.test(`json=${json}`, t => { const OUTPUT = [] const LOGS = [] - const npm = { + const npm = mockNpm({ prefix: 'foo', command: 'audit', + config: { + json, + }, flatOptions: { json, }, @@ -110,7 +114,7 @@ t.test('report endpoint error', t => { output: (...msg) => { OUTPUT.push(msg) }, - } + }) const Audit = requireInject('../../lib/audit.js', { 'npm-audit-report': () => { throw new Error('should not call audit report when there are errors') diff --git a/deps/npm/test/lib/bin.js b/deps/npm/test/lib/bin.js index 428b2e3bad..1d9341169b 100644 --- a/deps/npm/test/lib/bin.js +++ b/deps/npm/test/lib/bin.js @@ -1,5 +1,6 @@ const { test } = require('tap') const requireInject = require('require-inject') +const mockNpm = require('../fixtures/mock-npm') test('bin', (t) => { t.plan(4) @@ -7,13 +8,13 @@ test('bin', (t) => { const Bin = require('../../lib/bin.js') - const npm = { + const npm = mockNpm({ bin: dir, - flatOptions: { global: false }, + config: { global: false }, output: (output) => { t.equal(output, dir, 'prints the correct directory') }, - } + }) const bin = new Bin(npm) t.match(bin.usage, 'bin', 'usage has command name in it') @@ -39,13 +40,13 @@ test('bin -g', (t) => { '../../lib/utils/path.js': [dir], }) - const npm = { + const npm = mockNpm({ bin: dir, - flatOptions: { global: true }, + config: { global: true }, output: (output) => { t.equal(output, dir, 'prints the correct directory') }, - } + }) const bin = new Bin(npm) bin.exec([], (err) => { @@ -69,13 +70,13 @@ test('bin -g (not in path)', (t) => { const Bin = requireInject('../../lib/bin.js', { '../../lib/utils/path.js': ['/not/my/dir'], }) - const npm = { + const npm = mockNpm({ bin: dir, - flatOptions: { global: true }, + config: { global: true }, output: (output) => { t.equal(output, dir, 'prints the correct directory') }, - } + }) const bin = new Bin(npm) bin.exec([], (err) => { diff --git a/deps/npm/test/lib/birthday.js b/deps/npm/test/lib/birthday.js index c818223fb5..0589be7a8e 100644 --- a/deps/npm/test/lib/birthday.js +++ b/deps/npm/test/lib/birthday.js @@ -1,20 +1,23 @@ const t = require('tap') -const npm = { - flatOptions: { - yes: false, - package: [], - }, +const mockNpm = require('../fixtures/mock-npm') + +const config = { + yes: false, + package: [], +} +const npm = mockNpm({ + config, commands: { exec: (args, cb) => { - t.equal(npm.flatOptions.yes, true, 'should say yes') - t.strictSame(npm.flatOptions.package, ['@npmcli/npm-birthday'], + t.equal(npm.config.get('yes'), true, 'should say yes') + t.strictSame(npm.config.get('package'), ['@npmcli/npm-birthday'], 'uses correct package') t.strictSame(args, ['npm-birthday'], 'called with correct args') t.match(cb, Function, 'callback is a function') cb() }, }, -} +}) const Birthday = require('../../lib/birthday.js') const birthday = new Birthday(npm) diff --git a/deps/npm/test/lib/cache.js b/deps/npm/test/lib/cache.js index 773adc6a8a..0fdf768568 100644 --- a/deps/npm/test/lib/cache.js +++ b/deps/npm/test/lib/cache.js @@ -1,23 +1,12 @@ const t = require('tap') const requireInject = require('require-inject') +const mockNpm = require('../fixtures/mock-npm') const path = require('path') const usageUtil = () => 'usage instructions' -const flatOptions = { - force: false, -} - let outputOutput = [] -const npm = { - flatOptions, - cache: '/fake/path', - output: (msg) => { - outputOutput.push(msg) - }, -} - let rimrafPath = '' const rimraf = (path, cb) => { rimrafPath = path @@ -66,6 +55,14 @@ const Cache = requireInject('../../lib/cache.js', { '../../lib/utils/usage.js': usageUtil, }) +const npm = mockNpm({ + cache: '/fake/path', + flatOptions: { force: false }, + config: { force: false }, + output: (msg) => { + outputOutput.push(msg) + }, +}) const cache = new Cache(npm) t.test('cache no args', t => { @@ -83,10 +80,12 @@ t.test('cache clean', t => { }) t.test('cache clean (force)', t => { - flatOptions.force = true + npm.config.set('force', true) + npm.flatOptions.force = true t.teardown(() => { rimrafPath = '' - flatOptions.force = false + npm.config.force = false + npm.flatOptions.force = false }) cache.exec(['clear'], err => { @@ -131,7 +130,7 @@ t.test('cache add pkg only', t => { ['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.same(tarballStreamOpts, npm.flatOptions, 'passes the correct options to pacote') t.end() }) }) @@ -150,7 +149,7 @@ t.test('cache add pkg w/ spec modifier', t => { ['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.same(tarballStreamOpts, npm.flatOptions, 'passes the correct options to pacote') t.end() }) }) diff --git a/deps/npm/test/lib/ci.js b/deps/npm/test/lib/ci.js index 3419218ef9..7f06a6cebc 100644 --- a/deps/npm/test/lib/ci.js +++ b/deps/npm/test/lib/ci.js @@ -5,6 +5,7 @@ const readdir = util.promisify(fs.readdir) const { test } = require('tap') const requireInject = require('require-inject') +const mockNpm = require('../fixtures/mock-npm') test('should ignore scripts with --ignore-scripts', (t) => { const SCRIPTS = [] @@ -22,17 +23,15 @@ test('should ignore scripts with --ignore-scripts', (t) => { }, }) - const ci = new CI({ + const npm = mockNpm({ globalDir: 'path/to/node_modules/', prefix: 'foo', - flatOptions: { - global: false, - ignoreScripts: true, - }, config: { - get: () => false, + global: false, + 'ignore-scripts': true, }, }) + const ci = new CI(npm) ci.exec([], er => { if (er) @@ -115,12 +114,13 @@ test('should use Arborist and run-script', (t) => { }, }) - const ci = new CI({ + const npm = mockNpm({ prefix: path, - flatOptions: { + config: { global: false, }, }) + const ci = new CI(npm) ci.exec(null, er => { if (er) @@ -146,12 +146,13 @@ test('should pass flatOptions to Arborist.reify', (t) => { } }, }) - const ci = new CI({ + const npm = mockNpm({ prefix: 'foo', flatOptions: { production: true, }, }) + const ci = new CI(npm) ci.exec(null, er => { if (er) throw er @@ -173,14 +174,15 @@ test('should throw if package-lock.json or npm-shrinkwrap missing', (t) => { }, }, }) - const ci = new CI({ + const npm = mockNpm({ prefix: testDir, - flatOptions: { + config: { global: false, }, }) + const ci = new CI(npm) ci.exec(null, (err, res) => { - t.ok(err, 'throws error when there is no package-lock') + t.match(err, /package-lock.json/, 'throws error when there is no package-lock') t.notOk(res) t.end() }) @@ -191,12 +193,13 @@ test('should throw ECIGLOBAL', (t) => { '@npmcli/run-script': opts => {}, '../../lib/utils/reify-finish.js': async () => {}, }) - const ci = new CI({ + const npm = mockNpm({ prefix: 'foo', - flatOptions: { + config: { global: true, }, }) + const ci = new CI(npm) ci.exec(null, (err, res) => { t.equals(err.code, 'ECIGLOBAL', 'throws error with global packages') t.notOk(res) @@ -227,12 +230,13 @@ test('should remove existing node_modules before installing', (t) => { }, }) - const ci = new CI({ + const npm = mockNpm({ prefix: testDir, - flatOptions: { + config: { global: false, }, }) + const ci = new CI(npm) ci.exec(null, er => { if (er) diff --git a/deps/npm/test/lib/cli.js b/deps/npm/test/lib/cli.js index b5441be1e4..40da77bf44 100644 --- a/deps/npm/test/lib/cli.js +++ b/deps/npm/test/lib/cli.js @@ -1,7 +1,11 @@ const t = require('tap') let LOAD_ERROR = null +const npmOutputs = [] const npmock = { + log: { level: 'silent' }, + output: (...msg) => npmOutputs.push(msg), + usage: 'npm usage test example', version: '99.99.99', load: cb => cb(LOAD_ERROR), argv: [], @@ -21,8 +25,11 @@ const unsupportedMock = { } let errorHandlerCalled = null +let errorHandlerCb const errorHandlerMock = (...args) => { errorHandlerCalled = args + if (errorHandlerCb) + errorHandlerCb() } let errorHandlerExitCalled = null errorHandlerMock.exit = code => { @@ -39,15 +46,23 @@ const npmlogMock = { const requireInject = require('require-inject') const cli = requireInject.installGlobally('../../lib/cli.js', { '../../lib/npm.js': npmock, + '../../lib/utils/did-you-mean.js': () => '\ntest did you mean', '../../lib/utils/unsupported.js': unsupportedMock, '../../lib/utils/error-handler.js': errorHandlerMock, npmlog: npmlogMock, }) t.test('print the version, and treat npm_g to npm -g', t => { - const { log } = console - const consoleLogs = [] - console.log = (...msg) => consoleLogs.push(msg) + t.teardown(() => { + delete npmock.config.settings.version + process.argv = argv + npmock.argv.length = 0 + proc.argv.length = 0 + logs.length = 0 + npmOutputs.length = 0 + errorHandlerExitCalled = null + }) + const { argv } = process const proc = { argv: ['node', 'npm_g', '-v'], @@ -67,25 +82,13 @@ t.test('print the version, and treat npm_g to npm -g', t => { ['info', 'using', 'npm@%s', '99.99.99'], ['info', 'using', 'node@%s', '420.69.lol'], ]) - t.strictSame(consoleLogs, [['99.99.99']]) + t.strictSame(npmOutputs, [['99.99.99']]) t.strictSame(errorHandlerExitCalled, 0) - delete npmock.config.settings.version - process.argv = argv - console.log = log - npmock.argv.length = 0 - proc.argv.length = 0 - logs.length = 0 - consoleLogs.length = 0 - errorHandlerExitCalled = null - t.end() }) t.test('calling with --versions calls npm version with no args', t => { - const { log } = console - const consoleLogs = [] - console.log = (...msg) => consoleLogs.push(msg) const processArgv = process.argv const proc = { argv: ['node', 'npm', 'install', 'or', 'whatever', '--versions'], @@ -97,11 +100,10 @@ t.test('calling with --versions calls npm version with no args', t => { t.teardown(() => { delete npmock.config.settings.versions process.argv = processArgv - console.log = log npmock.argv.length = 0 proc.argv.length = 0 logs.length = 0 - consoleLogs.length = 0 + npmOutputs.length = 0 errorHandlerExitCalled = null delete npmock.commands.version }) @@ -117,7 +119,7 @@ t.test('calling with --versions calls npm version with no args', t => { ['info', 'using', 'node@%s', undefined], ]) - t.strictSame(consoleLogs, []) + t.strictSame(npmOutputs, []) t.strictSame(errorHandlerExitCalled, null) t.strictSame(args, []) @@ -127,55 +129,80 @@ t.test('calling with --versions calls npm version with no args', t => { cli(proc) }) -t.test('print usage if -h provided', t => { - const { log } = console - const consoleLogs = [] - console.log = (...msg) => consoleLogs.push(msg) +t.test('print usage if no params provided', t => { + const { output } = npmock + t.teardown(() => { + npmock.output = output + }) + const proc = { + argv: ['node', 'npm'], + on: () => {}, + } + npmock.argv = [] + npmock.output = (msg) => { + if (msg) { + t.match(msg, 'npm usage test example', 'outputs npm usage') + t.end() + } + } + cli(proc) +}) + +t.test('print usage if non-command param provided', t => { + const { output } = npmock + t.teardown(() => { + npmock.output = output + }) const proc = { argv: ['node', 'npm', 'asdf'], on: () => {}, } npmock.argv = ['asdf'] + npmock.output = (msg) => { + if (msg) { + t.match(msg, 'Unknown command: "asdf"\ntest did you mean', 'outputs did you mean') + t.end() + } + } + cli(proc) +}) +t.test('gracefully handles error printing usage', t => { + const { output } = npmock t.teardown(() => { - console.log = log - npmock.argv.length = 0 - proc.argv.length = 0 - logs.length = 0 - consoleLogs.length = 0 - errorHandlerExitCalled = null - delete npmock.commands.help + npmock.output = output + errorHandlerCb = null }) - - npmock.commands.help = (args, cb) => { - delete npmock.commands.help - t.equal(proc.title, 'npm') - t.strictSame(args, ['asdf']) - t.strictSame(npmock.argv, ['asdf']) - t.strictSame(proc.argv, ['node', 'npm', 'asdf']) - t.strictSame(logs, [ - 'pause', - ['verbose', 'cli', ['node', 'npm', 'asdf']], - ['info', 'using', 'npm@%s', '99.99.99'], - ['info', 'using', 'node@%s', undefined], - ]) - t.strictSame(consoleLogs, []) - t.strictSame(errorHandlerExitCalled, null) + const proc = { + argv: ['node', 'npm', 'asdf'], + on: () => {}, + } + npmock.argv = [] + npmock.output = (msg) => { + throw new Error('test exception') + } + errorHandlerCb = () => { + t.match(errorHandlerCalled, /test exception/) t.end() } - cli(proc) }) t.test('load error calls error handler', t => { - const er = new Error('poop') + t.teardown(() => { + errorHandlerCb = null + LOAD_ERROR = null + }) + + const er = new Error('test load error') LOAD_ERROR = er const proc = { argv: ['node', 'npm', 'asdf'], on: () => {}, } + errorHandlerCb = () => { + t.strictSame(errorHandlerCalled, [er]) + t.end() + } cli(proc) - t.strictSame(errorHandlerCalled, [er]) - LOAD_ERROR = null - t.end() }) diff --git a/deps/npm/test/lib/completion.js b/deps/npm/test/lib/completion.js index 708f138251..c6ef901a7e 100644 --- a/deps/npm/test/lib/completion.js +++ b/deps/npm/test/lib/completion.js @@ -63,11 +63,14 @@ const cmdList = { plumbing: [], } +// only include a subset so that the snapshots aren't huge and +// don't change when we add/remove config definitions. +const definitions = require('../../lib/utils/config/definitions.js') const config = { - types: { - global: Boolean, - browser: [null, Boolean, String], - registry: [null, String], + definitions: { + global: definitions.global, + browser: definitions.browser, + registry: definitions.registry, }, shorthands: { reg: ['--registry'], @@ -80,7 +83,7 @@ const deref = (cmd) => { const Completion = requireInject('../../lib/completion.js', { '../../lib/utils/cmd-list.js': cmdList, - '../../lib/utils/config.js': config, + '../../lib/utils/config/index.js': config, '../../lib/utils/deref-command.js': deref, '../../lib/utils/is-windows-shell.js': false, }) diff --git a/deps/npm/test/lib/config.js b/deps/npm/test/lib/config.js index 3aeb29f8d3..14cd816171 100644 --- a/deps/npm/test/lib/config.js +++ b/deps/npm/test/lib/config.js @@ -1,4 +1,5 @@ const t = require('tap') + const requireInject = require('require-inject') const { EventEmitter } = require('events') @@ -22,12 +23,21 @@ const redactCwd = (path) => { t.cleanSnapshot = (str) => redactCwd(str) let result = '' -const types = { - 'init-author-name': String, - 'init-version': String, - 'init.author.name': String, - 'init.version': String, -} + +const configDefs = require('../../lib/utils/config') +const definitions = Object.entries(configDefs.definitions) + .filter(([key, def]) => { + return [ + 'init-author-name', + 'init.author.name', + 'init-version', + 'init.version', + ].includes(key) + }).reduce((defs, [key, def]) => { + defs[key] = def + return defs + }, {}) + const defaults = { 'init-author-name': '', 'init-version': '1.0.0', @@ -35,7 +45,7 @@ const defaults = { 'init.version': '1.0.0', } -const flatOptions = { +const cliConfig = { editor: 'vi', json: false, long: false, @@ -43,7 +53,6 @@ const flatOptions = { } const npm = { - flatOptions, log: { info: () => null, enableProgress: () => null, @@ -53,10 +62,10 @@ const npm = { data: new Map(Object.entries({ default: { data: defaults, source: 'default values' }, global: { data: {}, source: '/etc/npmrc' }, - cli: { data: flatOptions, source: 'command line options' }, + cli: { data: cliConfig, source: 'command line options' }, })), get (key) { - return flatOptions[key] + return cliConfig[key] }, validate () { return true @@ -70,7 +79,7 @@ const npm = { const usageUtil = () => 'usage instructions' const mocks = { - '../../lib/utils/config.js': { defaults, types }, + '../../lib/utils/config/index.js': { defaults, definitions }, '../../lib/utils/usage.js': usageUtil, } @@ -110,13 +119,13 @@ t.test('config list overrides', t => { }, source: '~/.npmrc', }) - flatOptions['init.author.name'] = 'Bar' + cliConfig['init.author.name'] = 'Bar' npm.config.find = () => 'cli' result = '' t.teardown(() => { result = '' npm.config.data.delete('user') - delete flatOptions['init.author.name'] + delete cliConfig['init.author.name'] delete npm.config.find }) @@ -129,12 +138,12 @@ t.test('config list overrides', t => { t.test('config list --long', t => { t.plan(2) - npm.config.find = key => key in flatOptions ? 'cli' : 'default' - flatOptions.long = true + npm.config.find = key => key in cliConfig ? 'cli' : 'default' + cliConfig.long = true result = '' t.teardown(() => { delete npm.config.find - flatOptions.long = false + cliConfig.long = false result = '' }) @@ -147,7 +156,7 @@ t.test('config list --long', t => { t.test('config list --json', t => { t.plan(2) - flatOptions.json = true + cliConfig.json = true result = '' npm.config.list = [{ '//private-reg.npmjs.org/:_authThoken': 'f00ba1', @@ -158,7 +167,7 @@ t.test('config list --json', t => { t.teardown(() => { delete npm.config.list - flatOptions.json = false + cliConfig.json = false npm.config.get = npmConfigGet result = '' }) @@ -246,13 +255,13 @@ t.test('config delete key --global', t => { t.equal(where, 'global', 'should save global config post-delete') } - flatOptions.global = true + cliConfig.global = true config.exec(['delete', 'foo'], (err) => { t.ifError(err, 'npm config delete key --global') }) t.teardown(() => { - flatOptions.global = false + cliConfig.global = false delete npm.config.delete delete npm.config.save }) @@ -401,13 +410,13 @@ t.test('config set key --global', t => { t.equal(where, 'global', 'should save global config') } - flatOptions.global = true + cliConfig.global = true config.exec(['set', 'foo', 'bar'], (err) => { t.ifError(err, 'npm config set key --global') }) t.teardown(() => { - flatOptions.global = false + cliConfig.global = false delete npm.config.set delete npm.config.save }) @@ -555,7 +564,7 @@ sign-git-commit=true` t.test('config edit --global', t => { t.plan(6) - flatOptions.global = true + cliConfig.global = true const npmrc = 'init.author.name=Foo' npm.config.data.set('global', { source: '/etc/npmrc', @@ -595,7 +604,7 @@ t.test('config edit --global', t => { }) t.teardown(() => { - flatOptions.global = false + cliConfig.global = false npm.config.data.delete('user') delete npm.config.save }) @@ -612,7 +621,7 @@ t.test('completion', t => { testComp(['npm', 'config'], ['get', 'set', 'delete', 'ls', 'rm', 'edit', 'list']) testComp(['npm', 'config', 'set', 'foo'], []) - const possibleConfigKeys = [...Object.keys(types)] + const possibleConfigKeys = [...Object.keys(definitions)] testComp(['npm', 'config', 'get'], possibleConfigKeys) testComp(['npm', 'config', 'set'], possibleConfigKeys) testComp(['npm', 'config', 'delete'], possibleConfigKeys) diff --git a/deps/npm/test/lib/dedupe.js b/deps/npm/test/lib/dedupe.js index 3e8b2f4c01..851163f935 100644 --- a/deps/npm/test/lib/dedupe.js +++ b/deps/npm/test/lib/dedupe.js @@ -1,20 +1,13 @@ const { test } = require('tap') const requireInject = require('require-inject') - -const npm = (base) => { - const config = base.config - return { - ...base, - flatOptions: { dryRun: false }, - config: { - get: (k) => config[k], - }, - } -} +const mockNpm = require('../fixtures/mock-npm') test('should throw in global mode', (t) => { const Dedupe = requireInject('../../lib/dedupe.js') - const dedupe = new Dedupe(npm({ config: { global: true }})) + const npm = mockNpm({ + config: { 'dry-run': false, global: true }, + }) + const dedupe = new Dedupe(npm) dedupe.exec([], er => { t.match(er, { code: 'EDEDUPEGLOBAL' }, 'throws EDEDUPEGLOBAL') @@ -36,12 +29,13 @@ test('should remove dupes using Arborist', (t) => { t.ok(arb, 'gets arborist tree') }, }) - const dedupe = new Dedupe(npm({ + const npm = mockNpm({ prefix: 'foo', config: { 'dry-run': 'true', }, - })) + }) + const dedupe = new Dedupe(npm) dedupe.exec([], er => { if (er) throw er @@ -53,17 +47,18 @@ test('should remove dupes using Arborist', (t) => { test('should remove dupes using Arborist - no arguments', (t) => { const Dedupe = requireInject('../../lib/dedupe.js', { '@npmcli/arborist': function (args) { - t.ok(args.dryRun, 'gets dryRun from flatOptions') + t.ok(args.dryRun, 'gets dryRun from config') this.dedupe = () => {} }, '../../lib/utils/reify-output.js': () => {}, }) - const dedupe = new Dedupe(npm({ + const npm = mockNpm({ prefix: 'foo', config: { - 'dry-run': true, + 'dry-run': 'true', }, - })) + }) + const dedupe = new Dedupe(npm) dedupe.exec(null, () => { t.end() }) diff --git a/deps/npm/test/lib/diff.js b/deps/npm/test/lib/diff.js index 9f58505dca..08761c64c8 100644 --- a/deps/npm/test/lib/diff.js +++ b/deps/npm/test/lib/diff.js @@ -1,30 +1,35 @@ const { resolve } = require('path') const t = require('tap') const requireInject = require('require-inject') +const mockNpm = require('../fixtures/mock-npm') const noop = () => null let libnpmdiff = noop let rlp = () => 'foo' -const defaultFlatOptions = { - defaultTag: 'latest', + +const config = { + global: false, + tag: 'latest', diff: [], +} +const flatOptions = { + global: false, diffUnified: null, diffIgnoreAllSpace: false, diffNoPrefix: false, diffSrcPrefix: '', diffDstPrefix: '', diffText: false, - prefix: '.', savePrefix: '^', } -const npm = { +const npm = mockNpm({ globalDir: __dirname, - flatOptions: { ...defaultFlatOptions }, - get prefix () { - return this.flatOptions.prefix - }, + prefix: '.', + config, + flatOptions, output: noop, -} +}) + const mocks = { npmlog: { info: noop, verbose: noop }, libnpmdiff: (...args) => libnpmdiff(...args), @@ -34,10 +39,21 @@ const mocks = { } t.afterEach(cb => { - npm.flatOptions = { ...defaultFlatOptions } + config.global = false + config.tag = 'latest' + config.diff = [] + flatOptions.global = false + flatOptions.diffUnified = null + flatOptions.diffIgnoreAllSpace = false + flatOptions.diffNoPrefix = false + flatOptions.diffSrcPrefix = '' + flatOptions.diffDstPrefix = '' + flatOptions.diffText = false + flatOptions.savePrefix = '^' + npm.globalDir = __dirname + npm.prefix = '..' libnpmdiff = noop rlp = () => 'foo' - npm.globalDir = __dirname cb() }) @@ -55,7 +71,7 @@ t.test('no args', t => { t.match(opts, npm.flatOptions, 'should forward flat options') } - npm.flatOptions.prefix = path + npm.prefix = path diff.exec([], err => { if (err) throw err @@ -102,10 +118,11 @@ t.test('single arg', t => { t.equal(a, 'foo@1.0.0', 'should forward single spec') t.equal(b, `file:${path}`, 'should compare to cwd') t.match(opts, npm.flatOptions, 'should forward flat options') + t.end() } - npm.flatOptions.diff = ['foo@1.0.0'] - npm.flatOptions.prefix = path + config.diff = ['foo@1.0.0'] + npm.prefix = path diff.exec([], err => { if (err) throw err @@ -118,8 +135,8 @@ t.test('single arg', t => { throw new Error('ERR') } - npm.flatOptions.diff = ['foo@1.0.0'] - npm.flatOptions.prefix = path + config.diff = ['foo@1.0.0'] + npm.prefix = path diff.exec([], err => { t.match( err, @@ -140,8 +157,8 @@ t.test('single arg', t => { t.match(opts, npm.flatOptions, 'should forward flat options') } - npm.flatOptions.diff = ['foo@~1.0.0'] - npm.flatOptions.prefix = path + config.diff = ['foo@~1.0.0'] + npm.prefix = path diff.exec([], err => { if (err) throw err @@ -158,8 +175,8 @@ t.test('single arg', t => { t.match(opts, npm.flatOptions, 'should forward flat options') } - npm.flatOptions.diff = ['2.1.4'] - npm.flatOptions.prefix = path + config.diff = ['2.1.4'] + npm.prefix = path diff.exec([], err => { if (err) throw err @@ -171,7 +188,7 @@ t.test('single arg', t => { throw new Error('ERR') } - npm.flatOptions.diff = ['2.1.4'] + config.diff = ['2.1.4'] diff.exec([], err => { t.match( err, @@ -198,8 +215,8 @@ t.test('single arg', t => { }, 'should forward flatOptions and diffFiles') } - npm.flatOptions.diff = ['2.1.4'] - npm.flatOptions.prefix = path + config.diff = ['2.1.4'] + npm.prefix = path diff.exec(['./foo.js', './bar.js'], err => { if (err) throw err @@ -221,8 +238,8 @@ t.test('single arg', t => { t.equal(b, `file:${path}`, 'should compare to cwd') } - npm.flatOptions.diff = ['bar@1.0.0'] - npm.flatOptions.prefix = path + config.diff = ['bar@1.0.0'] + npm.prefix = path diff.exec([], err => { if (err) @@ -248,8 +265,8 @@ t.test('single arg', t => { t.match(opts, npm.flatOptions, 'should forward flat options') } - npm.flatOptions.diff = ['simple-output'] - npm.flatOptions.prefix = path + config.diff = ['simple-output'] + npm.prefix = path diff.exec([], err => { if (err) throw err @@ -262,8 +279,8 @@ t.test('single arg', t => { throw new Error('ERR') } - npm.flatOptions.diff = ['bar'] - npm.flatOptions.prefix = path + config.diff = ['bar'] + npm.prefix = path diff.exec([], err => { t.match( err, @@ -294,8 +311,8 @@ t.test('single arg', t => { }), }) - npm.flatOptions.diff = ['bar'] - npm.flatOptions.prefix = path + config.diff = ['bar'] + npm.prefix = path const Diff = requireInject('../../lib/diff.js', { ...mocks, @@ -355,9 +372,10 @@ t.test('single arg', t => { }, }) - npm.flatOptions.global = true - npm.flatOptions.diff = ['lorem'] - npm.flatOptions.prefix = resolve(path, 'project') + config.global = true + flatOptions.global = true + config.diff = ['lorem'] + npm.prefix = resolve(path, 'project') npm.globalDir = resolve(path, 'globalDir/lib/node_modules') const Diff = requireInject('../../lib/diff.js', { @@ -409,8 +427,8 @@ t.test('single arg', t => { t.equal(b, 'bar@2.0.0', 'should have expected comparison spec') } - npm.flatOptions.diff = ['bar@2.0.0'] - npm.flatOptions.prefix = path + config.diff = ['bar@2.0.0'] + npm.prefix = path diff.exec([], err => { if (err) @@ -466,8 +484,8 @@ t.test('single arg', t => { }) const diff = new Diff(npm) - npm.flatOptions.diff = ['lorem'] - npm.flatOptions.prefix = path + config.diff = ['lorem'] + npm.prefix = path diff.exec([], err => { if (err) @@ -499,8 +517,8 @@ t.test('single arg', t => { }) const diff = new Diff(npm) - npm.flatOptions.diff = ['lorem'] - npm.flatOptions.prefix = path + config.diff = ['lorem'] + npm.prefix = path diff.exec([], err => { if (err) @@ -518,8 +536,8 @@ t.test('single arg', t => { t.equal(b, `file:${path}`, 'should compare to cwd') } - npm.flatOptions.diff = ['bar'] - npm.flatOptions.prefix = path + config.diff = ['bar'] + npm.prefix = path diff.exec([], err => { if (err) @@ -537,8 +555,8 @@ t.test('single arg', t => { t.equal(b, `file:${path}`, 'should compare to cwd') } - npm.flatOptions.diff = ['my-project'] - npm.flatOptions.prefix = path + config.diff = ['my-project'] + npm.prefix = path diff.exec([], err => { if (err) throw err @@ -555,8 +573,8 @@ t.test('single arg', t => { t.equal(b, `file:${path}`, 'should compare to cwd') } - npm.flatOptions.diff = ['/path/to/other-dir'] - npm.flatOptions.prefix = path + config.diff = ['/path/to/other-dir'] + npm.prefix = path diff.exec([], err => { if (err) throw err @@ -566,7 +584,7 @@ t.test('single arg', t => { t.test('unsupported spec type', t => { rlp = async () => 'my-project' - npm.flatOptions.diff = ['git+https://github.com/user/foo'] + config.diff = ['git+https://github.com/user/foo'] diff.exec([], err => { t.match( @@ -591,7 +609,7 @@ t.test('first arg is a qualified spec', t => { t.match(opts, npm.flatOptions, 'should forward flat options') } - npm.flatOptions.diff = ['bar@1.0.0', 'bar@^2.0.0'] + config.diff = ['bar@1.0.0', 'bar@^2.0.0'] diff.exec([], err => { if (err) throw err @@ -624,8 +642,8 @@ t.test('first arg is a qualified spec', t => { t.equal(b, `bar@file:${resolve(path, 'node_modules/bar')}`, 'should target local node_modules pkg') } - npm.flatOptions.prefix = path - npm.flatOptions.diff = ['bar@2.0.0', 'bar'] + npm.prefix = path + config.diff = ['bar@2.0.0', 'bar'] diff.exec([], err => { if (err) throw err @@ -635,7 +653,7 @@ t.test('first arg is a qualified spec', t => { t.test('second arg is a valid semver version', t => { t.plan(2) - npm.flatOptions.diff = ['bar@1.0.0', '2.0.0'] + config.diff = ['bar@1.0.0', '2.0.0'] libnpmdiff = async ([a, b], opts) => { t.equal(a, 'bar@1.0.0', 'should set expected first spec') @@ -656,7 +674,7 @@ t.test('first arg is a qualified spec', t => { t.equal(b, 'bar-fork@latest', 'should target latest tag if not a dep') } - npm.flatOptions.diff = ['bar@1.0.0', 'bar-fork'] + config.diff = ['bar@1.0.0', 'bar-fork'] diff.exec([], err => { if (err) throw err @@ -693,8 +711,8 @@ t.test('first arg is a known dependency name', t => { t.equal(b, 'bar@2.0.0', 'should set expected second spec') } - npm.flatOptions.prefix = path - npm.flatOptions.diff = ['bar', 'bar@2.0.0'] + npm.prefix = path + config.diff = ['bar', 'bar@2.0.0'] diff.exec([], err => { if (err) throw err @@ -733,8 +751,8 @@ t.test('first arg is a known dependency name', t => { t.equal(b, `bar-fork@file:${resolve(path, 'node_modules/bar-fork')}`, 'should target fork local node_modules pkg') } - npm.flatOptions.prefix = path - npm.flatOptions.diff = ['bar', 'bar-fork'] + npm.prefix = path + config.diff = ['bar', 'bar-fork'] diff.exec([], err => { if (err) throw err @@ -767,8 +785,8 @@ t.test('first arg is a known dependency name', t => { t.equal(b, 'bar@2.0.0', 'should use package name from first arg') } - npm.flatOptions.prefix = path - npm.flatOptions.diff = ['bar', '2.0.0'] + npm.prefix = path + config.diff = ['bar', '2.0.0'] diff.exec([], err => { if (err) throw err @@ -801,8 +819,8 @@ t.test('first arg is a known dependency name', t => { t.equal(b, 'bar-fork@latest', 'should set expected second spec') } - npm.flatOptions.prefix = path - npm.flatOptions.diff = ['bar', 'bar-fork'] + npm.prefix = path + config.diff = ['bar', 'bar-fork'] diff.exec([], err => { if (err) throw err @@ -816,7 +834,7 @@ t.test('first arg is a valid semver range', t => { t.test('second arg is a qualified spec', t => { t.plan(2) - npm.flatOptions.diff = ['1.0.0', 'bar@2.0.0'] + config.diff = ['1.0.0', 'bar@2.0.0'] libnpmdiff = async ([a, b], opts) => { t.equal(a, 'bar@1.0.0', 'should use name from second arg') @@ -855,8 +873,8 @@ t.test('first arg is a valid semver range', t => { t.equal(b, `bar@file:${resolve(path, 'node_modules/bar')}`, 'should set expected second spec from nm') } - npm.flatOptions.prefix = path - npm.flatOptions.diff = ['1.0.0', 'bar'] + npm.prefix = path + config.diff = ['1.0.0', 'bar'] diff.exec([], err => { if (err) throw err @@ -872,7 +890,7 @@ t.test('first arg is a valid semver range', t => { t.equal(b, 'my-project@2.0.0', 'should use name from project dir') } - npm.flatOptions.diff = ['1.0.0', '2.0.0'] + config.diff = ['1.0.0', '2.0.0'] diff.exec([], err => { if (err) throw err @@ -885,8 +903,8 @@ t.test('first arg is a valid semver range', t => { throw new Error('ERR') } - npm.flatOptions.diff = ['1.0.0', '2.0.0'] - npm.flatOptions.prefix = path + config.diff = ['1.0.0', '2.0.0'] + npm.prefix = path diff.exec([], err => { t.match( err, @@ -906,7 +924,7 @@ t.test('first arg is a valid semver range', t => { t.equal(b, 'bar@latest', 'should compare against latest tag') } - npm.flatOptions.diff = ['1.0.0', 'bar'] + config.diff = ['1.0.0', 'bar'] diff.exec([], err => { if (err) throw err @@ -937,8 +955,8 @@ t.test('first arg is a valid semver range', t => { }) const diff = new Diff(npm) - npm.flatOptions.diff = ['1.0.0', 'lorem@2.0.0'] - npm.flatOptions.prefix = path + config.diff = ['1.0.0', 'lorem@2.0.0'] + npm.prefix = path diff.exec([], err => { if (err) @@ -960,7 +978,7 @@ t.test('first arg is an unknown dependency name', t => { t.match(opts, { where: '.' }, 'should forward pacote options') } - npm.flatOptions.diff = ['bar', 'bar@2.0.0'] + config.diff = ['bar', 'bar@2.0.0'] diff.exec([], err => { if (err) throw err @@ -993,8 +1011,8 @@ t.test('first arg is an unknown dependency name', t => { t.equal(b, `bar@file:${resolve(path, 'node_modules/bar')}`, 'should target local node_modules pkg') } - npm.flatOptions.prefix = path - npm.flatOptions.diff = ['bar-fork', 'bar'] + npm.prefix = path + config.diff = ['bar-fork', 'bar'] diff.exec([], err => { if (err) throw err @@ -1009,7 +1027,7 @@ t.test('first arg is an unknown dependency name', t => { t.equal(b, 'bar@^1.0.0', 'should use name from first arg') } - npm.flatOptions.diff = ['bar', '^1.0.0'] + config.diff = ['bar', '^1.0.0'] diff.exec([], err => { if (err) throw err @@ -1024,7 +1042,7 @@ t.test('first arg is an unknown dependency name', t => { t.equal(b, 'bar-fork@latest', 'should use latest tag') } - npm.flatOptions.diff = ['bar', 'bar-fork'] + config.diff = ['bar', 'bar-fork'] diff.exec([], err => { if (err) throw err @@ -1043,8 +1061,8 @@ t.test('first arg is an unknown dependency name', t => { t.equal(b, 'bar-fork@latest', 'should use latest tag') } - npm.flatOptions.diff = ['bar', 'bar-fork'] - npm.flatOptions.prefix = path + config.diff = ['bar', 'bar-fork'] + npm.prefix = path diff.exec([], err => { if (err) @@ -1059,7 +1077,7 @@ t.test('various options', t => { t.test('using --name-only option', t => { t.plan(1) - npm.flatOptions.diffNameOnly = true + flatOptions.diffNameOnly = true libnpmdiff = async ([a, b], opts) => { t.match(opts, { @@ -1077,7 +1095,7 @@ t.test('various options', t => { t.test('set files after both versions', t => { t.plan(3) - npm.flatOptions.diff = ['2.1.4', '3.0.0'] + config.diff = ['2.1.4', '3.0.0'] libnpmdiff = async ([a, b], opts) => { t.equal(a, 'foo@2.1.4', 'should use expected spec') @@ -1114,7 +1132,7 @@ t.test('various options', t => { }, 'should forward all remaining items as filenames') } - npm.flatOptions.prefix = path + npm.prefix = path diff.exec(['./foo.js', './bar.js'], err => { if (err) throw err @@ -1124,12 +1142,12 @@ t.test('various options', t => { t.test('using diff option', t => { t.plan(1) - npm.flatOptions.diffContext = 5 - npm.flatOptions.diffIgnoreWhitespace = true - npm.flatOptions.diffNoPrefix = false - npm.flatOptions.diffSrcPrefix = 'foo/' - npm.flatOptions.diffDstPrefix = 'bar/' - npm.flatOptions.diffText = true + flatOptions.diffContext = 5 + flatOptions.diffIgnoreWhitespace = true + flatOptions.diffNoPrefix = false + flatOptions.diffSrcPrefix = 'foo/' + flatOptions.diffDstPrefix = 'bar/' + flatOptions.diffText = true libnpmdiff = async ([a, b], opts) => { t.match(opts, { @@ -1153,7 +1171,7 @@ t.test('various options', t => { }) t.test('too many args', t => { - npm.flatOptions.diff = ['a', 'b', 'c'] + config.diff = ['a', 'b', 'c'] diff.exec([], err => { t.match( err, diff --git a/deps/npm/test/lib/dist-tag.js b/deps/npm/test/lib/dist-tag.js index a3c05bb2b3..9415dacbe4 100644 --- a/deps/npm/test/lib/dist-tag.js +++ b/deps/npm/test/lib/dist-tag.js @@ -1,18 +1,10 @@ const requireInject = require('require-inject') +const mockNpm = require('../fixtures/mock-npm') const { test } = require('tap') -let prefix let result = '' let log = '' -// these declared opts are used in ./utils/read-local-package.js -const _flatOptions = { - global: false, - get prefix () { - return prefix - }, -} - const routeMap = { '/-/package/@scoped%2fpkg/dist-tags': { latest: '1.0.0', @@ -60,20 +52,18 @@ const DistTag = requireInject('../../lib/dist-tag.js', { }, }) -const distTag = new DistTag({ - flatOptions: _flatOptions, +const npm = mockNpm({ config: { - get (key) { - return _flatOptions[key] - }, + global: false, }, output: msg => { result = msg }, }) +const distTag = new DistTag(npm) test('ls in current package', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: '@scoped/pkg', }), @@ -91,7 +81,7 @@ test('ls in current package', (t) => { }) test('no args in current package', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: '@scoped/pkg', }), @@ -109,7 +99,7 @@ test('no args in current package', (t) => { }) test('borked cmd usage', (t) => { - prefix = t.testdir({}) + npm.prefix = t.testdir({}) distTag.exec(['borked', '@scoped/pkg'], (err) => { t.matchSnapshot(err, 'should show usage error') result = '' @@ -119,7 +109,7 @@ test('borked cmd usage', (t) => { }) test('ls on named package', (t) => { - prefix = t.testdir({}) + npm.prefix = t.testdir({}) distTag.exec(['ls', '@scoped/another'], (err) => { t.ifError(err, 'npm dist-tags ls') t.matchSnapshot( @@ -133,7 +123,7 @@ test('ls on named package', (t) => { }) test('ls on missing package', (t) => { - prefix = t.testdir({}) + npm.prefix = t.testdir({}) distTag.exec(['ls', 'foo'], (err) => { t.matchSnapshot( log, @@ -150,7 +140,7 @@ test('ls on missing package', (t) => { }) test('ls on missing name in current package', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ version: '1.0.0', }), @@ -167,7 +157,7 @@ test('ls on missing name in current package', (t) => { }) test('only named package arg', (t) => { - prefix = t.testdir({}) + npm.prefix = t.testdir({}) distTag.exec(['@scoped/another'], (err) => { t.ifError(err, 'npm dist-tags ls') t.matchSnapshot( @@ -186,7 +176,7 @@ test('add new tag', (t) => { t.equal(opts.method, 'PUT', 'should trigger request to add new tag') t.equal(opts.body, '7.7.7', 'should point to expected version') } - prefix = t.testdir({}) + npm.prefix = t.testdir({}) distTag.exec(['add', '@scoped/another@7.7.7', 'c'], (err) => { t.ifError(err, 'npm dist-tags add') t.matchSnapshot( @@ -201,7 +191,7 @@ test('add new tag', (t) => { }) test('add using valid semver range as name', (t) => { - prefix = t.testdir({}) + npm.prefix = t.testdir({}) distTag.exec(['add', '@scoped/another@7.7.7', '1.0.0'], (err) => { t.match( err, @@ -219,7 +209,7 @@ test('add using valid semver range as name', (t) => { }) test('add missing args', (t) => { - prefix = t.testdir({}) + npm.prefix = t.testdir({}) distTag.exec(['add', '@scoped/another@7.7.7'], (err) => { t.matchSnapshot(err, 'should exit usage error message') result = '' @@ -229,7 +219,7 @@ test('add missing args', (t) => { }) test('add missing pkg name', (t) => { - prefix = t.testdir({}) + npm.prefix = t.testdir({}) distTag.exec(['add', null], (err) => { t.matchSnapshot(err, 'should exit usage error message') result = '' @@ -239,7 +229,7 @@ test('add missing pkg name', (t) => { }) test('set existing version', (t) => { - prefix = t.testdir({}) + npm.prefix = t.testdir({}) distTag.exec(['set', '@scoped/another@0.6.0', 'b'], (err) => { t.ifError(err, 'npm dist-tags set') t.matchSnapshot( @@ -256,7 +246,7 @@ test('remove existing tag', (t) => { npmRegistryFetchMock = async (url, opts) => { t.equal(opts.method, 'DELETE', 'should trigger request to remove tag') } - prefix = t.testdir({}) + npm.prefix = t.testdir({}) distTag.exec(['rm', '@scoped/another', 'c'], (err) => { t.ifError(err, 'npm dist-tags rm') t.matchSnapshot(log, 'should log remove info') @@ -269,7 +259,7 @@ test('remove existing tag', (t) => { }) test('remove non-existing tag', (t) => { - prefix = t.testdir({}) + npm.prefix = t.testdir({}) distTag.exec(['rm', '@scoped/another', 'nonexistent'], (err) => { t.match( err, @@ -284,7 +274,7 @@ test('remove non-existing tag', (t) => { }) test('remove missing pkg name', (t) => { - prefix = t.testdir({}) + npm.prefix = t.testdir({}) distTag.exec(['rm', null], (err) => { t.matchSnapshot(err, 'should exit usage error message') result = '' diff --git a/deps/npm/test/lib/exec.js b/deps/npm/test/lib/exec.js index eb9fef6a61..bcfe75577c 100644 --- a/deps/npm/test/lib/exec.js +++ b/deps/npm/test/lib/exec.js @@ -1,5 +1,6 @@ const t = require('tap') const requireInject = require('require-inject') +const mockNpm = require('../fixtures/mock-npm') const { resolve, delimiter } = require('path') const OUTPUT = [] const output = (...msg) => OUTPUT.push(msg) @@ -25,25 +26,23 @@ class Arborist { let PROGRESS_ENABLED = true const LOG_WARN = [] let PROGRESS_IGNORED = false -const npm = { - flatOptions: { - yes: true, - call: '', - package: [], - legacyPeerDeps: false, - shell: 'shell-cmd', - }, +const flatOptions = { + legacyPeerDeps: false, + package: [], +} +const config = { + cache: 'cache-dir', + yes: true, + call: '', + package: [], + shell: 'shell-cmd', +} +const npm = mockNpm({ + flatOptions, + config, localPrefix: 'local-prefix', localBin: 'local-bin', globalBin: 'global-bin', - config: { - get: k => { - if (k !== 'cache') - throw new Error('unexpected config get') - - return 'cache-dir' - }, - }, log: { disableProgress: () => { PROGRESS_ENABLED = false @@ -56,7 +55,7 @@ const npm = { }, }, output, -} +}) const RUN_SCRIPTS = [] const runScript = async opt => { @@ -108,9 +107,12 @@ t.afterEach(cb => { READ_ERROR = null LOG_WARN.length = 0 PROGRESS_IGNORED = false - npm.flatOptions.legacyPeerDeps = false - npm.flatOptions.package = [] - npm.flatOptions.call = '' + flatOptions.legacyPeerDeps = false + config.color = false + config.package = [] + flatOptions.package = [] + config.call = '' + config.yes = true npm.localBin = 'local-bin' npm.globalBin = 'global-bin' cb() @@ -186,7 +188,7 @@ t.test('npm exec foo, already present locally', t => { if (er) throw er t.strictSame(MKDIRPS, [], 'no need to make any dirs') - t.match(ARB_CTOR, [{ package: ['foo'], path }]) + t.match(ARB_CTOR, [{ path }]) t.strictSame(ARB_REIFY, [], 'no need to reify anything') t.equal(PROGRESS_ENABLED, true, 'progress re-enabled') t.match(RUN_SCRIPTS, [{ @@ -240,14 +242,27 @@ t.test('npm exec <noargs>, run interactive shell', t => { cb() }) } - t.test('print message when tty and not in CI', t => { CI_NAME = null process.stdin.isTTY = true run(t, true, () => { t.strictSame(LOG_WARN, []) t.strictSame(OUTPUT, [ - ['\nEntering npm script environment\nType \'exit\' or ^D when finished\n'], + [`\nEntering npm script environment at location:\n${process.cwd()}\nType 'exit' or ^D when finished\n`], + ], 'printed message about interactive shell') + t.end() + }) + }) + + t.test('print message with color when tty and not in CI', t => { + CI_NAME = null + process.stdin.isTTY = true + config.color = true + + run(t, true, () => { + t.strictSame(LOG_WARN, []) + t.strictSame(OUTPUT, [ + [`\u001b[0m\u001b[0m\n\u001b[0mEntering npm script environment\u001b[0m\u001b[0m at location:\u001b[0m\n\u001b[0m\u001b[2m${process.cwd()}\u001b[22m\u001b[0m\u001b[1m\u001b[22m\n\u001b[1mType 'exit' or ^D when finished\u001b[22m\n\u001b[1m\u001b[22m`], ], 'printed message about interactive shell') t.end() }) @@ -300,7 +315,7 @@ t.test('npm exec foo, not present locally or in central loc', t => { if (er) throw er t.strictSame(MKDIRPS, [installDir], 'need to make install dir') - t.match(ARB_CTOR, [{ package: ['foo'], path }]) + t.match(ARB_CTOR, [{ path }]) t.match(ARB_REIFY, [{add: ['foo@'], legacyPeerDeps: false}], 'need to install foo@') t.equal(PROGRESS_ENABLED, true, 'progress re-enabled') const PATH = `${resolve(installDir, 'node_modules', '.bin')}${delimiter}${process.env.PATH}` @@ -340,7 +355,7 @@ t.test('npm exec foo, not present locally but in central loc', t => { if (er) throw er t.strictSame(MKDIRPS, [installDir], 'need to make install dir') - t.match(ARB_CTOR, [{ package: ['foo'], path }]) + t.match(ARB_CTOR, [{ path }]) t.match(ARB_REIFY, [], 'no need to install again, already there') t.equal(PROGRESS_ENABLED, true, 'progress re-enabled') const PATH = `${resolve(installDir, 'node_modules', '.bin')}${delimiter}${process.env.PATH}` @@ -380,7 +395,7 @@ t.test('npm exec foo, present locally but wrong version', t => { if (er) throw er t.strictSame(MKDIRPS, [installDir], 'need to make install dir') - t.match(ARB_CTOR, [{ package: ['foo'], path }]) + t.match(ARB_CTOR, [{ path }]) t.match(ARB_REIFY, [{ add: ['foo@2.x'], legacyPeerDeps: false }], 'need to add foo@2.x') t.equal(PROGRESS_ENABLED, true, 'progress re-enabled') const PATH = `${resolve(installDir, 'node_modules', '.bin')}${delimiter}${process.env.PATH}` @@ -412,12 +427,13 @@ t.test('npm exec --package=foo bar', t => { }, _from: 'foo@', } - npm.flatOptions.package = ['foo'] + config.package = ['foo'] + flatOptions.package = ['foo'] exec.exec(['bar', 'one arg', 'two arg'], er => { if (er) throw er t.strictSame(MKDIRPS, [], 'no need to make any dirs') - t.match(ARB_CTOR, [{ package: ['foo'], path }]) + t.match(ARB_CTOR, [{ path }]) t.strictSame(ARB_REIFY, [], 'no need to reify anything') t.equal(PROGRESS_ENABLED, true, 'progress re-enabled') t.match(RUN_SCRIPTS, [{ @@ -459,7 +475,7 @@ t.test('npm exec @foo/bar -- --some=arg, locally installed', t => { if (er) throw er t.strictSame(MKDIRPS, [], 'no need to make any dirs') - t.match(ARB_CTOR, [{ package: ['@foo/bar'], path }]) + t.match(ARB_CTOR, [{ path }]) t.strictSame(ARB_REIFY, [], 'no need to reify anything') t.equal(PROGRESS_ENABLED, true, 'progress re-enabled') t.match(RUN_SCRIPTS, [{ @@ -502,7 +518,7 @@ t.test('npm exec @foo/bar, with same bin alias and no unscoped named bin, locall if (er) throw er t.strictSame(MKDIRPS, [], 'no need to make any dirs') - t.match(ARB_CTOR, [{ package: ['@foo/bar'], path }]) + t.match(ARB_CTOR, [{ path }]) t.strictSame(ARB_REIFY, [], 'no need to reify anything') t.equal(PROGRESS_ENABLED, true, 'progress re-enabled') t.match(RUN_SCRIPTS, [{ @@ -552,7 +568,7 @@ t.test('run command with 2 packages, need install, verify sort', t => { t.plan(cases.length) for (const packages of cases) { t.test(packages.join(', '), t => { - npm.flatOptions.package = packages + config.package = packages const add = packages.map(p => `${p}@`).sort((a, b) => a.localeCompare(b)) const path = t.testdir() const installDir = resolve('cache-dir/_npx/07de77790e5f40f2') @@ -583,7 +599,7 @@ t.test('run command with 2 packages, need install, verify sort', t => { if (er) throw er t.strictSame(MKDIRPS, [installDir], 'need to make install dir') - t.match(ARB_CTOR, [{ package: packages, path }]) + t.match(ARB_CTOR, [{ path }]) t.match(ARB_REIFY, [{add, legacyPeerDeps: false}], 'need to install both packages') t.equal(PROGRESS_ENABLED, true, 'progress re-enabled') const PATH = `${resolve(installDir, 'node_modules', '.bin')}${delimiter}${process.env.PATH}` @@ -652,8 +668,8 @@ t.test('npm exec foo, many bins in package, none named foo', t => { t.test('npm exec -p foo -c "ls -laF"', t => { const path = t.testdir() npm.localPrefix = path - npm.flatOptions.package = ['foo'] - npm.flatOptions.call = 'ls -laF' + config.package = ['foo'] + config.call = 'ls -laF' ARB_ACTUAL_TREE[path] = { children: new Map([['foo', { name: 'foo', version: '1.2.3' }]]), } @@ -666,7 +682,7 @@ t.test('npm exec -p foo -c "ls -laF"', t => { if (er) throw er t.strictSame(MKDIRPS, [], 'no need to make any dirs') - t.match(ARB_CTOR, [{ package: ['foo'], path }]) + t.match(ARB_CTOR, [{ path }]) t.strictSame(ARB_REIFY, [], 'no need to reify anything') t.equal(PROGRESS_ENABLED, true, 'progress re-enabled') t.match(RUN_SCRIPTS, [{ @@ -683,7 +699,7 @@ t.test('npm exec -p foo -c "ls -laF"', t => { }) t.test('positional args and --call together is an error', t => { - npm.flatOptions.call = 'true' + config.call = 'true' exec.exec(['foo'], er => { t.equal(er, exec.usage) t.end() @@ -705,8 +721,8 @@ t.test('prompt when installs are needed if not already present and shell is a TT const packages = ['foo', 'bar'] READ_RESULT = 'yolo' - npm.flatOptions.package = packages - npm.flatOptions.yes = undefined + config.package = packages + config.yes = undefined const add = packages.map(p => `${p}@`).sort((a, b) => a.localeCompare(b)) const path = t.testdir() @@ -738,7 +754,7 @@ t.test('prompt when installs are needed if not already present and shell is a TT if (er) throw er t.strictSame(MKDIRPS, [installDir], 'need to make install dir') - t.match(ARB_CTOR, [{ package: packages, path }]) + t.match(ARB_CTOR, [{ path }]) t.match(ARB_REIFY, [{add, legacyPeerDeps: false}], 'need to install both packages') t.equal(PROGRESS_ENABLED, true, 'progress re-enabled') const PATH = `${resolve(installDir, 'node_modules', '.bin')}${delimiter}${process.env.PATH}` @@ -774,8 +790,8 @@ t.test('skip prompt when installs are needed if not already present and shell is const packages = ['foo', 'bar'] READ_RESULT = 'yolo' - npm.flatOptions.package = packages - npm.flatOptions.yes = undefined + config.package = packages + config.yes = undefined const add = packages.map(p => `${p}@`).sort((a, b) => a.localeCompare(b)) const path = t.testdir() @@ -807,7 +823,7 @@ t.test('skip prompt when installs are needed if not already present and shell is if (er) throw er t.strictSame(MKDIRPS, [installDir], 'need to make install dir') - t.match(ARB_CTOR, [{ package: packages, path }]) + t.match(ARB_CTOR, [{ path }]) t.match(ARB_REIFY, [{add, legacyPeerDeps: false}], 'need to install both packages') t.equal(PROGRESS_ENABLED, true, 'progress re-enabled') const PATH = `${resolve(installDir, 'node_modules', '.bin')}${delimiter}${process.env.PATH}` @@ -841,8 +857,8 @@ t.test('skip prompt when installs are needed if not already present and shell is const packages = ['foo'] READ_RESULT = 'yolo' - npm.flatOptions.package = packages - npm.flatOptions.yes = undefined + config.package = packages + config.yes = undefined const add = packages.map(p => `${p}@`).sort((a, b) => a.localeCompare(b)) const path = t.testdir() @@ -866,7 +882,7 @@ t.test('skip prompt when installs are needed if not already present and shell is if (er) throw er t.strictSame(MKDIRPS, [installDir], 'need to make install dir') - t.match(ARB_CTOR, [{ package: packages, path }]) + t.match(ARB_CTOR, [{ path }]) t.match(ARB_REIFY, [{add, legacyPeerDeps: false}], 'need to install the package') t.equal(PROGRESS_ENABLED, true, 'progress re-enabled') const PATH = `${resolve(installDir, 'node_modules', '.bin')}${delimiter}${process.env.PATH}` @@ -900,8 +916,8 @@ t.test('abort if prompt rejected', t => { const packages = ['foo', 'bar'] READ_RESULT = 'no, why would I want such a thing??' - npm.flatOptions.package = packages - npm.flatOptions.yes = undefined + config.package = packages + config.yes = undefined const path = t.testdir() const installDir = resolve('cache-dir/_npx/07de77790e5f40f2') @@ -929,9 +945,9 @@ t.test('abort if prompt rejected', t => { _from: 'bar@', } exec.exec(['foobar'], er => { - t.equal(er, 'canceled', 'should be canceled') + t.match(er, /canceled/, 'should be canceled') t.strictSame(MKDIRPS, [installDir], 'need to make install dir') - t.match(ARB_CTOR, [{ package: packages, path }]) + t.match(ARB_CTOR, [{ path }]) t.strictSame(ARB_REIFY, [], 'no install performed') t.equal(PROGRESS_ENABLED, true, 'progress re-enabled') t.strictSame(RUN_SCRIPTS, []) @@ -958,8 +974,8 @@ t.test('abort if prompt false', t => { const packages = ['foo', 'bar'] READ_ERROR = 'canceled' - npm.flatOptions.package = packages - npm.flatOptions.yes = undefined + config.package = packages + config.yes = undefined const path = t.testdir() const installDir = resolve('cache-dir/_npx/07de77790e5f40f2') @@ -989,7 +1005,7 @@ t.test('abort if prompt false', t => { exec.exec(['foobar'], er => { t.equal(er, 'canceled', 'should be canceled') t.strictSame(MKDIRPS, [installDir], 'need to make install dir') - t.match(ARB_CTOR, [{ package: packages, path }]) + t.match(ARB_CTOR, [{ path }]) t.strictSame(ARB_REIFY, [], 'no install performed') t.equal(PROGRESS_ENABLED, true, 'progress re-enabled') t.strictSame(RUN_SCRIPTS, []) @@ -1015,8 +1031,8 @@ t.test('abort if -n provided', t => { const packages = ['foo', 'bar'] - npm.flatOptions.package = packages - npm.flatOptions.yes = false + config.package = packages + config.yes = false const path = t.testdir() const installDir = resolve('cache-dir/_npx/07de77790e5f40f2') @@ -1044,9 +1060,9 @@ t.test('abort if -n provided', t => { _from: 'bar@', } exec.exec(['foobar'], er => { - t.equal(er, 'canceled', 'should be canceled') + t.match(er, /canceled/, 'should be canceled') t.strictSame(MKDIRPS, [installDir], 'need to make install dir') - t.match(ARB_CTOR, [{ package: packages, path }]) + t.match(ARB_CTOR, [{ path }]) t.strictSame(ARB_REIFY, [], 'no install performed') t.equal(PROGRESS_ENABLED, true, 'progress re-enabled') t.strictSame(RUN_SCRIPTS, []) @@ -1073,8 +1089,8 @@ t.test('forward legacyPeerDeps opt', t => { }, _from: 'foo@', } - npm.flatOptions.yes = true - npm.flatOptions.legacyPeerDeps = true + config.yes = true + flatOptions.legacyPeerDeps = true exec.exec(['foo'], er => { if (er) throw er @@ -1082,3 +1098,93 @@ t.test('forward legacyPeerDeps opt', t => { t.done() }) }) + +t.test('workspaces', t => { + npm.localPrefix = t.testdir({ + node_modules: { + '.bin': { + foo: '', + }, + }, + packages: { + a: { + 'package.json': JSON.stringify({ + name: 'a', + version: '1.0.0', + bin: 'cli.js', + }), + 'cli.js': '', + }, + b: { + 'package.json': JSON.stringify({ + name: 'b', + version: '1.0.0', + }), + }, + }, + 'package.json': JSON.stringify({ + name: 'root', + version: '1.0.0', + workspaces: ['packages/*'], + }), + }) + + PROGRESS_IGNORED = true + npm.localBin = resolve(npm.localPrefix, 'node_modules/.bin') + + t.test('with args, run scripts in the context of a workspace', t => { + exec.execWorkspaces(['foo', 'one arg', 'two arg'], ['a', 'b'], er => { + if (er) + throw er + + t.match(RUN_SCRIPTS, [{ + pkg: { scripts: { npx: 'foo' }}, + args: ['one arg', 'two arg'], + banner: false, + path: process.cwd(), + stdioString: true, + event: 'npx', + env: { + PATH: [npm.localBin, ...PATH].join(delimiter), + }, + stdio: 'inherit', + }]) + t.end() + }) + }) + + t.test('no args, spawn interactive shell', async t => { + CI_NAME = null + process.stdin.isTTY = true + + await new Promise((res, rej) => { + exec.execWorkspaces([], ['a'], er => { + if (er) + return rej(er) + + t.strictSame(LOG_WARN, []) + t.strictSame(OUTPUT, [ + [`\nEntering npm script environment in workspace a@1.0.0 at location:\n${resolve(npm.localPrefix, 'packages/a')}\nType 'exit' or ^D when finished\n`], + ], 'printed message about interactive shell') + res() + }) + }) + + config.color = true + OUTPUT.length = 0 + await new Promise((res, rej) => { + exec.execWorkspaces([], ['a'], er => { + if (er) + return rej(er) + + t.strictSame(LOG_WARN, []) + t.strictSame(OUTPUT, [ + [`\u001b[0m\u001b[0m\n\u001b[0mEntering npm script environment\u001b[0m\u001b[0m in workspace \u001b[32ma@1.0.0\u001b[39m at location:\u001b[0m\n\u001b[0m\u001b[2m${resolve(npm.localPrefix, 'packages/a')}\u001b[22m\u001b[0m\u001b[1m\u001b[22m\n\u001b[1mType 'exit' or ^D when finished\u001b[22m\n\u001b[1m\u001b[22m`], + ], 'printed message about interactive shell') + res() + }) + }) + }) + + t.end() +}) diff --git a/deps/npm/test/lib/fund.js b/deps/npm/test/lib/fund.js index 2ae604a653..8c10007844 100644 --- a/deps/npm/test/lib/fund.js +++ b/deps/npm/test/lib/fund.js @@ -1,5 +1,6 @@ const { test } = require('tap') const requireInject = require('require-inject') +const mockNpm = require('../fixtures/mock-npm') const version = '1.0.0' const funding = { @@ -180,19 +181,18 @@ const conflictingFundingPackages = { let result = '' let printUrl = '' -const _flatOptions = { +const config = { color: false, json: false, global: false, - prefix: undefined, unicode: false, - which: undefined, + which: null, } const openUrl = async (npm, url, msg) => { if (url === 'http://npmjs.org') throw new Error('ERROR') - if (_flatOptions.json) { + if (config.json) { printUrl = JSON.stringify({ title: msg, url: url, @@ -210,18 +210,16 @@ const Fund = requireInject('../../lib/fund.js', { : Promise.reject(new Error('ERROR')), }, }) -const fund = new Fund({ - flatOptions: _flatOptions, - get prefix () { - return _flatOptions.prefix - }, +const npm = mockNpm({ + config, output: msg => { result += msg + '\n' }, }) +const fund = new Fund(npm) test('fund with no package containing funding', t => { - _flatOptions.prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'no-funding-package', version: '0.0.0', @@ -237,7 +235,7 @@ test('fund with no package containing funding', t => { }) test('fund in which same maintainer owns all its deps', t => { - _flatOptions.prefix = t.testdir(maintainerOwnsAllDeps) + npm.prefix = t.testdir(maintainerOwnsAllDeps) fund.exec([], (err) => { t.ifError(err, 'should not error out') @@ -248,8 +246,8 @@ test('fund in which same maintainer owns all its deps', t => { }) test('fund in which same maintainer owns all its deps, using --json option', t => { - _flatOptions.json = true - _flatOptions.prefix = t.testdir(maintainerOwnsAllDeps) + config.json = true + npm.prefix = t.testdir(maintainerOwnsAllDeps) fund.exec([], (err) => { t.ifError(err, 'should not error out') @@ -281,13 +279,13 @@ test('fund in which same maintainer owns all its deps, using --json option', t = ) result = '' - _flatOptions.json = false + config.json = false t.end() }) }) test('fund containing multi-level nested deps with no funding', t => { - _flatOptions.prefix = t.testdir(nestedNoFundingPackages) + npm.prefix = t.testdir(nestedNoFundingPackages) fund.exec([], (err) => { t.ifError(err, 'should not error out') @@ -302,8 +300,8 @@ test('fund containing multi-level nested deps with no funding', t => { }) test('fund containing multi-level nested deps with no funding, using --json option', t => { - _flatOptions.prefix = t.testdir(nestedNoFundingPackages) - _flatOptions.json = true + npm.prefix = t.testdir(nestedNoFundingPackages) + config.json = true fund.exec([], (err) => { t.ifError(err, 'should not error out') @@ -328,14 +326,14 @@ test('fund containing multi-level nested deps with no funding, using --json opti ) result = '' - _flatOptions.json = false + config.json = false t.end() }) }) test('fund containing multi-level nested deps with no funding, using --json option', t => { - _flatOptions.prefix = t.testdir(nestedMultipleFundingPackages) - _flatOptions.json = true + npm.prefix = t.testdir(nestedMultipleFundingPackages) + config.json = true fund.exec([], (err) => { t.ifError(err, 'should not error out') @@ -385,26 +383,26 @@ test('fund containing multi-level nested deps with no funding, using --json opti ) result = '' - _flatOptions.json = false + config.json = false t.end() }) }) test('fund does not support global', t => { - _flatOptions.prefix = t.testdir({}) - _flatOptions.global = true + npm.prefix = t.testdir({}) + config.global = true fund.exec([], (err) => { t.match(err.code, 'EFUNDGLOBAL', 'should throw EFUNDGLOBAL error') result = '' - _flatOptions.global = false + config.global = false t.end() }) }) test('fund using package argument', t => { - _flatOptions.prefix = t.testdir(maintainerOwnsAllDeps) + npm.prefix = t.testdir(maintainerOwnsAllDeps) fund.exec(['.'], (err) => { t.ifError(err, 'should not error out') @@ -416,9 +414,9 @@ test('fund using package argument', t => { }) test('fund does not support global, using --json option', t => { - _flatOptions.prefix = t.testdir({}) - _flatOptions.global = true - _flatOptions.json = true + npm.prefix = t.testdir({}) + config.global = true + config.json = true fund.exec([], (err) => { t.equal(err.code, 'EFUNDGLOBAL', 'should use EFUNDGLOBAL error code') @@ -428,14 +426,14 @@ test('fund does not support global, using --json option', t => { 'should use expected error msg' ) - _flatOptions.global = false - _flatOptions.json = false + config.global = false + config.json = false t.end() }) }) test('fund using string shorthand', t => { - _flatOptions.prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'funding-string-shorthand', version: '0.0.0', @@ -453,7 +451,7 @@ test('fund using string shorthand', t => { }) test('fund using nested packages with multiple sources', t => { - _flatOptions.prefix = t.testdir(nestedMultipleFundingPackages) + npm.prefix = t.testdir(nestedMultipleFundingPackages) fund.exec(['.'], (err) => { t.ifError(err, 'should not error out') @@ -465,7 +463,7 @@ test('fund using nested packages with multiple sources', t => { }) test('fund using symlink ref', t => { - _flatOptions.prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'using-symlink-ref', version: '1.0.0', @@ -511,7 +509,7 @@ test('fund using symlink ref', t => { }) test('fund using data from actual tree', t => { - _flatOptions.prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'using-actual-tree', version: '1.0.0', @@ -558,22 +556,22 @@ test('fund using data from actual tree', t => { }) test('fund using nested packages with multiple sources, with a source number', t => { - _flatOptions.prefix = t.testdir(nestedMultipleFundingPackages) - _flatOptions.which = '1' + npm.prefix = t.testdir(nestedMultipleFundingPackages) + config.which = '1' fund.exec(['.'], (err) => { t.ifError(err, 'should not error out') t.matchSnapshot(printUrl, 'should open the numbered URL') - _flatOptions.which = undefined + config.which = null printUrl = '' t.end() }) }) test('fund using pkg name while having conflicting versions', t => { - _flatOptions.prefix = t.testdir(conflictingFundingPackages) - _flatOptions.which = '1' + npm.prefix = t.testdir(conflictingFundingPackages) + config.which = '1' fund.exec(['foo'], (err) => { t.ifError(err, 'should not error out') @@ -585,8 +583,8 @@ test('fund using pkg name while having conflicting versions', t => { }) test('fund using package argument with no browser, using --json option', t => { - _flatOptions.prefix = t.testdir(maintainerOwnsAllDeps) - _flatOptions.json = true + npm.prefix = t.testdir(maintainerOwnsAllDeps) + config.json = true fund.exec(['.'], (err) => { t.ifError(err, 'should not error out') @@ -599,14 +597,14 @@ test('fund using package argument with no browser, using --json option', t => { 'should open funding url using json output' ) - _flatOptions.json = false + config.json = false printUrl = '' t.end() }) }) test('fund using package info fetch from registry', t => { - _flatOptions.prefix = t.testdir({}) + npm.prefix = t.testdir({}) fund.exec(['ntl'], (err) => { t.ifError(err, 'should not error out') @@ -622,7 +620,7 @@ test('fund using package info fetch from registry', t => { }) test('fund tries to use package info fetch from registry but registry has nothing', t => { - _flatOptions.prefix = t.testdir({}) + npm.prefix = t.testdir({}) fund.exec(['foo'], (err) => { t.equal(err.code, 'ENOFUND', 'should have ENOFUND error code') @@ -638,7 +636,7 @@ test('fund tries to use package info fetch from registry but registry has nothin }) test('fund but target module has no funding info', t => { - _flatOptions.prefix = t.testdir(nestedNoFundingPackages) + npm.prefix = t.testdir(nestedNoFundingPackages) fund.exec(['foo'], (err) => { t.equal(err.code, 'ENOFUND', 'should have ENOFUND error code') @@ -654,8 +652,8 @@ test('fund but target module has no funding info', t => { }) test('fund using bad which value', t => { - _flatOptions.prefix = t.testdir(nestedMultipleFundingPackages) - _flatOptions.which = 3 + npm.prefix = t.testdir(nestedMultipleFundingPackages) + config.which = 3 fund.exec(['bar'], (err) => { t.equal(err.code, 'EFUNDNUMBER', 'should have EFUNDNUMBER error code') @@ -665,14 +663,14 @@ test('fund using bad which value', t => { 'should have bad which option error message' ) - _flatOptions.which = undefined + config.which = null result = '' t.end() }) }) test('fund pkg missing version number', t => { - _flatOptions.prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'foo', funding: 'http://example.com/foo', @@ -688,7 +686,7 @@ test('fund pkg missing version number', t => { }) test('fund a package throws on openUrl', t => { - _flatOptions.prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'foo', version: '1.0.0', @@ -704,7 +702,7 @@ test('fund a package throws on openUrl', t => { }) test('fund a package with type and multiple sources', t => { - _flatOptions.prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'foo', funding: [ @@ -730,7 +728,7 @@ test('fund a package with type and multiple sources', t => { }) test('fund colors', t => { - _flatOptions.prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-fund-colors', version: '1.0.0', @@ -782,20 +780,20 @@ test('fund colors', t => { }, }, }) - _flatOptions.color = true + npm.color = true fund.exec([], (err) => { t.ifError(err, 'should not error out') t.matchSnapshot(result, 'should print output with color info') result = '' - _flatOptions.color = false + npm.color = false t.end() }) }) test('sub dep with fund info and a parent with no funding info', t => { - _flatOptions.prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-multiple-funding-sources', version: '1.0.0', diff --git a/deps/npm/test/lib/help-search.js b/deps/npm/test/lib/help-search.js index 6228f5ca97..567097a2eb 100644 --- a/deps/npm/test/lib/help-search.js +++ b/deps/npm/test/lib/help-search.js @@ -1,6 +1,7 @@ const { test } = require('tap') const { join } = require('path') const requireInject = require('require-inject') +const mockNpm = require('../fixtures/mock-npm') const ansicolors = require('ansicolors') const OUTPUT = [] @@ -8,26 +9,24 @@ const output = (msg) => { OUTPUT.push(msg) } -let npmHelpArgs = null -let npmHelpErr = null -const npm = { +const config = { + long: false, +} +const npmHelpErr = null +const npm = mockNpm({ color: false, + config, flatOptions: { long: false, }, + usage: 'npm test usage', commands: { help: (args, cb) => { - npmHelpArgs = args return cb(npmHelpErr) }, }, output, -} - -let npmUsageArg = null -const npmUsage = (npm, arg) => { - npmUsageArg = arg -} +}) let globRoot = null const globDir = { @@ -45,7 +44,6 @@ const glob = (p, cb) => cb(null, Object.keys(globDir).map((file) => join(globRoot, file))) const HelpSearch = requireInject('../../lib/help-search.js', { - '../../lib/utils/npm-usage.js': npmUsage, glob, }) const helpSearch = new HelpSearch(npm) @@ -61,8 +59,7 @@ test('npm help-search', t => { if (err) throw err - t.match(OUTPUT, /Top hits for/, 'outputs results') - t.match(OUTPUT, /Did you mean this\?\n\s+exec/, 'matched command, so suggest it') + t.match(OUTPUT, /Top hits for "exec"/, 'outputs results') t.end() }) }) @@ -84,46 +81,12 @@ test('npm help-search multiple terms', t => { }) }) -test('npm help-search single result prints full section', t => { - globRoot = t.testdir(globDir) - t.teardown(() => { - OUTPUT.length = 0 - npmHelpArgs = null - globRoot = null - }) - - return helpSearch.exec(['does not exist in'], (err) => { - if (err) - throw err - - t.strictSame(npmHelpArgs, ['npm-install'], 'identified the correct man page and called help with it') - t.end() - }) -}) - -test('npm help-search single result propagates error', t => { - globRoot = t.testdir(globDir) - npmHelpErr = new Error('help broke') - t.teardown(() => { - OUTPUT.length = 0 - npmHelpArgs = null - npmHelpErr = null - globRoot = null - }) - - return helpSearch.exec(['does not exist in'], (err) => { - t.strictSame(npmHelpArgs, ['npm-install'], 'identified the correct man page and called help with it') - t.match(err, /help broke/, 'propagated the error from help') - t.end() - }) -}) - test('npm help-search long output', t => { globRoot = t.testdir(globDir) - npm.flatOptions.long = true + config.long = true t.teardown(() => { OUTPUT.length = 0 - npm.flatOptions.long = false + config.long = false globRoot = null }) @@ -138,11 +101,11 @@ test('npm help-search long output', t => { test('npm help-search long output with color', t => { globRoot = t.testdir(globDir) - npm.flatOptions.long = true + config.long = true npm.color = true t.teardown(() => { OUTPUT.length = 0 - npm.flatOptions.long = false + config.long = false npm.color = false globRoot = null }) @@ -159,7 +122,8 @@ test('npm help-search long output with color', t => { test('npm help-search no args', t => { return helpSearch.exec([], (err) => { - t.match(err, /npm help-search/, 'throws usage') + t.notOk(err) + t.match(OUTPUT, /npm help-search/, 'outputs usage') t.end() }) }) @@ -168,7 +132,6 @@ test('npm help-search no matches', t => { globRoot = t.testdir(globDir) t.teardown(() => { OUTPUT.length = 0 - npmUsageArg = null globRoot = null }) @@ -176,7 +139,7 @@ test('npm help-search no matches', t => { if (err) throw err - t.equal(npmUsageArg, false, 'called npmUsage for no matches') + t.match(OUTPUT, /No matches/) t.end() }) }) diff --git a/deps/npm/test/lib/help.js b/deps/npm/test/lib/help.js index ae2f7e99da..ccf13a7e46 100644 --- a/deps/npm/test/lib/help.js +++ b/deps/npm/test/lib/help.js @@ -2,11 +2,6 @@ const { test } = require('tap') const requireInject = require('require-inject') const { EventEmitter } = require('events') -let npmUsageArg = null -const npmUsage = (npm, arg) => { - npmUsageArg = arg -} - const npmConfig = { usage: false, viewer: undefined, @@ -16,6 +11,7 @@ const npmConfig = { let helpSearchArgs = null const OUTPUT = [] const npm = { + usage: 'test npm usage', config: { get: (key) => npmConfig[key], set: (key, value) => { @@ -48,7 +44,9 @@ const globDefaults = [ let globErr = null let globResult = globDefaults +let globParam const glob = (p, cb) => { + globParam = p return cb(globErr, globResult) } @@ -71,7 +69,6 @@ const openUrl = async (npm, url, msg) => { } const Help = requireInject('../../lib/help.js', { - '../../lib/utils/npm-usage.js': npmUsage, '../../lib/utils/open-url.js': openUrl, child_process: { spawn, @@ -81,15 +78,11 @@ const Help = requireInject('../../lib/help.js', { const help = new Help(npm) test('npm help', t => { - t.teardown(() => { - npmUsageArg = null - }) - return help.exec([], (err) => { if (err) throw err - t.equal(npmUsageArg, false, 'called npmUsage') + t.match(OUTPUT, ['test npm usage'], 'showed npm usage') t.end() }) }) @@ -107,22 +100,6 @@ test('npm help completion', async t => { t.rejects(help.completion({ conf: { argv: { remain: [] } } }), /glob failed/, 'glob errors propagate') }) -test('npm help -h', t => { - npmConfig.usage = true - t.teardown(() => { - npmConfig.usage = false - OUTPUT.length = 0 - }) - - return help.exec(['help'], (err) => { - if (err) - throw err - - t.strictSame(OUTPUT, ['npm help <term>'], 'outputs usage information for command') - t.end() - }) -}) - test('npm help multiple args calls search', t => { t.teardown(() => { helpSearchArgs = null @@ -180,7 +157,7 @@ test('npm help whoami', t => { throw err t.equal(spawnBin, 'man', 'calls man by default') - t.strictSame(spawnArgs, ['1', 'npm-whoami'], 'passes the correct arguments') + t.strictSame(spawnArgs, [globResult[0]], 'passes the correct arguments') t.end() }) }) @@ -212,12 +189,12 @@ test('npm help 5 install', t => { npmConfig.viewer = 'browser' globResult = [ '/root/man/man5/install.5', - '/root/man/man1/npm-install.1', ] t.teardown(() => { npmConfig.viewer = undefined globResult = globDefaults + globParam = null spawnBin = null spawnArgs = null }) @@ -226,6 +203,7 @@ test('npm help 5 install', t => { if (err) throw err + t.match(globParam, /man5/, 'searches only in man5 folder') t.match(openUrlArg, /configuring-npm(\/|\\)install.html$/, 'attempts to open the correct url') t.end() }) @@ -234,11 +212,11 @@ test('npm help 5 install', t => { test('npm help 7 config', t => { npmConfig.viewer = 'browser' globResult = [ - '/root/man/man1/npm-config.1', '/root/man/man7/config.7', ] t.teardown(() => { npmConfig.viewer = undefined + globParam = null globResult = globDefaults spawnBin = null spawnArgs = null @@ -248,49 +226,12 @@ test('npm help 7 config', t => { if (err) throw err + t.match(globParam, /man7/, 'searches only in man5 folder') t.match(openUrlArg, /using-npm(\/|\\)config.html$/, 'attempts to open the correct url') t.end() }) }) -test('npm help with browser viewer and invalid section throws', t => { - npmConfig.viewer = 'browser' - globResult = [ - '/root/man/man1/npm-config.1', - '/root/man/man7/config.7', - '/root/man/man9/config.9', - ] - t.teardown(() => { - npmConfig.viewer = undefined - globResult = globDefaults - spawnBin = null - spawnArgs = null - }) - - return help.exec(['9', 'config'], (err) => { - t.match(err, /invalid man section: 9/, 'throws appropriate error') - t.end() - }) -}) - -test('npm help global redirects to folders', t => { - globResult = ['/root/man/man5/folders.5'] - t.teardown(() => { - globResult = globDefaults - spawnBin = null - spawnArgs = null - }) - - return help.exec(['global'], (err) => { - if (err) - throw err - - t.equal(spawnBin, 'man', 'calls man by default') - t.strictSame(spawnArgs, ['5', 'folders'], 'passes the correct arguments') - t.end() - }) -}) - test('npm help package.json redirects to package-json', t => { globResult = ['/root/man/man5/package-json.5'] t.teardown(() => { @@ -304,7 +245,8 @@ test('npm help package.json redirects to package-json', t => { throw err t.equal(spawnBin, 'man', 'calls man by default') - t.strictSame(spawnArgs, ['5', 'package-json'], 'passes the correct arguments') + t.match(globParam, /package-json/, 'glob was asked to find package-json') + t.strictSame(spawnArgs, [globResult[0]], 'passes the correct arguments') t.end() }) }) @@ -327,7 +269,7 @@ test('npm help ?(un)star', t => { throw err t.equal(spawnBin, 'emacsclient', 'maps woman to emacs correctly') - t.strictSame(spawnArgs, ['-e', `(woman-find-file '/root/man/man1/npm-unstar.1')`], 'passes the correct arguments') + t.strictSame(spawnArgs, ['-e', `(woman-find-file '/root/man/man1/npm-star.1')`], 'passes the correct arguments') t.end() }) }) @@ -350,7 +292,7 @@ test('npm help - woman viewer propagates errors', t => { return help.exec(['?(un)star'], (err) => { t.match(err, /help process exited with code: 1/, 'received the correct error') t.equal(spawnBin, 'emacsclient', 'maps woman to emacs correctly') - t.strictSame(spawnArgs, ['-e', `(woman-find-file '/root/man/man1/npm-unstar.1')`], 'passes the correct arguments') + t.strictSame(spawnArgs, ['-e', `(woman-find-file '/root/man/man1/npm-star.1')`], 'passes the correct arguments') t.end() }) }) @@ -372,7 +314,7 @@ test('npm help un*', t => { throw err t.equal(spawnBin, 'man', 'calls man by default') - t.strictSame(spawnArgs, ['1', 'npm-unstar'], 'passes the correct arguments') + t.strictSame(spawnArgs, ['/root/man/man1/npm-uninstall.1'], 'passes the correct arguments') t.end() }) }) @@ -394,7 +336,7 @@ test('npm help - man viewer propagates errors', t => { return help.exec(['un*'], (err) => { t.match(err, /help process exited with code: 1/, 'received correct error') t.equal(spawnBin, 'man', 'calls man by default') - t.strictSame(spawnArgs, ['1', 'npm-unstar'], 'passes the correct arguments') + t.strictSame(spawnArgs, ['/root/man/man1/npm-uninstall.1'], 'passes the correct arguments') t.end() }) }) diff --git a/deps/npm/test/lib/init.js b/deps/npm/test/lib/init.js index 8b9f32e156..2b212f4a15 100644 --- a/deps/npm/test/lib/init.js +++ b/deps/npm/test/lib/init.js @@ -1,5 +1,6 @@ const t = require('tap') const requireInject = require('require-inject') +const mockNpm = require('../fixtures/mock-npm') let result = '' const npmLog = { @@ -10,14 +11,17 @@ const npmLog = { resume: () => null, silly: () => null, } -const npm = { - config: { set () {} }, - flatOptions: {}, +const config = { + 'init-module': '~/.npm-init.js', +} +const npm = mockNpm({ + config, log: npmLog, + commands: {}, output: (...msg) => { result += msg.join('\n') }, -} +}) const mocks = { 'init-package-json': (dir, initFile, config, cb) => cb(null, 'data'), '../../lib/utils/usage.js': () => 'usage instructions', @@ -27,19 +31,13 @@ const init = new Init(npm) t.afterEach(cb => { result = '' - npm.config = { get: () => '', set () {} } + config.package = undefined npm.commands = {} - Object.defineProperty(npm, 'flatOptions', { value: {} }) npm.log = npmLog cb() }) t.test('classic npm init no args', t => { - npm.config = { - get () { - return '~/.npm-init.js' - }, - } init.exec([], err => { t.ifError(err, 'npm init no args') t.matchSnapshot(result, 'should print helper info') @@ -49,9 +47,7 @@ t.test('classic npm init no args', t => { t.test('classic npm init -y', t => { t.plan(7) - npm.config = { - get: () => '~/.npm-init.js', - } + config.yes = true Object.defineProperty(npm, 'flatOptions', { value: { yes: true} }) npm.log = { ...npm.log } npm.log.silly = (title, msg) => { @@ -72,14 +68,9 @@ t.test('classic npm init -y', t => { }) t.test('npm init <arg>', t => { - t.plan(4) - npm.config = { - set (key, val) { - t.equal(key, 'package', 'should set package key') - t.deepEqual(val, [], 'should set empty array value') - }, - } + t.plan(3) npm.commands.exec = (arr, cb) => { + t.deepEqual(config.package, [], 'should set empty array value') t.deepEqual( arr, ['create-react-app'], @@ -178,20 +169,9 @@ t.test('npm init exec error', t => { }) t.test('should not rewrite flatOptions', t => { - t.plan(4) - Object.defineProperty(npm, 'flatOptions', { - get: () => ({}), - set () { - throw new Error('Should not set flatOptions') - }, - }) - npm.config = { - set (key, val) { - t.equal(key, 'package', 'should set package key') - t.deepEqual(val, [], 'should set empty array value') - }, - } + t.plan(3) npm.commands.exec = (arr, cb) => { + t.deepEqual(config.package, [], 'should set empty array value') t.deepEqual( arr, ['create-react-app', 'my-app'], diff --git a/deps/npm/test/lib/install.js b/deps/npm/test/lib/install.js index 8b7a968511..b44452a69c 100644 --- a/deps/npm/test/lib/install.js +++ b/deps/npm/test/lib/install.js @@ -2,6 +2,7 @@ const { test } = require('tap') const Install = require('../../lib/install.js') const requireInject = require('require-inject') +const mockNpm = require('../fixtures/mock-npm') test('should install using Arborist', (t) => { const SCRIPTS = [] @@ -28,16 +29,14 @@ test('should install using Arborist', (t) => { throw new Error('got wrong object passed to reify-finish') }, }) - const install = new Install({ + + const npm = mockNpm({ + config: { dev: true }, + flatOptions: { global: false }, globalDir: 'path/to/node_modules/', prefix: 'foo', - flatOptions: { - global: false, - }, - config: { - get: () => true, - }, }) + const install = new Install(npm) t.test('with args', t => { install.exec(['fizzbuzz'], er => { @@ -86,17 +85,16 @@ test('should ignore scripts with --ignore-scripts', (t) => { } }, }) - const install = new Install({ + const npm = mockNpm({ globalDir: 'path/to/node_modules/', prefix: 'foo', - flatOptions: { - global: false, - ignoreScripts: true, - }, + flatOptions: { global: false }, config: { - get: () => false, + global: false, + 'ignore-scripts': true, }, }) + const install = new Install(npm) install.exec([], er => { if (er) throw er @@ -113,16 +111,13 @@ test('should install globally using Arborist', (t) => { this.reify = () => {} }, }) - const install = new Install({ + const npm = mockNpm({ globalDir: 'path/to/node_modules/', prefix: 'foo', - flatOptions: { - global: true, - }, - config: { - get: () => false, - }, + config: { global: true }, + flatOptions: { global: true }, }) + const install = new Install(npm) install.exec([], er => { if (er) throw er diff --git a/deps/npm/test/lib/link.js b/deps/npm/test/lib/link.js index be7af3f524..0d96ba0bcd 100644 --- a/deps/npm/test/lib/link.js +++ b/deps/npm/test/lib/link.js @@ -3,6 +3,7 @@ const { resolve } = require('path') const Arborist = require('@npmcli/arborist') const t = require('tap') const requireInject = require('require-inject') +const mockNpm = require('../fixtures/mock-npm') const redactCwd = (path) => { const normalizePath = p => p @@ -15,17 +16,13 @@ const redactCwd = (path) => { t.cleanSnapshot = (str) => redactCwd(str) let reifyOutput -const npm = { +const config = {} +const npm = mockNpm({ globalDir: null, prefix: null, - flatOptions: {}, - config: { - get () { - return false - }, - find () {}, - }, -} + config, +}) + const printLinks = async (opts) => { let res = '' const arb = new Arborist(opts) diff --git a/deps/npm/test/lib/load-all-commands.js b/deps/npm/test/lib/load-all-commands.js index e31a2b9936..d7eb2eae0a 100644 --- a/deps/npm/test/lib/load-all-commands.js +++ b/deps/npm/test/lib/load-all-commands.js @@ -1,27 +1,37 @@ -// Thanks to nyc not working properly with proxies this -// doesn't affect coverage. but it does ensure that every command has a usage -// that contains its name, and if it has completion it is a function -const npm = require('../../lib/npm.js') +// Thanks to nyc not working properly with proxies this doesn't affect +// coverage. but it does ensure that every command has a usage that renders, +// contains its name, a description, and if it has completion it is a function. +// That it renders also ensures that any params we've defined in our commands +// work. +const requireInject = require('require-inject') +const npm = requireInject('../../lib/npm.js') const t = require('tap') const { cmdList } = require('../../lib/utils/cmd-list.js') -t.test('load npm', t => npm.load(er => { - if (er) - throw er -})) - +let npmOutput = [] +npm.output = (msg) => { + npmOutput = msg +} t.test('load each command', t => { - t.plan(cmdList.length) - for (const cmd of cmdList.sort((a, b) => a.localeCompare(b))) { - t.test(cmd, t => { - const impl = npm.commands[cmd] - if (impl.completion) { - t.plan(3) - t.isa(impl.completion, 'function', 'completion, if present, is a function') - } else - t.plan(2) - t.isa(impl, 'function', 'implementation is a function') - t.match(impl.usage, cmd, 'usage contains the command') - }) - } + t.plan(cmdList.length + 1) + npm.load((er) => { + t.notOk(er) + npm.config.set('usage', true) + for (const cmd of cmdList.sort((a, b) => a.localeCompare(b))) { + t.test(cmd, t => { + const impl = npm.commands[cmd] + if (impl.completion) + t.isa(impl.completion, 'function', 'completion, if present, is a function') + t.isa(impl, 'function', 'implementation is a function') + t.ok(impl.description, 'implementation has a description') + t.ok(impl.name, 'implementation has a name') + t.match(impl.usage, cmd, 'usage contains the command') + impl([], (err) => { + t.notOk(err) + t.match(npmOutput, impl.usage, 'usage is output') + t.end() + }) + }) + } + }) }) diff --git a/deps/npm/test/lib/logout.js b/deps/npm/test/lib/logout.js index b00fa641d8..bae797f969 100644 --- a/deps/npm/test/lib/logout.js +++ b/deps/npm/test/lib/logout.js @@ -1,12 +1,17 @@ const requireInject = require('require-inject') +const mockNpm = require('../fixtures/mock-npm') const { test } = require('tap') -const _flatOptions = { +const config = { registry: 'https://registry.npmjs.org/', scope: '', } +const flatOptions = { + registry: 'https://registry.npmjs.org/', + scope: '', +} +const npm = mockNpm({ config, flatOptions }) -const config = {} const npmlog = {} let result = null @@ -20,15 +25,12 @@ const mocks = { } const Logout = requireInject('../../lib/logout.js', mocks) -const logout = new Logout({ - flatOptions: _flatOptions, - config, -}) +const logout = new Logout(npm) test('token logout', async (t) => { t.plan(6) - _flatOptions.token = '@foo/' + flatOptions.token = '@foo/' npmlog.verbose = (title, msg) => { t.equal(title, 'logout', 'should have correcct log prefix') @@ -39,7 +41,7 @@ test('token logout', async (t) => { ) } - config.clearCredentialsByURI = (registry) => { + npm.config.clearCredentialsByURI = (registry) => { t.equal( registry, 'https://registry.npmjs.org/', @@ -47,7 +49,7 @@ test('token logout', async (t) => { ) } - config.save = (type) => { + npm.config.save = (type) => { t.equal(type, 'user', 'should save to user config') } @@ -70,7 +72,7 @@ test('token logout', async (t) => { 'should call npm-registry-fetch with expected values' ) - delete _flatOptions.token + delete flatOptions.token result = null mocks['npm-registry-fetch'] = null config.clearCredentialsByURI = null @@ -86,9 +88,11 @@ test('token logout', async (t) => { test('token scoped logout', async (t) => { t.plan(8) - _flatOptions.token = '@foo/' - _flatOptions.scope = '@myscope' - _flatOptions['@myscope:registry'] = 'https://diff-registry.npmjs.com/' + flatOptions.token = '@foo/' + config.scope = '@myscope' + config['@myscope:registry'] = 'https://diff-registry.npmjs.com/' + flatOptions.scope = '@myscope' + flatOptions['@myscope:registry'] = 'https://diff-registry.npmjs.com/' npmlog.verbose = (title, msg) => { t.equal(title, 'logout', 'should have correcct log prefix') @@ -99,7 +103,7 @@ test('token scoped logout', async (t) => { ) } - config.clearCredentialsByURI = (registry) => { + npm.config.clearCredentialsByURI = (registry) => { t.equal( registry, 'https://diff-registry.npmjs.com/', @@ -107,7 +111,7 @@ test('token scoped logout', async (t) => { ) } - config.delete = (ref, type) => { + npm.config.delete = (ref, type) => { t.equal( ref, '@myscope:registry', @@ -116,7 +120,7 @@ test('token scoped logout', async (t) => { t.equal(type, 'user', 'should delete from user config') } - config.save = (type) => { + npm.config.save = (type) => { t.equal(type, 'user', 'should save to user config') } @@ -140,9 +144,9 @@ test('token scoped logout', async (t) => { 'should call npm-registry-fetch with expected values' ) - _flatOptions.scope = '' - delete _flatOptions['@myscope:registry'] - delete _flatOptions.token + config.scope = '' + delete config['@myscope:registry'] + delete flatOptions.token result = null mocks['npm-registry-fetch'] = null config.clearCredentialsByURI = null @@ -158,8 +162,8 @@ test('token scoped logout', async (t) => { test('user/pass logout', async (t) => { t.plan(3) - _flatOptions.username = 'foo' - _flatOptions.password = 'bar' + flatOptions.username = 'foo' + flatOptions.password = 'bar' npmlog.verbose = (title, msg) => { t.equal(title, 'logout', 'should have correcct log prefix') @@ -170,17 +174,17 @@ test('user/pass logout', async (t) => { ) } - config.clearCredentialsByURI = () => null - config.save = () => null + npm.config.clearCredentialsByURI = () => null + npm.config.save = () => null await new Promise((res, rej) => { logout.exec([], (err) => { t.ifError(err, 'should not error out') - delete _flatOptions.username - delete _flatOptions.password - config.clearCredentialsByURI = null - config.save = null + delete flatOptions.username + delete flatOptions.password + npm.config.clearCredentialsByURI = null + npm.config.save = null npmlog.verbose = null res() @@ -203,9 +207,9 @@ test('missing credentials', (t) => { test('ignore invalid scoped registry config', async (t) => { t.plan(5) - _flatOptions.token = '@foo/' - _flatOptions.scope = '@myscope' - _flatOptions['@myscope:registry'] = '' + flatOptions.token = '@foo/' + config.scope = '@myscope' + flatOptions['@myscope:registry'] = '' npmlog.verbose = (title, msg) => { t.equal(title, 'logout', 'should have correcct log prefix') @@ -216,7 +220,7 @@ test('ignore invalid scoped registry config', async (t) => { ) } - config.clearCredentialsByURI = (registry) => { + npm.config.clearCredentialsByURI = (registry) => { t.equal( registry, 'https://registry.npmjs.org/', @@ -224,8 +228,8 @@ test('ignore invalid scoped registry config', async (t) => { ) } - config.delete = () => null - config.save = () => null + npm.config.delete = () => null + npm.config.save = () => null await new Promise((res, rej) => { logout.exec([], (err) => { @@ -247,7 +251,7 @@ test('ignore invalid scoped registry config', async (t) => { 'should call npm-registry-fetch with expected values' ) - delete _flatOptions.token + delete flatOptions.token result = null mocks['npm-registry-fetch'] = null config.clearCredentialsByURI = null diff --git a/deps/npm/test/lib/ls.js b/deps/npm/test/lib/ls.js index bcbd341356..5367dec688 100644 --- a/deps/npm/test/lib/ls.js +++ b/deps/npm/test/lib/ls.js @@ -1,4 +1,5 @@ const t = require('tap') +const mockNpm = require('../fixtures/mock-npm') const { resolve } = require('path') const { utimesSync } = require('fs') @@ -84,12 +85,9 @@ const diffDepTypesNmFixture = { }, } -let prefix -let globalDir = 'MISSING_GLOBAL_DIR' let result = '' -// note this _flatOptions representations is for tests-only and does not -// represent exactly the properties found in the actual flatOptions obj -const _flatOptions = { +const LS = require('../../lib/ls.js') +const config = { all: true, color: false, dev: false, @@ -99,32 +97,18 @@ const _flatOptions = { link: false, only: null, parseable: false, - get prefix () { - return prefix - }, production: false, } -const LS = require('../../lib/ls.js') -const ls = new LS({ - flatOptions: _flatOptions, - limit: { - fetch: 3, - }, - get prefix () { - return _flatOptions.prefix - }, - get globalDir () { - return globalDir - }, - config: { - get (key) { - return _flatOptions[key] - }, - }, +const flatOptions = { +} +const npm = mockNpm({ + config, + flatOptions, output: msg => { result = msg }, }) +const ls = new LS(npm) const redactCwd = res => res && res.replace(/\\+/g, '/').replace(new RegExp(__dirname.replace(/\\+/g, '/'), 'gi'), '{CWD}') @@ -138,10 +122,10 @@ const cleanUpResult = (done, t) => { t.test('ls', (t) => { t.beforeEach(cleanUpResult) - _flatOptions.json = false - _flatOptions.unicode = false + config.json = false + config.unicode = false t.test('no args', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -160,7 +144,7 @@ t.test('ls', (t) => { }) t.test('missing package.json', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ ...simpleNmFixture, }) ls.exec([], (err) => { @@ -175,7 +159,7 @@ t.test('ls', (t) => { }) t.test('extraneous deps', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -198,8 +182,8 @@ t.test('ls', (t) => { }) t.test('with filter arg', (t) => { - _flatOptions.color = true - prefix = t.testdir({ + npm.color = true + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -213,15 +197,15 @@ t.test('ls', (t) => { ls.exec(['lorem'], (err) => { t.ifError(err, 'npm ls') t.matchSnapshot(redactCwd(result), 'should output tree contaning only occurrences of filtered by package and colored output') - _flatOptions.color = false + npm.color = false t.end() }) }) t.test('with dot filter arg', (t) => { - _flatOptions.all = false - _flatOptions.depth = 0 - prefix = t.testdir({ + config.all = false + config.depth = 0 + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -235,14 +219,14 @@ t.test('ls', (t) => { ls.exec(['.'], (err) => { t.ifError(err, 'should not throw on missing dep above current level') t.matchSnapshot(redactCwd(result), 'should output tree contaning only occurrences of filtered by package and colored output') - _flatOptions.all = true - _flatOptions.depth = Infinity + config.all = true + config.depth = Infinity t.end() }) }) t.test('with filter arg nested dep', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -261,7 +245,7 @@ t.test('ls', (t) => { }) t.test('with multiple filter args', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -289,7 +273,7 @@ t.test('ls', (t) => { }) t.test('with missing filter arg', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -314,9 +298,9 @@ t.test('ls', (t) => { }) t.test('default --depth value should be 0', (t) => { - _flatOptions.all = false - _flatOptions.depth = undefined - prefix = t.testdir({ + config.all = false + config.depth = undefined + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -330,16 +314,16 @@ t.test('ls', (t) => { ls.exec([], (err) => { t.ifError(err, 'npm ls') t.matchSnapshot(redactCwd(result), 'should output tree containing only top-level dependencies') - _flatOptions.all = true - _flatOptions.depth = Infinity + config.all = true + config.depth = Infinity t.end() }) }) t.test('--depth=0', (t) => { - _flatOptions.all = false - _flatOptions.depth = 0 - prefix = t.testdir({ + config.all = false + config.depth = 0 + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -353,16 +337,16 @@ t.test('ls', (t) => { ls.exec([], (err) => { t.ifError(err, 'npm ls') t.matchSnapshot(redactCwd(result), 'should output tree containing only top-level dependencies') - _flatOptions.all = true - _flatOptions.depth = Infinity + config.all = true + config.depth = Infinity t.end() }) }) t.test('--depth=1', (t) => { - _flatOptions.all = false - _flatOptions.depth = 1 - prefix = t.testdir({ + config.all = false + config.depth = 1 + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -414,14 +398,14 @@ t.test('ls', (t) => { ls.exec([], (err) => { t.ifError(err, 'npm ls') t.matchSnapshot(redactCwd(result), 'should output tree containing top-level deps and their deps only') - _flatOptions.all = true - _flatOptions.depth = Infinity + config.all = true + config.depth = Infinity t.end() }) }) t.test('missing/invalid/extraneous', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -447,8 +431,8 @@ t.test('ls', (t) => { }) t.test('colored output', (t) => { - _flatOptions.color = true - prefix = t.testdir({ + npm.color = true + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -462,14 +446,14 @@ t.test('ls', (t) => { ls.exec([], (err) => { t.equal(err.code, 'ELSPROBLEMS', 'should have error code') t.matchSnapshot(redactCwd(result), 'should output tree containing color info') - _flatOptions.color = false + npm.color = false t.end() }) }) t.test('--dev', (t) => { - _flatOptions.dev = true - prefix = t.testdir({ + config.dev = true + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -491,14 +475,14 @@ t.test('ls', (t) => { }) ls.exec([], () => { t.matchSnapshot(redactCwd(result), 'should output tree containing dev deps') - _flatOptions.dev = false + config.dev = false t.end() }) }) t.test('--only=development', (t) => { - _flatOptions.only = 'development' - prefix = t.testdir({ + config.only = 'development' + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -520,14 +504,14 @@ t.test('ls', (t) => { }) ls.exec([], () => { t.matchSnapshot(redactCwd(result), 'should output tree containing only development deps') - _flatOptions.only = null + config.only = null t.end() }) }) t.test('--link', (t) => { - _flatOptions.link = true - prefix = t.testdir({ + config.link = true + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -559,13 +543,13 @@ t.test('ls', (t) => { }) ls.exec([], () => { t.matchSnapshot(redactCwd(result), 'should output tree containing linked deps') - _flatOptions.link = false + config.link = false t.end() }) }) t.test('print deduped symlinks', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'print-deduped-symlinks', version: '1.0.0', @@ -595,14 +579,14 @@ t.test('ls', (t) => { }) ls.exec([], () => { t.matchSnapshot(redactCwd(result), 'should output tree containing linked deps') - _flatOptions.link = false + config.link = false t.end() }) }) t.test('--production', (t) => { - _flatOptions.production = true - prefix = t.testdir({ + config.production = true + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -624,14 +608,14 @@ t.test('ls', (t) => { }) ls.exec([], () => { t.matchSnapshot(redactCwd(result), 'should output tree containing production deps') - _flatOptions.production = false + config.production = false t.end() }) }) t.test('--only=prod', (t) => { - _flatOptions.only = 'prod' - prefix = t.testdir({ + config.only = 'prod' + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -653,14 +637,14 @@ t.test('ls', (t) => { }) ls.exec([], () => { t.matchSnapshot(redactCwd(result), 'should output tree containing only prod deps') - _flatOptions.only = null + config.only = null t.end() }) }) t.test('--long', (t) => { - _flatOptions.long = true - prefix = t.testdir({ + config.long = true + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -682,16 +666,16 @@ t.test('ls', (t) => { }) ls.exec([], () => { t.matchSnapshot(redactCwd(result), 'should output tree info with descriptions') - _flatOptions.long = true + config.long = true t.end() }) }) t.test('--long --depth=0', (t) => { - _flatOptions.all = false - _flatOptions.depth = 0 - _flatOptions.long = true - prefix = t.testdir({ + config.all = false + config.depth = 0 + config.long = true + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -713,15 +697,15 @@ t.test('ls', (t) => { }) ls.exec([], () => { t.matchSnapshot(redactCwd(result), 'should output tree containing top-level deps with descriptions') - _flatOptions.all = true - _flatOptions.depth = Infinity - _flatOptions.long = false + config.all = true + config.depth = Infinity + config.long = false t.end() }) }) t.test('json read problems', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': '{broken json', }) ls.exec([], (err) => { @@ -732,7 +716,7 @@ t.test('ls', (t) => { }) t.test('empty location', (t) => { - prefix = t.testdir({}) + npm.prefix = t.testdir({}) ls.exec([], (err) => { t.ifError(err, 'should not error out on empty locations') t.matchSnapshot(redactCwd(result), 'should print empty result') @@ -741,7 +725,7 @@ t.test('ls', (t) => { }) t.test('invalid peer dep', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -768,8 +752,8 @@ t.test('ls', (t) => { }) t.test('invalid deduped dep', (t) => { - _flatOptions.color = true - prefix = t.testdir({ + npm.color = true + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'invalid-deduped-dep', version: '1.0.0', @@ -798,13 +782,13 @@ t.test('ls', (t) => { }) ls.exec([], () => { t.matchSnapshot(redactCwd(result), 'should output tree signaling mismatching peer dep in problems') - _flatOptions.color = false + npm.color = false t.end() }) }) t.test('deduped missing dep', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -834,7 +818,7 @@ t.test('ls', (t) => { }) t.test('unmet peer dep', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -852,8 +836,8 @@ t.test('ls', (t) => { }) t.test('unmet optional dep', (t) => { - _flatOptions.color = true - prefix = t.testdir({ + npm.color = true + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -878,13 +862,13 @@ t.test('ls', (t) => { t.match(err.code, 'ELSPROBLEMS', 'should have ELSPROBLEMS error code') t.match(err.message, /invalid: optional-dep@1.0.0/, 'should have invalid dep error msg') t.matchSnapshot(redactCwd(result), 'should output tree with empty entry for missing optional deps') - _flatOptions.color = false + npm.color = false t.end() }) }) t.test('cycle deps', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -921,8 +905,8 @@ t.test('ls', (t) => { }) t.test('cycle deps with filter args', (t) => { - _flatOptions.color = true - prefix = t.testdir({ + npm.color = true + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -954,13 +938,13 @@ t.test('ls', (t) => { ls.exec(['a'], (err) => { t.ifError(err, 'npm ls') t.matchSnapshot(redactCwd(result), 'should print tree output containing deduped ref') - _flatOptions.color = false + npm.color = false t.end() }) }) t.test('with no args dedupe entries', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'dedupe-entries', version: '1.0.0', @@ -1007,9 +991,9 @@ t.test('ls', (t) => { }) t.test('with no args dedupe entries and not displaying all', (t) => { - _flatOptions.all = false - _flatOptions.depth = 0 - prefix = t.testdir({ + config.all = false + config.depth = 0 + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'dedupe-entries', version: '1.0.0', @@ -1051,15 +1035,15 @@ t.test('ls', (t) => { ls.exec([], (err) => { t.ifError(err, 'npm ls') t.matchSnapshot(redactCwd(result), 'should print tree output containing deduped ref') - _flatOptions.all = true - _flatOptions.depth = Infinity + config.all = true + config.depth = Infinity t.end() }) }) t.test('with args and dedupe entries', (t) => { - _flatOptions.color = true - prefix = t.testdir({ + npm.color = true + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'dedupe-entries', version: '1.0.0', @@ -1101,13 +1085,13 @@ t.test('ls', (t) => { ls.exec(['@npmcli/b'], (err) => { t.ifError(err, 'npm ls') t.matchSnapshot(redactCwd(result), 'should print tree output containing deduped ref') - _flatOptions.color = false + npm.color = false t.end() }) }) t.test('with args and different order of items', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'dedupe-entries', version: '1.0.0', @@ -1154,7 +1138,7 @@ t.test('ls', (t) => { }) t.test('using aliases', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -1189,7 +1173,7 @@ t.test('ls', (t) => { }, }, }) - touchHiddenPackageLock(prefix) + touchHiddenPackageLock(npm.prefix) ls.exec([], () => { t.matchSnapshot(redactCwd(result), 'should output tree containing aliases') t.end() @@ -1197,7 +1181,7 @@ t.test('ls', (t) => { }) t.test('resolved points to git ref', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -1235,7 +1219,7 @@ t.test('ls', (t) => { }, }, }) - touchHiddenPackageLock(prefix) + touchHiddenPackageLock(npm.prefix) ls.exec([], (err) => { t.ifError(err, 'npm ls') t.matchSnapshot(redactCwd(result), 'should output tree containing git refs') @@ -1244,7 +1228,7 @@ t.test('ls', (t) => { }) t.test('broken resolved field', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ node_modules: { a: { 'package.json': JSON.stringify({ @@ -1288,7 +1272,7 @@ t.test('ls', (t) => { }) t.test('from and resolved properties', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -1334,7 +1318,7 @@ t.test('ls', (t) => { }, }, }) - touchHiddenPackageLock(prefix) + touchHiddenPackageLock(npm.prefix) ls.exec([], () => { t.matchSnapshot(redactCwd(result), 'should not be printed in tree output') t.end() @@ -1342,7 +1326,7 @@ t.test('ls', (t) => { }) t.test('global', (t) => { - _flatOptions.global = true + config.global = true const fixtures = t.testdir({ node_modules: { a: { @@ -1369,18 +1353,18 @@ t.test('ls', (t) => { }) // mimics lib/npm.js globalDir getter but pointing to fixtures - globalDir = resolve(fixtures, 'node_modules') + npm.globalDir = resolve(fixtures, 'node_modules') ls.exec([], () => { t.matchSnapshot(redactCwd(result), 'should print tree and not mark top-level items extraneous') - globalDir = 'MISSING_GLOBAL_DIR' - _flatOptions.global = false + npm.globalDir = 'MISSING_GLOBAL_DIR' + config.global = false t.end() }) }) t.test('filtering by child of missing dep', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'filter-by-child-of-missing-dep', version: '1.0.0', @@ -1432,7 +1416,7 @@ t.test('ls', (t) => { }) t.test('loading a tree containing workspaces', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'filter-by-child-of-missing-dep', version: '1.0.0', @@ -1483,8 +1467,8 @@ t.test('ls', (t) => { }) t.test('filter pkg arg using depth option', (t) => { - _flatOptions.depth = 0 - prefix = t.testdir({ + config.depth = 0 + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-pkg-arg-filter-with-depth-opt', version: '1.0.0', @@ -1540,7 +1524,7 @@ t.test('ls', (t) => { t.matchSnapshot(redactCwd(result), 'should print empty results msg') // if no --depth config is defined, should print path to dep - _flatOptions.depth = null // default config value + config.depth = null // default config value ls.exec(['d'], (err) => { t.ifError(err, 'should NOT have ELSPROBLEMS error code when filter') t.matchSnapshot(redactCwd(result), 'should print expected result') @@ -1550,7 +1534,7 @@ t.test('ls', (t) => { }) t.teardown(() => { - _flatOptions.depth = Infinity + config.depth = Infinity }) t.end() @@ -1558,11 +1542,11 @@ t.test('ls', (t) => { t.test('ls --parseable', (t) => { t.beforeEach(cleanUpResult) - _flatOptions.json = false - _flatOptions.unicode = false - _flatOptions.parseable = true + config.json = false + config.unicode = false + config.parseable = true t.test('no args', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -1581,7 +1565,7 @@ t.test('ls --parseable', (t) => { }) t.test('missing package.json', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ ...simpleNmFixture, }) ls.exec([], (err) => { @@ -1596,7 +1580,7 @@ t.test('ls --parseable', (t) => { }) t.test('extraneous deps', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -1614,7 +1598,7 @@ t.test('ls --parseable', (t) => { }) t.test('with filter arg', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -1633,7 +1617,7 @@ t.test('ls --parseable', (t) => { }) t.test('with filter arg nested dep', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -1652,7 +1636,7 @@ t.test('ls --parseable', (t) => { }) t.test('with multiple filter args', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -1680,7 +1664,7 @@ t.test('ls --parseable', (t) => { }) t.test('with missing filter arg', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -1705,9 +1689,9 @@ t.test('ls --parseable', (t) => { }) t.test('default --depth value should be 0', (t) => { - _flatOptions.all = false - _flatOptions.depth = undefined - prefix = t.testdir({ + config.all = false + config.depth = undefined + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -1721,16 +1705,16 @@ t.test('ls --parseable', (t) => { ls.exec([], (err) => { t.ifError(err, 'npm ls') t.matchSnapshot(redactCwd(result), 'should output parseable output containing only top-level dependencies') - _flatOptions.all = true - _flatOptions.depth = Infinity + config.all = true + config.depth = Infinity t.end() }) }) t.test('--depth=0', (t) => { - _flatOptions.all = false - _flatOptions.depth = 0 - prefix = t.testdir({ + config.all = false + config.depth = 0 + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -1744,16 +1728,16 @@ t.test('ls --parseable', (t) => { ls.exec([], (err) => { t.ifError(err, 'npm ls') t.matchSnapshot(redactCwd(result), 'should output tree containing only top-level dependencies') - _flatOptions.all = true - _flatOptions.depth = Infinity + config.all = true + config.depth = Infinity t.end() }) }) t.test('--depth=1', (t) => { - _flatOptions.all = false - _flatOptions.depth = 1 - prefix = t.testdir({ + config.all = false + config.depth = 1 + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -1767,14 +1751,14 @@ t.test('ls --parseable', (t) => { ls.exec([], (err) => { t.ifError(err, 'npm ls') t.matchSnapshot(redactCwd(result), 'should output parseable containing top-level deps and their deps only') - _flatOptions.all = true - _flatOptions.depth = Infinity + config.all = true + config.depth = Infinity t.end() }) }) t.test('missing/invalid/extraneous', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -1793,8 +1777,8 @@ t.test('ls --parseable', (t) => { }) t.test('--dev', (t) => { - _flatOptions.dev = true - prefix = t.testdir({ + config.dev = true + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -1816,14 +1800,14 @@ t.test('ls --parseable', (t) => { }) ls.exec([], () => { t.matchSnapshot(redactCwd(result), 'should output tree containing dev deps') - _flatOptions.dev = false + config.dev = false t.end() }) }) t.test('--only=development', (t) => { - _flatOptions.only = 'development' - prefix = t.testdir({ + config.only = 'development' + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -1845,14 +1829,14 @@ t.test('ls --parseable', (t) => { }) ls.exec([], () => { t.matchSnapshot(redactCwd(result), 'should output tree containing only development deps') - _flatOptions.only = null + config.only = null t.end() }) }) t.test('--link', (t) => { - _flatOptions.link = true - prefix = t.testdir({ + config.link = true + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -1884,14 +1868,14 @@ t.test('ls --parseable', (t) => { }) ls.exec([], () => { t.matchSnapshot(redactCwd(result), 'should output tree containing linked deps') - _flatOptions.link = false + config.link = false t.end() }) }) t.test('--production', (t) => { - _flatOptions.production = true - prefix = t.testdir({ + config.production = true + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -1913,14 +1897,14 @@ t.test('ls --parseable', (t) => { }) ls.exec([], () => { t.matchSnapshot(redactCwd(result), 'should output tree containing production deps') - _flatOptions.production = false + config.production = false t.end() }) }) t.test('--only=prod', (t) => { - _flatOptions.only = 'prod' - prefix = t.testdir({ + config.only = 'prod' + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -1942,14 +1926,14 @@ t.test('ls --parseable', (t) => { }) ls.exec([], () => { t.matchSnapshot(redactCwd(result), 'should output tree containing only prod deps') - _flatOptions.only = null + config.only = null t.end() }) }) t.test('--long', (t) => { - _flatOptions.long = true - prefix = t.testdir({ + config.long = true + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -1971,13 +1955,13 @@ t.test('ls --parseable', (t) => { }) ls.exec([], () => { t.matchSnapshot(redactCwd(result), 'should output tree info with descriptions') - _flatOptions.long = true + config.long = true t.end() }) }) t.test('--long with extraneous deps', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -1996,8 +1980,8 @@ t.test('ls --parseable', (t) => { }) t.test('--long missing/invalid/extraneous', (t) => { - _flatOptions.long = true - prefix = t.testdir({ + config.long = true + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -2011,14 +1995,14 @@ t.test('ls --parseable', (t) => { ls.exec([], (err) => { t.match(err, { code: 'ELSPROBLEMS' }, 'should list dep problems') t.matchSnapshot(redactCwd(result), 'should output parseable result containing EXTRANEOUS/INVALID labels') - _flatOptions.long = false + config.long = false t.end() }) }) t.test('--long print symlink target location', (t) => { - _flatOptions.long = true - prefix = t.testdir({ + config.long = true + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -2051,16 +2035,16 @@ t.test('ls --parseable', (t) => { ls.exec([], (err) => { t.ifError(err, 'npm ls') t.matchSnapshot(redactCwd(result), 'should output parseable results with symlink targets') - _flatOptions.long = false + config.long = false t.end() }) }) t.test('--long --depth=0', (t) => { - _flatOptions.all = false - _flatOptions.depth = 0 - _flatOptions.long = true - prefix = t.testdir({ + config.all = false + config.depth = 0 + config.long = true + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -2082,15 +2066,15 @@ t.test('ls --parseable', (t) => { }) ls.exec([], () => { t.matchSnapshot(redactCwd(result), 'should output tree containing top-level deps with descriptions') - _flatOptions.all = true - _flatOptions.depth = Infinity - _flatOptions.long = false + config.all = true + config.depth = Infinity + config.long = false t.end() }) }) t.test('json read problems', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': '{broken json', }) ls.exec([], (err) => { @@ -2101,7 +2085,7 @@ t.test('ls --parseable', (t) => { }) t.test('empty location', (t) => { - prefix = t.testdir({}) + npm.prefix = t.testdir({}) ls.exec([], (err) => { t.ifError(err, 'should not error out on empty locations') t.matchSnapshot(redactCwd(result), 'should print empty result') @@ -2110,7 +2094,7 @@ t.test('ls --parseable', (t) => { }) t.test('unmet peer dep', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -2137,7 +2121,7 @@ t.test('ls --parseable', (t) => { }) t.test('unmet optional dep', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -2167,7 +2151,7 @@ t.test('ls --parseable', (t) => { }) t.test('cycle deps', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -2203,7 +2187,7 @@ t.test('ls --parseable', (t) => { }) t.test('using aliases', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -2234,7 +2218,7 @@ t.test('ls --parseable', (t) => { }, }, }) - touchHiddenPackageLock(prefix) + touchHiddenPackageLock(npm.prefix) ls.exec([], () => { t.matchSnapshot(redactCwd(result), 'should output tree containing aliases') t.end() @@ -2242,7 +2226,7 @@ t.test('ls --parseable', (t) => { }) t.test('resolved points to git ref', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -2279,7 +2263,7 @@ t.test('ls --parseable', (t) => { }, }, }) - touchHiddenPackageLock(prefix) + touchHiddenPackageLock(npm.prefix) ls.exec([], () => { t.matchSnapshot(redactCwd(result), 'should output tree containing git refs') t.end() @@ -2287,7 +2271,7 @@ t.test('ls --parseable', (t) => { }) t.test('from and resolved properties', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -2333,7 +2317,7 @@ t.test('ls --parseable', (t) => { }, }, }) - touchHiddenPackageLock(prefix) + touchHiddenPackageLock(npm.prefix) ls.exec([], () => { t.matchSnapshot(redactCwd(result), 'should not be printed in tree output') t.end() @@ -2341,7 +2325,7 @@ t.test('ls --parseable', (t) => { }) t.test('global', (t) => { - _flatOptions.global = true + config.global = true const fixtures = t.testdir({ node_modules: { a: { @@ -2368,12 +2352,12 @@ t.test('ls --parseable', (t) => { }) // mimics lib/npm.js globalDir getter but pointing to fixtures - globalDir = resolve(fixtures, 'node_modules') + npm.globalDir = resolve(fixtures, 'node_modules') ls.exec([], () => { t.matchSnapshot(redactCwd(result), 'should print parseable output for global deps') - globalDir = 'MISSING_GLOBAL_DIR' - _flatOptions.global = false + npm.globalDir = 'MISSING_GLOBAL_DIR' + config.global = false t.end() }) }) @@ -2383,10 +2367,10 @@ t.test('ls --parseable', (t) => { t.test('ls --json', (t) => { t.beforeEach(cleanUpResult) - _flatOptions.json = true - _flatOptions.parseable = false + config.json = true + config.parseable = false t.test('no args', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -2425,7 +2409,7 @@ t.test('ls --json', (t) => { }) t.test('missing package.json', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ ...simpleNmFixture, }) ls.exec([], (err) => { @@ -2474,7 +2458,7 @@ t.test('ls --json', (t) => { }) t.test('extraneous deps', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -2528,7 +2512,7 @@ t.test('ls --json', (t) => { }) t.test('with filter arg', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -2564,7 +2548,7 @@ t.test('ls --json', (t) => { }) t.test('with filter arg nested dep', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -2600,7 +2584,7 @@ t.test('ls --json', (t) => { }) t.test('with multiple filter args', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -2648,7 +2632,7 @@ t.test('ls --json', (t) => { }) t.test('with missing filter arg', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -2680,9 +2664,9 @@ t.test('ls --json', (t) => { }) t.test('default --depth value should now be 0', (t) => { - _flatOptions.all = false - _flatOptions.depth = undefined - prefix = t.testdir({ + config.all = false + config.depth = undefined + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -2711,16 +2695,16 @@ t.test('ls --json', (t) => { }, 'should output json containing only top-level dependencies' ) - _flatOptions.all = true - _flatOptions.depth = Infinity + config.all = true + config.depth = Infinity t.end() }) }) t.test('--depth=0', (t) => { - _flatOptions.all = false - _flatOptions.depth = 0 - prefix = t.testdir({ + config.all = false + config.depth = 0 + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -2749,16 +2733,16 @@ t.test('ls --json', (t) => { }, 'should output json containing only top-level dependencies' ) - _flatOptions.all = true - _flatOptions.depth = Infinity + config.all = true + config.depth = Infinity t.end() }) }) t.test('--depth=1', (t) => { - _flatOptions.all = false - _flatOptions.depth = 1 - prefix = t.testdir({ + config.all = false + config.depth = 1 + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -2792,14 +2776,14 @@ t.test('ls --json', (t) => { }, 'should output json containing top-level deps and their deps only' ) - _flatOptions.all = true - _flatOptions.depth = Infinity + config.all = true + config.depth = Infinity t.end() }) }) t.test('missing/invalid/extraneous', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -2858,8 +2842,8 @@ t.test('ls --json', (t) => { }) t.test('--dev', (t) => { - _flatOptions.dev = true - prefix = t.testdir({ + config.dev = true + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -2899,14 +2883,14 @@ t.test('ls --json', (t) => { }, 'should output json containing dev deps' ) - _flatOptions.dev = false + config.dev = false t.end() }) }) t.test('--only=development', (t) => { - _flatOptions.only = 'development' - prefix = t.testdir({ + config.only = 'development' + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -2946,14 +2930,14 @@ t.test('ls --json', (t) => { }, 'should output json containing only development deps' ) - _flatOptions.only = null + config.only = null t.end() }) }) t.test('--link', (t) => { - _flatOptions.link = true - prefix = t.testdir({ + config.link = true + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -2998,14 +2982,14 @@ t.test('ls --json', (t) => { }, 'should output json containing linked deps' ) - _flatOptions.link = false + config.link = false t.end() }) }) t.test('--production', (t) => { - _flatOptions.production = true - prefix = t.testdir({ + config.production = true + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -3039,14 +3023,14 @@ t.test('ls --json', (t) => { }, 'should output json containing production deps' ) - _flatOptions.production = false + config.production = false t.end() }) }) t.test('--only=prod', (t) => { - _flatOptions.only = 'prod' - prefix = t.testdir({ + config.only = 'prod' + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -3080,13 +3064,13 @@ t.test('ls --json', (t) => { }, 'should output json containing only prod deps' ) - _flatOptions.only = null + config.only = null t.end() }) }) t.test('from lockfile', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ node_modules: { '@isaacs': { 'dedupe-tests-a': { @@ -3215,8 +3199,8 @@ t.test('ls --json', (t) => { }) t.test('--long', (t) => { - _flatOptions.long = true - prefix = t.testdir({ + config.long = true + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -3345,16 +3329,16 @@ t.test('ls --json', (t) => { }, 'should output long json info' ) - _flatOptions.long = true + config.long = true t.end() }) }) t.test('--long --depth=0', (t) => { - _flatOptions.all = false - _flatOptions.depth = 0 - _flatOptions.long = true - prefix = t.testdir({ + config.all = false + config.depth = 0 + config.long = true + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -3446,15 +3430,15 @@ t.test('ls --json', (t) => { }, 'should output json containing top-level deps in long format' ) - _flatOptions.all = true - _flatOptions.depth = Infinity - _flatOptions.long = false + config.all = true + config.depth = Infinity + config.long = false t.end() }) }) t.test('json read problems', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': '{broken json', }) ls.exec([], (err) => { @@ -3475,7 +3459,7 @@ t.test('ls --json', (t) => { }) t.test('empty location', (t) => { - prefix = t.testdir({}) + npm.prefix = t.testdir({}) ls.exec([], (err) => { t.ifError(err, 'should not error out on empty locations') t.deepEqual( @@ -3488,7 +3472,7 @@ t.test('ls --json', (t) => { }) t.test('unmet peer dep', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -3547,7 +3531,7 @@ t.test('ls --json', (t) => { }) t.test('unmet optional dep', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -3611,7 +3595,7 @@ t.test('ls --json', (t) => { }) t.test('cycle deps', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -3667,7 +3651,7 @@ t.test('ls --json', (t) => { }) t.test('using aliases', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -3697,7 +3681,7 @@ t.test('ls --json', (t) => { }, }, }) - touchHiddenPackageLock(prefix) + touchHiddenPackageLock(npm.prefix) ls.exec([], () => { t.deepEqual( jsonParse(result), @@ -3718,7 +3702,7 @@ t.test('ls --json', (t) => { }) t.test('resolved points to git ref', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -3757,7 +3741,7 @@ t.test('ls --json', (t) => { }, }, }) - touchHiddenPackageLock(prefix) + touchHiddenPackageLock(npm.prefix) ls.exec([], () => { t.deepEqual( jsonParse(result), @@ -3778,7 +3762,7 @@ t.test('ls --json', (t) => { }) t.test('from and resolved properties', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'test-npm-ls', version: '1.0.0', @@ -3841,7 +3825,7 @@ t.test('ls --json', (t) => { }, }, }) - touchHiddenPackageLock(prefix) + touchHiddenPackageLock(npm.prefix) ls.exec([], () => { t.deepEqual( jsonParse(result), @@ -3862,7 +3846,7 @@ t.test('ls --json', (t) => { }) t.test('node.name fallback if missing root package name', (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ version: '1.0.0', }), @@ -3881,7 +3865,7 @@ t.test('ls --json', (t) => { }) t.test('global', (t) => { - _flatOptions.global = true + config.global = true const fixtures = t.testdir({ node_modules: { a: { @@ -3908,7 +3892,7 @@ t.test('ls --json', (t) => { }) // mimics lib/npm.js globalDir getter but pointing to fixtures - globalDir = resolve(fixtures, 'node_modules') + npm.globalDir = resolve(fixtures, 'node_modules') ls.exec([], () => { t.deepEqual( @@ -3931,8 +3915,8 @@ t.test('ls --json', (t) => { }, 'should print json output for global deps' ) - globalDir = 'MISSING_GLOBAL_DIR' - _flatOptions.global = false + npm.globalDir = 'MISSING_GLOBAL_DIR' + config.global = false t.end() }) }) diff --git a/deps/npm/test/lib/npm.js b/deps/npm/test/lib/npm.js index 87cbea8f2c..5739193980 100644 --- a/deps/npm/test/lib/npm.js +++ b/deps/npm/test/lib/npm.js @@ -42,7 +42,7 @@ const npmlog = require('npmlog') const npmPath = resolve(__dirname, '..', '..') const Config = require('@npmcli/config') -const { types, defaults, shorthands } = require('../../lib/utils/config.js') +const { definitions, shorthands, flatten } = require('../../lib/utils/config') const freshConfig = (opts = {}) => { for (const env of Object.keys(process.env).filter(e => /^npm_/.test(e))) delete process.env[env] @@ -50,12 +50,12 @@ const freshConfig = (opts = {}) => { process.env.npm_config_cache = CACHE npm.config = new Config({ - types, - defaults, + definitions, shorthands, npmPath, log: npmlog, ...opts, + flatten, }) } @@ -145,6 +145,7 @@ t.test('npm.load', t => { t.equal(npm.loading, false, 'not loading yet') const p = npm.load(first).then(() => { + t.ok(npm.usage, 'has usage') npm.config.set('prefix', dir) t.match(npm, { loaded: true, @@ -160,7 +161,7 @@ t.test('npm.load', t => { npm.load(third) t.equal(thirdCalled, true, 'third callbback got called') t.match(logs, [ - ['timing', 'npm:load', /Completed in [0-9]+ms/], + ['timing', 'npm:load', /Completed in [0-9.]+ms/], ]) logs.length = 0 @@ -289,6 +290,11 @@ t.test('npm.load', t => { t.equal(npm.config.get('scope'), '@foo', 'added the @ sign to scope') t.match(logs.filter(l => l[0] !== 'timing' || !/^config:/.test(l[1])), [ [ + 'timing', + 'npm:load:whichnode', + /Completed in [0-9.]+ms/, + ], + [ 'verbose', 'node symlink', resolve(dir, 'bin', node), @@ -296,7 +302,7 @@ t.test('npm.load', t => { [ 'timing', 'npm:load', - /Completed in [0-9]+ms/, + /Completed in [0-9.]+ms/, ], ]) logs.length = 0 @@ -307,6 +313,9 @@ t.test('npm.load', t => { if (er) throw er + t.equal(npm.command, 'll', 'command set to first npm command') + t.equal(npm.flatOptions.npmCommand, 'll', 'npmCommand flatOption set') + t.same(consoleLogs, [[npm.commands.ll.usage]], 'print usage') consoleLogs.length = 0 npm.config.set('usage', false) @@ -318,6 +327,9 @@ t.test('npm.load', t => { if (er) throw er + t.strictSame([npm.command, npm.flatOptions.npmCommand], ['ll', 'll'], + 'does not change npm.command when another command is called') + t.match(logs, [ [ 'error', @@ -328,12 +340,12 @@ t.test('npm.load', t => { [ 'timing', 'command:config', - /Completed in [0-9]+ms/, + /Completed in [0-9.]+ms/, ], [ 'timing', 'command:get', - /Completed in [0-9]+ms/, + /Completed in [0-9.]+ms/, ], ]) t.same(consoleLogs, [['scope=@foo\n\u2010not-a-dash=undefined']]) @@ -343,6 +355,84 @@ t.test('npm.load', t => { await new Promise((res) => setTimeout(res)) }) + t.test('workpaces-aware configs and commands', async t => { + const dir = t.testdir({ + packages: { + a: { + 'package.json': JSON.stringify({ + name: 'a', + version: '1.0.0', + scripts: { test: 'echo test a' }, + }), + }, + b: { + 'package.json': JSON.stringify({ + name: 'b', + version: '1.0.0', + scripts: { test: 'echo test b' }, + }), + }, + }, + 'package.json': JSON.stringify({ + name: 'root', + version: '1.0.0', + workspaces: ['./packages/*'], + }), + '.npmrc': '', + }) + + const { log } = console + const consoleLogs = [] + console.log = (...msg) => consoleLogs.push(msg) + + const { execPath } = process + t.teardown(() => { + console.log = log + }) + + freshConfig({ + argv: [ + execPath, + process.argv[1], + '--userconfig', + resolve(dir, '.npmrc'), + '--color', + 'false', + '--workspaces', + 'true', + ], + }) + + await npm.load(er => { + if (er) + throw er + }) + + npm.localPrefix = dir + + await new Promise((res, rej) => { + npm.commands['run-script']([], er => { + if (er) + rej(er) + + t.match( + consoleLogs, + [ + ['Lifecycle scripts included in a@1.0.0:'], + [' test\n echo test a'], + [''], + ['Lifecycle scripts included in b@1.0.0:'], + [' test\n echo test b'], + [''], + ], + 'should exec workspaces version of commands' + ) + + res() + }) + }) + }) + t.end() }) diff --git a/deps/npm/test/lib/outdated.js b/deps/npm/test/lib/outdated.js index 02952971b6..5aff7c37ac 100644 --- a/deps/npm/test/lib/outdated.js +++ b/deps/npm/test/lib/outdated.js @@ -1,5 +1,6 @@ const t = require('tap') const requireInject = require('require-inject') +const mockNpm = require('../fixtures/mock-npm') const packument = spec => { const mocks = { @@ -89,12 +90,13 @@ const outdated = (dir, opts) => { packument, }, }) - return new Outdated({ + const npm = mockNpm({ + ...opts, prefix: dir, globalDir: `${globalDir}/node_modules`, - flatOptions: opts, output, }) + return new Outdated(npm) } t.beforeEach((done) => { @@ -173,7 +175,7 @@ t.test('should display outdated deps', t => { t.test('outdated global', t => { outdated(null, { - global: true, + config: { global: true }, }).exec([], () => { t.matchSnapshot(logs) t.end() @@ -182,7 +184,9 @@ t.test('should display outdated deps', t => { t.test('outdated', t => { outdated(testDir, { - global: false, + config: { + global: false, + }, color: true, }).exec([], () => { t.matchSnapshot(logs) @@ -192,9 +196,11 @@ t.test('should display outdated deps', t => { t.test('outdated --omit=dev', t => { outdated(testDir, { - global: false, + config: { + global: false, + omit: ['dev'], + }, color: true, - omit: ['dev'], }).exec([], () => { t.matchSnapshot(logs) t.end() @@ -203,9 +209,11 @@ t.test('should display outdated deps', t => { t.test('outdated --omit=dev --omit=peer', t => { outdated(testDir, { - global: false, + config: { + global: false, + omit: ['dev', 'peer'], + }, color: true, - omit: ['dev', 'peer'], }).exec([], () => { t.matchSnapshot(logs) t.end() @@ -214,9 +222,11 @@ t.test('should display outdated deps', t => { t.test('outdated --omit=prod', t => { outdated(testDir, { - global: false, + config: { + global: false, + omit: ['prod'], + }, color: true, - omit: ['prod'], }).exec([], () => { t.matchSnapshot(logs) t.end() @@ -225,8 +235,10 @@ t.test('should display outdated deps', t => { t.test('outdated --long', t => { outdated(testDir, { - global: false, - long: true, + config: { + global: false, + long: true, + }, }).exec([], () => { t.matchSnapshot(logs) t.end() @@ -235,8 +247,10 @@ t.test('should display outdated deps', t => { t.test('outdated --json', t => { outdated(testDir, { - global: false, - json: true, + config: { + global: false, + json: true, + }, }).exec([], () => { t.matchSnapshot(logs) t.end() @@ -245,9 +259,11 @@ t.test('should display outdated deps', t => { t.test('outdated --json --long', t => { outdated(testDir, { - global: false, - json: true, - long: true, + config: { + global: false, + json: true, + long: true, + }, }).exec([], () => { t.matchSnapshot(logs) t.end() @@ -256,8 +272,10 @@ t.test('should display outdated deps', t => { t.test('outdated --parseable', t => { outdated(testDir, { - global: false, - parseable: true, + config: { + global: false, + parseable: true, + }, }).exec([], () => { t.matchSnapshot(logs) t.end() @@ -266,9 +284,11 @@ t.test('should display outdated deps', t => { t.test('outdated --parseable --long', t => { outdated(testDir, { - global: false, - parseable: true, - long: true, + config: { + global: false, + parseable: true, + long: true, + }, }).exec([], () => { t.matchSnapshot(logs) t.end() @@ -277,7 +297,9 @@ t.test('should display outdated deps', t => { t.test('outdated --all', t => { outdated(testDir, { - all: true, + config: { + all: true, + }, }).exec([], () => { t.matchSnapshot(logs) t.end() @@ -286,7 +308,9 @@ t.test('should display outdated deps', t => { t.test('outdated specific dep', t => { outdated(testDir, { - global: false, + config: { + global: false, + }, }).exec(['alpha'], () => { t.matchSnapshot(logs) t.end() diff --git a/deps/npm/test/lib/pack.js b/deps/npm/test/lib/pack.js index ce319be76b..a5163acfdc 100644 --- a/deps/npm/test/lib/pack.js +++ b/deps/npm/test/lib/pack.js @@ -1,5 +1,6 @@ const t = require('tap') const requireInject = require('require-inject') +const mockNpm = require('../fixtures/mock-npm') const OUTPUT = [] const output = (...msg) => OUTPUT.push(msg) @@ -25,14 +26,15 @@ t.test('should pack current directory with no arguments', (t) => { clearProgress: () => {}, }, }) - const pack = new Pack({ - flatOptions: { + const npm = mockNpm({ + config: { unicode: false, json: false, - dryRun: false, + 'dry-run': false, }, output, }) + const pack = new Pack(npm) pack.exec([], er => { if (er) @@ -60,14 +62,15 @@ t.test('should pack given directory', (t) => { clearProgress: () => {}, }, }) - const pack = new Pack({ - flatOptions: { + const npm = mockNpm({ + config: { unicode: true, json: true, - dryRun: true, + 'dry-run': true, }, output, }) + const pack = new Pack(npm) pack.exec([testDir], er => { if (er) @@ -95,14 +98,15 @@ t.test('should pack given directory for scoped package', (t) => { clearProgress: () => {}, }, }) - const pack = new Pack({ - flatOptions: { + const npm = mockNpm({ + config: { unicode: true, json: true, - dryRun: true, + 'dry-run': true, }, output, }) + const pack = new Pack(npm) return pack.exec([testDir], er => { if (er) @@ -129,14 +133,15 @@ t.test('should log pack contents', (t) => { clearProgress: () => {}, }, }) - const pack = new Pack({ - flatOptions: { + const npm = mockNpm({ + config: { unicode: false, json: false, - dryRun: false, + 'dry-run': false, }, output, }) + const pack = new Pack(npm) pack.exec([], er => { if (er) diff --git a/deps/npm/test/lib/ping.js b/deps/npm/test/lib/ping.js index f3563036f7..95361035ac 100644 --- a/deps/npm/test/lib/ping.js +++ b/deps/npm/test/lib/ping.js @@ -1,14 +1,15 @@ const { test } = require('tap') const requireInject = require('require-inject') +const mockNpm = require('../fixtures/mock-npm') test('pings', (t) => { t.plan(8) - const flatOptions = { registry: 'https://registry.npmjs.org' } + const registry = 'https://registry.npmjs.org' let noticeCalls = 0 const Ping = requireInject('../../lib/ping.js', { '../../lib/utils/ping.js': function (spec) { - t.equal(spec, flatOptions, 'passes flatOptions') + t.equal(spec.registry, registry, 'passes flatOptions') return {} }, npmlog: { @@ -16,7 +17,7 @@ test('pings', (t) => { ++noticeCalls if (noticeCalls === 1) { t.equal(type, 'PING', 'should log a PING') - t.equal(spec, flatOptions.registry, 'should log the registry url') + t.equal(spec, registry, 'should log the registry url') } else { t.equal(type, 'PONG', 'should log a PONG') t.match(spec, /\d+ms/, 'should log the elapsed milliseconds') @@ -24,7 +25,11 @@ test('pings', (t) => { }, }, }) - const ping = new Ping({ flatOptions }) + const npm = mockNpm({ + config: { registry }, + flatOptions: { registry }, + }) + const ping = new Ping(npm) ping.exec([], (err) => { t.equal(noticeCalls, 2, 'should have logged 2 lines') @@ -36,12 +41,12 @@ test('pings', (t) => { test('pings and logs details', (t) => { t.plan(10) - const flatOptions = { registry: 'https://registry.npmjs.org' } + const registry = 'https://registry.npmjs.org' const details = { extra: 'data' } let noticeCalls = 0 const Ping = requireInject('../../lib/ping.js', { '../../lib/utils/ping.js': function (spec) { - t.equal(spec, flatOptions, 'passes flatOptions') + t.equal(spec.registry, registry, 'passes flatOptions') return details }, npmlog: { @@ -49,7 +54,7 @@ test('pings and logs details', (t) => { ++noticeCalls if (noticeCalls === 1) { t.equal(type, 'PING', 'should log a PING') - t.equal(spec, flatOptions.registry, 'should log the registry url') + t.equal(spec, registry, 'should log the registry url') } else if (noticeCalls === 2) { t.equal(type, 'PONG', 'should log a PONG') t.match(spec, /\d+ms/, 'should log the elapsed milliseconds') @@ -61,7 +66,11 @@ test('pings and logs details', (t) => { }, }, }) - const ping = new Ping({ flatOptions }) + const npm = mockNpm({ + config: { registry }, + flatOptions: { registry }, + }) + const ping = new Ping(npm) ping.exec([], (err) => { t.equal(noticeCalls, 3, 'should have logged 3 lines') @@ -73,12 +82,12 @@ test('pings and logs details', (t) => { test('pings and returns json', (t) => { t.plan(11) - const flatOptions = { registry: 'https://registry.npmjs.org', json: true } + const registry = 'https://registry.npmjs.org' const details = { extra: 'data' } let noticeCalls = 0 const Ping = requireInject('../../lib/ping.js', { '../../lib/utils/ping.js': function (spec) { - t.equal(spec, flatOptions, 'passes flatOptions') + t.equal(spec.registry, registry, 'passes flatOptions') return details }, npmlog: { @@ -86,7 +95,7 @@ test('pings and returns json', (t) => { ++noticeCalls if (noticeCalls === 1) { t.equal(type, 'PING', 'should log a PING') - t.equal(spec, flatOptions.registry, 'should log the registry url') + t.equal(spec, registry, 'should log the registry url') } else { t.equal(type, 'PONG', 'should log a PONG') t.match(spec, /\d+ms/, 'should log the elapsed milliseconds') @@ -94,15 +103,17 @@ test('pings and returns json', (t) => { }, }, }) - const ping = new Ping({ - flatOptions, + const npm = mockNpm({ + config: { registry, json: true }, + flatOptions: { registry }, output: function (spec) { const parsed = JSON.parse(spec) - t.equal(parsed.registry, flatOptions.registry, 'returns the correct registry url') + t.equal(parsed.registry, registry, 'returns the correct registry url') t.match(parsed.details, details, 'prints returned details') t.type(parsed.time, 'number', 'returns time as a number') }, }) + const ping = new Ping(npm) ping.exec([], (err) => { t.equal(noticeCalls, 2, 'should have logged 2 lines') diff --git a/deps/npm/test/lib/profile.js b/deps/npm/test/lib/profile.js index d1be93b0cb..5b1210615a 100644 --- a/deps/npm/test/lib/profile.js +++ b/deps/npm/test/lib/profile.js @@ -1,20 +1,24 @@ const t = require('tap') const requireInject = require('require-inject') +const mockNpm = require('../fixtures/mock-npm') let result = '' -const flatOptions = { +const config = { otp: '', json: false, parseable: false, registry: 'https://registry.npmjs.org/', } -const npm = { - config: {}, - flatOptions: { ...flatOptions }, +const flatOptions = { + registry: 'https://registry.npmjs.org/', +} +const npm = mockNpm({ + config, + flatOptions, output: (...msg) => { result = result ? `${result}\n${msg.join('\n')}` : msg.join('\n') }, -} +}) const mocks = { ansistyles: { bright: a => a }, npmlog: { @@ -65,8 +69,10 @@ const userProfile = { t.afterEach(cb => { result = '' - npm.config = {} - npm.flatOptions = { ...flatOptions } + flatOptions.otp = '' + config.json = false + config.parseable = false + config.registry = 'https://registry.npmjs.org/' cb() }) @@ -111,7 +117,7 @@ t.test('profile get no args', t => { }) t.test('--json', t => { - npm.flatOptions.json = true + config.json = true profile.exec(['get'], err => { if (err) @@ -127,7 +133,7 @@ t.test('profile get no args', t => { }) t.test('--parseable', t => { - npm.flatOptions.parseable = true + config.parseable = true profile.exec(['get'], err => { if (err) @@ -256,7 +262,7 @@ t.test('profile get <key>', t => { }) t.test('--json', t => { - npm.flatOptions.json = true + config.json = true profile.exec(['get', 'name'], err => { if (err) @@ -272,7 +278,7 @@ t.test('profile get <key>', t => { }) t.test('--parseable', t => { - npm.flatOptions.parseable = true + config.parseable = true profile.exec(['get', 'name'], err => { if (err) @@ -316,7 +322,7 @@ t.test('profile get multiple args', t => { }) t.test('--json', t => { - npm.flatOptions.json = true + config.json = true profile.exec(['get', 'name', 'email', 'github'], err => { if (err) @@ -332,7 +338,7 @@ t.test('profile get multiple args', t => { }) t.test('--parseable', t => { - npm.flatOptions.parseable = true + config.parseable = true profile.exec(['get', 'name', 'email', 'github'], err => { if (err) @@ -451,7 +457,7 @@ t.test('profile set <key> <value>', t => { t.test('--json', t => { t.plan(2) - npm.flatOptions.json = true + config.json = true const Profile = requireInject('../../lib/profile.js', { ...mocks, @@ -476,7 +482,7 @@ t.test('profile set <key> <value>', t => { t.test('--parseable', t => { t.plan(2) - npm.flatOptions.parseable = true + config.parseable = true const Profile = requireInject('../../lib/profile.js', { ...mocks, @@ -705,7 +711,7 @@ t.test('enable-2fa', t => { }) t.test('no support for --json output', t => { - npm.flatOptions.json = true + config.json = true profile.exec(['enable-2fa', 'auth-only'], err => { t.match( @@ -719,7 +725,7 @@ t.test('enable-2fa', t => { }) t.test('no support for --parseable output', t => { - npm.flatOptions.parseable = true + config.parseable = true profile.exec(['enable-2fa', 'auth-only'], err => { t.match( @@ -817,18 +823,16 @@ t.test('enable-2fa', t => { t.plan(10) // mock legacy basic auth style - npm.config = { - getCredentialsByURI (reg) { - t.equal(reg, flatOptions.registry, 'should use expected registry') - return { auth: Buffer.from('foo:bar').toString('base64') } - }, - setCredentialsByURI (registry, { token }) { - t.equal(registry, flatOptions.registry, 'should set expected registry') - t.equal(token, 'token', 'should set expected token') - }, - save (type) { - t.equal(type, 'user', 'should save to user config') - }, + npm.config.getCredentialsByURI = (reg) => { + t.equal(reg, flatOptions.registry, 'should use expected registry') + return { auth: Buffer.from('foo:bar').toString('base64') } + } + npm.config.setCredentialsByURI = (registry, { token }) => { + t.equal(registry, flatOptions.registry, 'should set expected registry') + t.equal(token, 'token', 'should set expected token') + } + npm.config.save = (type) => { + t.equal(type, 'user', 'should save to user config') } const npmProfile = { @@ -901,12 +905,10 @@ t.test('enable-2fa', t => { t.test('from token and set otp, retries on pending and verifies with qrcode', t => { t.plan(4) - npm.flatOptions.otp = '1234' + flatOptions.otp = '1234' - npm.config = { - getCredentialsByURI () { - return { token: 'token' } - }, + npm.config.getCredentialsByURI = () => { + return { token: 'token' } } let setCount = 0 @@ -1003,12 +1005,10 @@ t.test('enable-2fa', t => { }) t.test('from token and set otp, retrieves invalid otp', t => { - npm.flatOptions.otp = '1234' + flatOptions.otp = '1234' - npm.config = { - getCredentialsByURI () { - return { token: 'token' } - }, + npm.config.getCredentialsByURI = () => { + return { token: 'token' } } const npmProfile = { @@ -1055,12 +1055,11 @@ t.test('enable-2fa', t => { }) t.test('from token auth provides --otp config arg', t => { - npm.flatOptions.otp = '123456' + flatOptions.otp = '123456' + flatOptions.otp = '123456' - npm.config = { - getCredentialsByURI (reg) { - return { token: 'token' } - }, + npm.config.getCredentialsByURI = (reg) => { + return { token: 'token' } } const npmProfile = { @@ -1105,10 +1104,8 @@ t.test('enable-2fa', t => { }) t.test('missing tfa from user profile', t => { - npm.config = { - getCredentialsByURI (reg) { - return { token: 'token' } - }, + npm.config.getCredentialsByURI = (reg) => { + return { token: 'token' } } const npmProfile = { @@ -1156,10 +1153,8 @@ t.test('enable-2fa', t => { }) t.test('defaults to auth-and-writes permission if no mode specified', t => { - npm.config = { - getCredentialsByURI (reg) { - return { token: 'token' } - }, + npm.config.getCredentialsByURI = (reg) => { + return { token: 'token' } } const npmProfile = { @@ -1303,7 +1298,7 @@ t.test('disable-2fa', t => { }) t.test('--json', t => { - npm.flatOptions.json = true + config.json = true const Profile = requireInject('../../lib/profile.js', { ...mocks, @@ -1326,7 +1321,7 @@ t.test('disable-2fa', t => { }) t.test('--parseable', t => { - npm.flatOptions.parseable = true + config.parseable = true const Profile = requireInject('../../lib/profile.js', { ...mocks, @@ -1354,7 +1349,7 @@ t.test('disable-2fa', t => { t.test('--otp config already set', t => { t.plan(3) - npm.flatOptions.otp = '123456' + flatOptions.otp = '123456' const npmProfile = { async get () { diff --git a/deps/npm/test/lib/publish.js b/deps/npm/test/lib/publish.js index 6337a1fcf0..f61377b54f 100644 --- a/deps/npm/test/lib/publish.js +++ b/deps/npm/test/lib/publish.js @@ -1,5 +1,6 @@ const t = require('tap') const requireInject = require('require-inject') +const mockNpm = require('../fixtures/mock-npm') const fs = require('fs') // The way we set loglevel is kind of convoluted, and there is no way to affect @@ -10,11 +11,13 @@ const log = require('npmlog') log.level = 'silent' // mock config -const {defaults} = require('../../lib/utils/config.js') +const {definitions} = require('../../lib/utils/config') +const defaults = Object.entries(definitions).reduce((defaults, [key, def]) => { + defaults[key] = def.default + return defaults +}, {}) -const config = { - list: [defaults], -} +const config = defaults t.afterEach(cb => { log.level = 'silent' @@ -54,18 +57,17 @@ t.test('should publish with libnpmpublish, passing through flatOptions and respe }, }, }) - const publish = new Publish({ + const npm = mockNpm({ + config, flatOptions: { customValue: true, }, - config: { - ...config, - getCredentialsByURI: (uri) => { - t.same(uri, registry, 'gets credentials for expected registry') - return { token: 'some.registry.token' } - }, - }, }) + npm.config.getCredentialsByURI = (uri) => { + t.same(uri, registry, 'gets credentials for expected registry') + return { token: 'some.registry.token' } + } + const publish = new Publish(npm) publish.exec([testDir], (er) => { if (er) @@ -104,15 +106,12 @@ t.test('re-loads publishConfig.registry if added during script process', (t) => }, }, }) - const publish = new Publish({ - config: { - ...config, - getCredentialsByURI: (uri) => { - t.same(uri, registry, 'gets credentials for expected registry') - return { token: 'some.registry.token' } - }, - }, - }) + const npm = mockNpm({ config }) + npm.config.getCredentialsByURI = (uri) => { + t.same(uri, registry, 'gets credentials for expected registry') + return { token: 'some.registry.token' } + } + const publish = new Publish(npm) publish.exec([testDir], (er) => { if (er) @@ -148,21 +147,17 @@ t.test('if loglevel=info and json, should not output package contents', (t) => { }, }, }) - const publish = new Publish({ - flatOptions: { - json: true, - }, - config: { - ...config, - getCredentialsByURI: (uri) => { - t.same(uri, defaults.registry, 'gets credentials for expected registry') - return { token: 'some.registry.token' } - }, - }, + const npm = mockNpm({ + config: { ...config, json: true }, output: () => { t.pass('output is called') }, }) + npm.config.getCredentialsByURI = (uri) => { + t.same(uri, defaults.registry, 'gets credentials for expected registry') + return { token: 'some.registry.token' } + } + const publish = new Publish(npm) publish.exec([testDir], (er) => { if (er) @@ -198,20 +193,17 @@ t.test('if loglevel=silent and dry-run, should not output package contents or pu }, }, }) - const publish = new Publish({ - flatOptions: { - dryRun: true, - }, - config: { - ...config, - getCredentialsByURI: () => { - throw new Error('should not call getCredentialsByURI in dry run') - }, - }, + const npm = mockNpm({ + config: { ...config, 'dry-run': true }, output: () => { throw new Error('should not output in dry run mode') }, }) + npm.config.getCredentialsByURI = () => { + throw new Error('should not call getCredentialsByURI in dry run') + } + + const publish = new Publish(npm) publish.exec([testDir], (er) => { if (er) @@ -247,20 +239,16 @@ t.test('if loglevel=info and dry-run, should not publish, should log package con }, }, }) - const publish = new Publish({ - flatOptions: { - dryRun: true, - }, - config: { - ...config, - getCredentialsByURI: () => { - throw new Error('should not call getCredentialsByURI in dry run') - }, - }, + const npm = mockNpm({ + config: { ...config, 'dry-run': true }, output: () => { t.pass('output fn is called') }, }) + npm.config.getCredentialsByURI = () => { + throw new Error('should not call getCredentialsByURI in dry run') + } + const publish = new Publish(npm) publish.exec([testDir], (er) => { if (er) @@ -285,12 +273,10 @@ t.test('throws when invalid tag', (t) => { t.plan(1) const Publish = requireInject('../../lib/publish.js') - const publish = new Publish({ - flatOptions: { - defaultTag: '0.0.13', - }, - config, + const npm = mockNpm({ + config: { ...config, tag: '0.0.13' }, }) + const publish = new Publish(npm) publish.exec([], (err) => { t.match(err, { @@ -331,15 +317,12 @@ t.test('can publish a tarball', t => { }, }, }) - const publish = new Publish({ - config: { - ...config, - getCredentialsByURI: (uri) => { - t.same(uri, defaults.registry, 'gets credentials for expected registry') - return { token: 'some.registry.token' } - }, - }, - }) + const npm = mockNpm({ config }) + npm.config.getCredentialsByURI = (uri) => { + t.same(uri, defaults.registry, 'gets credentials for expected registry') + return { token: 'some.registry.token' } + } + const publish = new Publish(npm) publish.exec([`${testDir}/tarball/package.tgz`], (er) => { if (er) @@ -352,15 +335,12 @@ t.test('can publish a tarball', t => { t.test('should check auth for default registry', t => { t.plan(2) const Publish = requireInject('../../lib/publish.js') - const publish = new Publish({ - config: { - ...config, - getCredentialsByURI: (uri) => { - t.same(uri, defaults.registry, 'gets credentials for expected registry') - return {} - }, - }, - }) + const npm = mockNpm({ config }) + npm.config.getCredentialsByURI = (uri) => { + t.same(uri, defaults.registry, 'gets credentials for expected registry') + return {} + } + const publish = new Publish(npm) publish.exec([], (err) => { t.match(err, { @@ -375,18 +355,15 @@ t.test('should check auth for configured registry', t => { t.plan(2) const registry = 'https://some.registry' const Publish = requireInject('../../lib/publish.js') - const publish = new Publish({ - flatOptions: { - registry, - }, - config: { - ...config, - getCredentialsByURI: (uri) => { - t.same(uri, registry, 'gets credentials for expected registry') - return {} - }, - }, + const npm = mockNpm({ + config, + flatOptions: { registry }, }) + npm.config.getCredentialsByURI = (uri) => { + t.same(uri, registry, 'gets credentials for expected registry') + return {} + } + const publish = new Publish(npm) publish.exec([], (err) => { t.match(err, { @@ -408,18 +385,15 @@ t.test('should check auth for scope specific registry', t => { }) const Publish = requireInject('../../lib/publish.js') - const publish = new Publish({ - flatOptions: { - '@npm:registry': registry, - }, - config: { - ...config, - getCredentialsByURI: (uri) => { - t.same(uri, registry, 'gets credentials for expected registry') - return {} - }, - }, + const npm = mockNpm({ + config, + flatOptions: { '@npm:registry': registry }, }) + npm.config.getCredentialsByURI = (uri) => { + t.same(uri, registry, 'gets credentials for expected registry') + return {} + } + const publish = new Publish(npm) publish.exec([testDir], (err) => { t.match(err, { @@ -448,18 +422,16 @@ t.test('should use auth for scope specific registry', t => { }, }, }) - const publish = new Publish({ - flatOptions: { - '@npm:registry': registry, - }, - config: { - ...config, - getCredentialsByURI: (uri) => { - t.same(uri, registry, 'gets credentials for expected registry') - return { token: 'some.registry.token' } - }, - }, + const npm = mockNpm({ + config, + flatOptions: { '@npm:registry': registry }, }) + npm.config.getCredentialsByURI = (uri) => { + t.same(uri, registry, 'gets credentials for expected registry') + return { token: 'some.registry.token' } + } + const publish = new Publish(npm) + publish.exec([testDir], (er) => { if (er) throw er @@ -489,9 +461,60 @@ t.test('read registry only from publishConfig', t => { }, }, }) + const npm = mockNpm({ + config, + }) + npm.config.getCredentialsByURI = (uri) => { + t.same(uri, registry, 'gets credentials for expected registry') + return { token: 'some.registry.token' } + } + const publish = new Publish(npm) + + publish.exec([testDir], (er) => { + if (er) + throw er + t.pass('got to callback') + t.end() + }) +}) + +t.test('able to publish after if encountered multiple configs', t => { + t.plan(3) + + const registry = 'https://some.registry' + const tag = 'better-tag' + const publishConfig = { registry } + const testDir = t.testdir({ + 'package.json': JSON.stringify({ + name: 'my-cool-pkg', + version: '1.0.0', + publishConfig, + }, null, 2), + }) + + const configList = [defaults] + configList.unshift(Object.assign(Object.create(configList[0]), { + registry: `https://other.registry`, + tag: 'some-tag', + })) + configList.unshift(Object.assign(Object.create(configList[0]), { tag })) + + const Publish = requireInject('../../lib/publish.js', { + libnpmpublish: { + publish: (manifest, tarData, opts) => { + t.same(opts.defaultTag, tag, 'gets option for expected tag') + }, + }, + }) const publish = new Publish({ + // what would be flattened by the configList created above + flatOptions: { + defaultTag: 'better-tag', + registry: 'https://other.registry', + }, config: { - ...config, + get: key => configList[0][key], + list: configList, getCredentialsByURI: (uri) => { t.same(uri, registry, 'gets credentials for expected registry') return { token: 'some.registry.token' } diff --git a/deps/npm/test/lib/rebuild.js b/deps/npm/test/lib/rebuild.js index 1eb45e0d1d..6e144b7e11 100644 --- a/deps/npm/test/lib/rebuild.js +++ b/deps/npm/test/lib/rebuild.js @@ -1,25 +1,27 @@ const fs = require('fs') const { resolve } = require('path') +const mockNpm = require('../fixtures/mock-npm') const t = require('tap') let result = '' -const npm = { +const config = { + global: false, +} +const npm = mockNpm({ globalDir: '', - flatOptions: { - global: false, - }, + config, prefix: '', output: (...msg) => { result += msg.join('\n') }, -} +}) const Rebuild = require('../../lib/rebuild.js') const rebuild = new Rebuild(npm) t.afterEach(cb => { npm.prefix = '' - npm.flatOptions.global = false + config.global = false npm.globalDir = '' result = '' cb() @@ -34,7 +36,7 @@ t.test('no args', t => { version: '1.0.0', bin: 'cwd', scripts: { - preinstall: `node -e 'require("fs").writeFileSync("cwd", "")'`, + preinstall: "node -e \"require('fs').writeFileSync('cwd', '')\"", }, }), }, @@ -44,7 +46,7 @@ t.test('no args', t => { version: '1.0.0', bin: 'cwd', scripts: { - preinstall: `node -e 'require("fs").writeFileSync("cwd", "")'`, + preinstall: "node -e \"require('fs').writeFileSync('cwd', '')\"", }, }), }, @@ -237,7 +239,7 @@ t.test('global prefix', t => { }, }) - npm.flatOptions.global = true + config.global = true npm.globalDir = resolve(globalPath, 'lib', 'node_modules') rebuild.exec([], err => { diff --git a/deps/npm/test/lib/run-script.js b/deps/npm/test/lib/run-script.js index 0566daf234..f7eb46fedf 100644 --- a/deps/npm/test/lib/run-script.js +++ b/deps/npm/test/lib/run-script.js @@ -1,37 +1,60 @@ +const { resolve } = require('path') const t = require('tap') const requireInject = require('require-inject') +const mockNpm = require('../fixtures/mock-npm') + +const normalizePath = p => p + .replace(/\\+/g, '/') + .replace(/\r\n/g, '\n') + +const cleanOutput = (str) => normalizePath(str) + .replace(normalizePath(process.cwd()), '{CWD}') const RUN_SCRIPTS = [] -const npm = { +const flatOptions = { + scriptShell: undefined, +} +const config = { + json: false, + parseable: false, + 'if-present': false, +} + +const npm = mockNpm({ localPrefix: __dirname, - flatOptions: { - scriptShell: undefined, - json: false, - parseable: false, - }, - config: { - settings: { - 'if-present': false, + flatOptions, + config, + commands: { + help: { + description: 'test help description', }, - get: k => npm.config.settings[k], - set: (k, v) => { - npm.config.settings[k] = v + test: { + description: 'test test description', }, }, output: (...msg) => output.push(msg), -} +}) const output = [] +const npmlog = { + disableProgress: () => null, + level: 'warn', + error: () => null, +} + t.afterEach(cb => { + npm.color = false + npmlog.level = 'warn' + npmlog.error = () => null output.length = 0 RUN_SCRIPTS.length = 0 - npm.flatOptions.json = false - npm.flatOptions.parseable = false + config['if-present'] = false + config.json = false + config.parseable = false cb() }) -const npmlog = { level: 'warn' } const getRS = windows => { const RunScript = requireInject('../../lib/run-script.js', { '@npmcli/run-script': Object.assign(async opts => { @@ -261,26 +284,41 @@ t.test('try to run missing script', t => { npm.localPrefix = t.testdir({ 'package.json': JSON.stringify({ scripts: { hello: 'world' }, + bin: { goodnight: 'moon' }, }), }) t.test('no suggestions', t => { runScript.exec(['notevenclose'], er => { t.match(er, { - message: 'missing script: notevenclose', + message: 'Missing script: "notevenclose"', }) t.end() }) }) - t.test('suggestions', t => { + t.test('script suggestions', t => { runScript.exec(['helo'], er => { t.match(er, { - message: 'missing script: helo\n\nDid you mean this?\n hello', + message: 'Missing script: "helo"', + }) + t.match(er, { + message: 'npm run hello', + }) + t.end() + }) + }) + t.test('bin suggestions', t => { + runScript.exec(['goodneght'], er => { + t.match(er, { + message: 'Missing script: "goodneght"', + }) + t.match(er, { + message: 'npm exec goodnight', }) t.end() }) }) t.test('with --if-present', t => { - npm.config.set('if-present', true) + config['if-present'] = true runScript.exec(['goodbye'], er => { if (er) throw er @@ -331,7 +369,7 @@ t.test('run pre/post hooks', t => { }) t.test('skip pre/post hooks when using ignoreScripts', t => { - npm.flatOptions.ignoreScripts = true + config['ignore-scripts'] = true npm.localPrefix = t.testdir({ 'package.json': JSON.stringify({ @@ -368,7 +406,7 @@ t.test('skip pre/post hooks when using ignoreScripts', t => { }, ]) t.end() - delete npm.flatOptions.ignoreScripts + delete config['ignore-scripts'] }) }) @@ -443,13 +481,14 @@ t.test('list scripts', t => { if (er) throw er t.strictSame(output, [ - ['Lifecycle scripts included in x:'], + ['Lifecycle scripts included in x@1.2.3:'], [' test\n exit 2'], [' start\n node server.js'], [' stop\n node kill-server.js'], ['\navailable via `npm run-script`:'], [' preenv\n echo before the env'], [' postenv\n echo after the env'], + [''], ], 'basic report') t.end() }) @@ -466,7 +505,7 @@ t.test('list scripts', t => { }) t.test('warn json', t => { npmlog.level = 'warn' - npm.flatOptions.json = true + config.json = true runScript.exec([], er => { if (er) throw er @@ -476,7 +515,7 @@ t.test('list scripts', t => { }) t.test('parseable', t => { - npm.flatOptions.parseable = true + config.parseable = true runScript.exec([], er => { if (er) throw er @@ -522,8 +561,9 @@ t.test('list scripts, only commands', t => { if (er) throw er t.strictSame(output, [ - ['Lifecycle scripts included in x:'], + ['Lifecycle scripts included in x@1.2.3:'], [' preversion\n echo doing the version dance'], + [''], ]) t.end() }) @@ -542,9 +582,443 @@ t.test('list scripts, only non-commands', t => { if (er) throw er t.strictSame(output, [ - ['Scripts available in x via `npm run-script`:'], + ['Scripts available in x@1.2.3 via `npm run-script`:'], [' glorp\n echo doing the glerp glop'], + [''], ]) t.end() }) }) + +t.test('workspaces', t => { + npm.localPrefix = t.testdir({ + packages: { + a: { + 'package.json': JSON.stringify({ + name: 'a', + version: '1.0.0', + scripts: { glorp: 'echo a doing the glerp glop' }, + }), + }, + b: { + 'package.json': JSON.stringify({ + name: 'b', + version: '2.0.0', + scripts: { glorp: 'echo b doing the glerp glop' }, + }), + }, + c: { + 'package.json': JSON.stringify({ + name: 'c', + version: '1.0.0', + scripts: { + test: 'exit 0', + posttest: 'echo posttest', + lorem: 'echo c lorem', + }, + }), + }, + d: { + 'package.json': JSON.stringify({ + name: 'd', + version: '1.0.0', + scripts: { + test: 'exit 0', + posttest: 'echo posttest', + }, + }), + }, + e: { + 'package.json': JSON.stringify({ + name: 'e', + scripts: { test: 'exit 0', start: 'echo start something' }, + }), + }, + noscripts: { + 'package.json': JSON.stringify({ + name: 'noscripts', + version: '1.0.0', + }), + }, + }, + 'package.json': JSON.stringify({ + name: 'x', + version: '1.2.3', + workspaces: ['packages/*'], + }), + }) + + t.test('list all scripts', t => { + runScript.execWorkspaces([], [], er => { + if (er) + throw er + t.strictSame(output, [ + ['Scripts available in a@1.0.0 via `npm run-script`:'], + [' glorp\n echo a doing the glerp glop'], + [''], + ['Scripts available in b@2.0.0 via `npm run-script`:'], + [' glorp\n echo b doing the glerp glop'], + [''], + ['Lifecycle scripts included in c@1.0.0:'], + [' test\n exit 0'], + [' posttest\n echo posttest'], + ['\navailable via `npm run-script`:'], + [' lorem\n echo c lorem'], + [''], + ['Lifecycle scripts included in d@1.0.0:'], + [' test\n exit 0'], + [' posttest\n echo posttest'], + [''], + ['Lifecycle scripts included in e:'], + [' test\n exit 0'], + [' start\n echo start something'], + [''], + ]) + t.end() + }) + }) + + t.test('list regular scripts, filtered by name', t => { + runScript.execWorkspaces([], ['a', 'b'], er => { + if (er) + throw er + t.strictSame(output, [ + ['Scripts available in a@1.0.0 via `npm run-script`:'], + [' glorp\n echo a doing the glerp glop'], + [''], + ['Scripts available in b@2.0.0 via `npm run-script`:'], + [' glorp\n echo b doing the glerp glop'], + [''], + ]) + t.end() + }) + }) + + t.test('list regular scripts, filtered by path', t => { + runScript.execWorkspaces([], ['./packages/a'], er => { + if (er) + throw er + t.strictSame(output, [ + ['Scripts available in a@1.0.0 via `npm run-script`:'], + [' glorp\n echo a doing the glerp glop'], + [''], + ]) + t.end() + }) + }) + + t.test('list regular scripts, filtered by parent folder', t => { + runScript.execWorkspaces([], ['./packages'], er => { + if (er) + throw er + t.strictSame(output, [ + ['Scripts available in a@1.0.0 via `npm run-script`:'], + [' glorp\n echo a doing the glerp glop'], + [''], + ['Scripts available in b@2.0.0 via `npm run-script`:'], + [' glorp\n echo b doing the glerp glop'], + [''], + ['Lifecycle scripts included in c@1.0.0:'], + [' test\n exit 0'], + [' posttest\n echo posttest'], + ['\navailable via `npm run-script`:'], + [' lorem\n echo c lorem'], + [''], + ['Lifecycle scripts included in d@1.0.0:'], + [' test\n exit 0'], + [' posttest\n echo posttest'], + [''], + ['Lifecycle scripts included in e:'], + [' test\n exit 0'], + [' start\n echo start something'], + [''], + ]) + t.end() + }) + }) + + t.test('list all scripts with colors', t => { + npm.color = true + runScript.execWorkspaces([], [], er => { + if (er) + throw er + t.strictSame(output, [ + [ + '\u001b[1mScripts\u001b[22m available in \x1B[32ma@1.0.0\x1B[39m via `\x1B[34mnpm run-script\x1B[39m`:', + ], + [' glorp\n \x1B[2mecho a doing the glerp glop\x1B[22m'], + [''], + [ + '\u001b[1mScripts\u001b[22m available in \x1B[32mb@2.0.0\x1B[39m via `\x1B[34mnpm run-script\x1B[39m`:', + ], + [' glorp\n \x1B[2mecho b doing the glerp glop\x1B[22m'], + [''], + [ + '\x1B[0m\x1B[1mLifecycle scripts\x1B[22m\x1B[0m included in \x1B[32mc@1.0.0\x1B[39m:', + ], + [' test\n \x1B[2mexit 0\x1B[22m'], + [' posttest\n \x1B[2mecho posttest\x1B[22m'], + ['\navailable via `\x1B[34mnpm run-script\x1B[39m`:'], + [' lorem\n \x1B[2mecho c lorem\x1B[22m'], + [''], + [ + '\x1B[0m\x1B[1mLifecycle scripts\x1B[22m\x1B[0m included in \x1B[32md@1.0.0\x1B[39m:', + ], + [' test\n \x1B[2mexit 0\x1B[22m'], + [' posttest\n \x1B[2mecho posttest\x1B[22m'], + [''], + [ + '\x1B[0m\x1B[1mLifecycle scripts\x1B[22m\x1B[0m included in \x1B[32me\x1B[39m:', + ], + [' test\n \x1B[2mexit 0\x1B[22m'], + [' start\n \x1B[2mecho start something\x1B[22m'], + [''], + ]) + t.end() + }) + }) + + t.test('list all scripts --json', t => { + config.json = true + runScript.execWorkspaces([], [], er => { + if (er) + throw er + t.strictSame(output, [ + [ + '{\n' + + ' "a": {\n' + + ' "glorp": "echo a doing the glerp glop"\n' + + ' },\n' + + ' "b": {\n' + + ' "glorp": "echo b doing the glerp glop"\n' + + ' },\n' + + ' "c": {\n' + + ' "test": "exit 0",\n' + + ' "posttest": "echo posttest",\n' + + ' "lorem": "echo c lorem"\n' + + ' },\n' + + ' "d": {\n' + + ' "test": "exit 0",\n' + + ' "posttest": "echo posttest"\n' + + ' },\n' + + ' "e": {\n' + + ' "test": "exit 0",\n' + + ' "start": "echo start something"\n' + + ' },\n' + + ' "noscripts": {}\n' + + '}', + ], + ]) + t.end() + }) + }) + + t.test('list all scripts --parseable', t => { + config.parseable = true + runScript.execWorkspaces([], [], er => { + if (er) + throw er + t.strictSame(output, [ + ['a:glorp:echo a doing the glerp glop'], + ['b:glorp:echo b doing the glerp glop'], + ['c:test:exit 0'], + ['c:posttest:echo posttest'], + ['c:lorem:echo c lorem'], + ['d:test:exit 0'], + ['d:posttest:echo posttest'], + ['e:test:exit 0'], + ['e:start:echo start something'], + ]) + t.end() + }) + }) + + t.test('list no scripts --loglevel=silent', t => { + npmlog.level = 'silent' + runScript.execWorkspaces([], [], er => { + if (er) + throw er + t.strictSame(output, []) + t.end() + }) + }) + + t.test('run scripts across all workspaces', t => { + runScript.execWorkspaces(['test'], [], er => { + if (er) + throw er + + t.match(RUN_SCRIPTS, [ + { + path: resolve(npm.localPrefix, 'packages/c'), + pkg: { name: 'c', version: '1.0.0' }, + event: 'test', + }, + { + path: resolve(npm.localPrefix, 'packages/c'), + pkg: { name: 'c', version: '1.0.0' }, + event: 'posttest', + }, + { + path: resolve(npm.localPrefix, 'packages/d'), + pkg: { name: 'd', version: '1.0.0' }, + event: 'test', + }, + { + path: resolve(npm.localPrefix, 'packages/d'), + pkg: { name: 'd', version: '1.0.0' }, + event: 'posttest', + }, + { + path: resolve(npm.localPrefix, 'packages/e'), + pkg: { name: 'e' }, + event: 'test', + }, + ]) + t.end() + }) + }) + + t.test('missing scripts in all workspaces', t => { + const LOG = [] + npmlog.error = (err) => { + LOG.push(String(err)) + } + runScript.execWorkspaces(['missing-script'], [], er => { + t.match( + er, + /Missing script: missing-script/, + 'should throw missing script error' + ) + + process.exitCode = 0 // clean exit code + + t.match(RUN_SCRIPTS, []) + t.strictSame(LOG.map(cleanOutput), [ + 'Lifecycle script `missing-script` failed with error:', + 'Error: Missing script: "missing-script"\n\nTo see a list of scripts, run:\n npm run', + ' in workspace: a@1.0.0', + ' at location: {CWD}/test/lib/run-script-workspaces/packages/a', + 'Lifecycle script `missing-script` failed with error:', + 'Error: Missing script: "missing-script"\n\nTo see a list of scripts, run:\n npm run', + ' in workspace: b@2.0.0', + ' at location: {CWD}/test/lib/run-script-workspaces/packages/b', + 'Lifecycle script `missing-script` failed with error:', + 'Error: Missing script: "missing-script"\n\nTo see a list of scripts, run:\n npm run', + ' in workspace: c@1.0.0', + ' at location: {CWD}/test/lib/run-script-workspaces/packages/c', + 'Lifecycle script `missing-script` failed with error:', + 'Error: Missing script: "missing-script"\n\nTo see a list of scripts, run:\n npm run', + ' in workspace: d@1.0.0', + ' at location: {CWD}/test/lib/run-script-workspaces/packages/d', + 'Lifecycle script `missing-script` failed with error:', + 'Error: Missing script: "missing-script"\n\nTo see a list of scripts, run:\n npm run', + ' in workspace: e', + ' at location: {CWD}/test/lib/run-script-workspaces/packages/e', + 'Lifecycle script `missing-script` failed with error:', + 'Error: Missing script: "missing-script"\n\nTo see a list of scripts, run:\n npm run', + ' in workspace: noscripts@1.0.0', + ' at location: {CWD}/test/lib/run-script-workspaces/packages/noscripts', + ], 'should log error msgs for each workspace script') + + t.end() + }) + }) + + t.test('missing scripts in some workspaces', t => { + const LOG = [] + npmlog.error = (err) => { + LOG.push(String(err)) + } + runScript.execWorkspaces(['test'], ['a', 'b', 'c', 'd'], er => { + if (er) + throw er + + t.match(RUN_SCRIPTS, []) + t.strictSame(LOG.map(cleanOutput), [ + 'Lifecycle script `test` failed with error:', + 'Error: Missing script: "test"\n\nTo see a list of scripts, run:\n npm run', + ' in workspace: a@1.0.0', + ' at location: {CWD}/test/lib/run-script-workspaces/packages/a', + 'Lifecycle script `test` failed with error:', + 'Error: Missing script: "test"\n\nTo see a list of scripts, run:\n npm run', + ' in workspace: b@2.0.0', + ' at location: {CWD}/test/lib/run-script-workspaces/packages/b', + ], 'should log error msgs for each workspace script') + t.end() + }) + }) + + t.test('no workspaces when filtering by user args', t => { + runScript.execWorkspaces([], ['foo', 'bar'], er => { + t.equal( + er.message, + 'No workspaces found:\n --workspace=foo --workspace=bar', + 'should throw error msg' + ) + t.end() + }) + }) + + t.test('no workspaces', t => { + const _prevPrefix = npm.localPrefix + npm.localPrefix = t.testdir({ + 'package.json': JSON.stringify({ + name: 'foo', + version: '1.0.0', + }), + }) + + runScript.execWorkspaces([], [], er => { + t.match(er, /No workspaces found!/, 'should throw error msg') + npm.localPrefix = _prevPrefix + t.end() + }) + }) + + t.test('single failed workspace run', t => { + const RunScript = requireInject('../../lib/run-script.js', { + '@npmcli/run-script': () => { + throw new Error('err') + }, + npmlog, + '../../lib/utils/is-windows-shell.js': false, + }) + const runScript = new RunScript(npm) + + runScript.execWorkspaces(['test'], ['c'], er => { + t.ok('should complete running all targets') + process.exitCode = 0 // clean up exit code + t.end() + }) + }) + + t.test('failed workspace run with succeeded runs', t => { + const RunScript = requireInject('../../lib/run-script.js', { + '@npmcli/run-script': async opts => { + if (opts.pkg.name === 'a') + throw new Error('ERR') + + RUN_SCRIPTS.push(opts) + }, + npmlog, + '../../lib/utils/is-windows-shell.js': false, + }) + const runScript = new RunScript(npm) + + runScript.execWorkspaces(['glorp'], ['a', 'b'], er => { + t.match(RUN_SCRIPTS, [ + { + path: resolve(npm.localPrefix, 'packages/b'), + pkg: { name: 'b', version: '2.0.0' }, + event: 'glorp', + }, + ]) + + process.exitCode = 0 // clean up exit code + t.end() + }) + }) + + t.end() +}) diff --git a/deps/npm/test/lib/search.js b/deps/npm/test/lib/search.js index b1ba7775c7..b7b4084421 100644 --- a/deps/npm/test/lib/search.js +++ b/deps/npm/test/lib/search.js @@ -1,6 +1,7 @@ const Minipass = require('minipass') const t = require('tap') const requireInject = require('require-inject') +const mockNpm = require('../fixtures/mock-npm') const libnpmsearchResultFixture = require('../fixtures/libnpmsearch-stream-result.js') @@ -12,12 +13,17 @@ const flatOptions = { opts: '', }, } -const npm = { +const config = { + json: false, + parseable: false, +} +const npm = mockNpm({ + config, flatOptions: { ...flatOptions }, output: (...msg) => { result += msg.join('\n') }, -} +}) const npmlog = { silly () {}, clearProgress () {}, @@ -29,12 +35,13 @@ const mocks = { npmlog, libnpmsearch, '../../lib/utils/usage.js': () => 'usage instructions', - // '../../lib/search/format-package-stream.js': a => a, } t.afterEach(cb => { result = '' - npm.flatOptions = flatOptions + config.json = false + config.parseable = false + npm.flatOptions = { ...flatOptions } cb() }) @@ -86,7 +93,8 @@ t.test('search <name> --json', (t) => { const src = new Minipass() src.objectMode = true - flatOptions.json = true + npm.flatOptions.json = true + config.json = true const libnpmsearch = { stream () { return src @@ -114,7 +122,7 @@ t.test('search <name> --json', (t) => { 'should have expected search results as json' ) - flatOptions.json = false + config.json = false t.end() }) diff --git a/deps/npm/test/lib/set-script.js b/deps/npm/test/lib/set-script.js index 7a057c5036..b6b6e2519f 100644 --- a/deps/npm/test/lib/set-script.js +++ b/deps/npm/test/lib/set-script.js @@ -31,6 +31,7 @@ test.test('fails when package.json not found', (t) => { }) test.test('fails on invalid JSON', (t) => { const SetScript = requireInject('../../lib/set-script.js', { + '../../lib/utils/config/definitions.js': {}, fs: { readFile: () => {}, // read-package-json-fast explodes w/o this readFileSync: (name, charcode) => { @@ -45,6 +46,7 @@ test.test('fails on invalid JSON', (t) => { test.test('creates scripts object', (t) => { var mockFile = '' const SetScript = requireInject('../../lib/set-script.js', { + '../../lib/utils/config/definitions.js': {}, fs: { readFileSync: (name, charcode) => { return '{}' @@ -70,6 +72,7 @@ test.test('creates scripts object', (t) => { test.test('warns before overwriting', (t) => { var warningListened = '' const SetScript = requireInject('../../lib/set-script.js', { + '../../lib/utils/config/definitions.js': {}, fs: { readFileSync: (name, charcode) => { return JSON.stringify({ @@ -102,6 +105,7 @@ test.test('warns before overwriting', (t) => { test.test('provided indentation and eol is used', (t) => { var mockFile = '' const SetScript = requireInject('../../lib/set-script.js', { + '../../lib/utils/config/definitions.js': {}, fs: { readFileSync: (name, charcode) => { return '{}' @@ -128,6 +132,7 @@ test.test('provided indentation and eol is used', (t) => { test.test('goes to default when undefined indent and eol provided', (t) => { var mockFile = '' const SetScript = requireInject('../../lib/set-script.js', { + '../../lib/utils/config/definitions.js': {}, fs: { readFileSync: (name, charcode) => { return '{}' diff --git a/deps/npm/test/lib/shrinkwrap.js b/deps/npm/test/lib/shrinkwrap.js index dc4bc3b220..faf452ea70 100644 --- a/deps/npm/test/lib/shrinkwrap.js +++ b/deps/npm/test/lib/shrinkwrap.js @@ -1,16 +1,21 @@ const t = require('tap') const fs = require('fs') const requireInject = require('require-inject') +const mockNpm = require('../fixtures/mock-npm') -const npm = { +const config = { + global: false, +} +const flatOptions = { + depth: 0, +} +const npm = mockNpm({ + config, + flatOptions, lockfileVersion: 2, globalDir: '', - flatOptions: { - depth: 0, - global: false, - }, prefix: '', -} +}) const tree = { meta: { hiddenLockfile: null, @@ -32,11 +37,12 @@ const mocks = { } }, '../../lib/utils/usage.js': () => 'usage instructions', + '../../lib/utils/config/definitions.js': {}, } t.afterEach(cb => { npm.prefix = '' - npm.flatOptions.global = false + config.global = false npm.globalDir = '' cb() }) @@ -50,7 +56,7 @@ t.test('no args', t => { constructor (args) { t.deepEqual( args, - { ...npm.flatOptions, path: npm.prefix }, + { ...flatOptions, path: npm.prefix }, 'should call arborist constructor with expected args' ) } @@ -101,7 +107,7 @@ t.test('no virtual tree', t => { constructor (args) { t.deepEqual( args, - { ...npm.flatOptions, path: npm.prefix }, + { ...flatOptions, path: npm.prefix }, 'should call arborist constructor with expected args' ) } @@ -156,7 +162,7 @@ t.test('existing package-json file', t => { constructor (args) { t.deepEqual( args, - { ...npm.flatOptions, path: npm.prefix }, + { ...flatOptions, path: npm.prefix }, 'should call arborist constructor with expected args' ) } @@ -218,7 +224,7 @@ t.test('update shrinkwrap file version', t => { constructor (args) { t.deepEqual( args, - { ...npm.flatOptions, path: npm.prefix }, + { ...flatOptions, path: npm.prefix }, 'should call arborist constructor with expected args' ) } @@ -272,7 +278,7 @@ t.test('update to date shrinkwrap file', t => { constructor (args) { t.deepEqual( args, - { ...npm.flatOptions, path: npm.prefix }, + { ...flatOptions, path: npm.prefix }, 'should call arborist constructor with expected args' ) } @@ -320,7 +326,7 @@ t.test('update to date shrinkwrap file', t => { t.test('shrinkwrap --global', t => { const Shrinkwrap = requireInject('../../lib/shrinkwrap.js', mocks) - npm.flatOptions.global = true + config.global = true const shrinkwrap = new Shrinkwrap(npm) shrinkwrap.exec([], err => { diff --git a/deps/npm/test/lib/star.js b/deps/npm/test/lib/star.js index 774fabe392..fa75d21057 100644 --- a/deps/npm/test/lib/star.js +++ b/deps/npm/test/lib/star.js @@ -1,16 +1,20 @@ const requireInject = require('require-inject') +const mockNpm = require('../fixtures/mock-npm') const t = require('tap') let result = '' const noop = () => null -const npm = { - config: { get () {} }, - flatOptions: { unicode: false }, +const config = { + unicode: false, + 'star.unstar': false, +} +const npm = mockNpm({ + config, output: (...msg) => { result += msg.join('\n') }, -} +}) const npmFetch = { json: noop } const npmlog = { error: noop, info: noop, verbose: noop } const mocks = { @@ -24,8 +28,8 @@ const Star = requireInject('../../lib/star.js', mocks) const star = new Star(npm) t.afterEach(cb => { - npm.config = { get () {} } - npm.flatOptions.unicode = false + config.unicode = false + config['star.unstar'] = false npmlog.info = noop result = '' cb() @@ -73,7 +77,7 @@ t.test('star a package', t => { t.test('unstar a package', t => { t.plan(4) const pkgName = '@npmcli/arborist' - npm.config.get = key => key === 'star.unstar' + config['star.unstar'] = true npmFetch.json = async (uri, opts) => ({ _id: pkgName, _rev: 'hash', @@ -100,7 +104,7 @@ t.test('unstar a package', t => { t.test('unicode', async t => { t.test('star a package', t => { - npm.flatOptions.unicode = true + config.unicode = true npmFetch.json = async (uri, opts) => ({}) star.exec(['pkg'], err => { if (err) @@ -115,8 +119,8 @@ t.test('unicode', async t => { }) t.test('unstar a package', t => { - npm.flatOptions.unicode = true - npm.config.get = key => key === 'star.unstar' + config.unicode = true + config['star.unstar'] = true npmFetch.json = async (uri, opts) => ({}) star.exec(['pkg'], err => { if (err) diff --git a/deps/npm/test/lib/uninstall.js b/deps/npm/test/lib/uninstall.js index c62b59950b..5cb8a243ec 100644 --- a/deps/npm/test/lib/uninstall.js +++ b/deps/npm/test/lib/uninstall.js @@ -2,18 +2,18 @@ const fs = require('fs') const { resolve } = require('path') const t = require('tap') const requireInject = require('require-inject') +const mockNpm = require('../fixtures/mock-npm') -const npm = { +const npm = mockNpm({ globalDir: '', - flatOptions: { + config: { global: false, prefix: '', }, localPrefix: '', -} +}) const mocks = { '../../lib/utils/reify-finish.js': () => Promise.resolve(), - '../../lib/utils/usage.js': () => 'usage instructions', } const Uninstall = requireInject('../../lib/uninstall.js', mocks) @@ -85,13 +85,13 @@ t.test('remove single installed lib', t => { const b = resolve(path, 'node_modules/b') t.ok(() => fs.statSync(b)) - npm.flatOptions.prefix = path + npm.config.set('prefix', path) uninstall.exec(['b'], err => { if (err) throw err - t.throws(() => fs.statSync(b), 'should have removed package from nm') + t.throws(() => fs.statSync(b), 'should have removed package from npm') t.end() }) }) @@ -148,7 +148,7 @@ t.test('remove multiple installed libs', t => { t.ok(() => fs.statSync(a)) t.ok(() => fs.statSync(b)) - npm.flatOptions.prefix = path + npm.config.set('prefix', path) uninstall.exec(['b'], err => { if (err) @@ -195,8 +195,8 @@ t.test('no args global', t => { npm.localPrefix = resolve(path, 'projects', 'a') npm.globalDir = resolve(path, 'lib', 'node_modules') - npm.flatOptions.global = true - npm.flatOptions.prefix = path + npm.config.set('global', true) + npm.config.set('prefix', path) const a = resolve(path, 'lib/node_modules/a') t.ok(() => fs.statSync(a)) @@ -221,8 +221,7 @@ t.test('no args global but no package.json', t => { uninstall.exec([], err => { t.match( err, - 'usage instructions', - 'should throw usage instructions' + 'npm uninstall' ) t.end() diff --git a/deps/npm/test/lib/unpublish.js b/deps/npm/test/lib/unpublish.js index b1255b94a8..ba99b53303 100644 --- a/deps/npm/test/lib/unpublish.js +++ b/deps/npm/test/lib/unpublish.js @@ -1,19 +1,21 @@ const t = require('tap') const requireInject = require('require-inject') +const mockNpm = require('../fixtures/mock-npm') let result = '' const noop = () => null -const npm = { +const config = { + force: false, + silent: false, + loglevel: 'silly', +} +const npm = mockNpm({ localPrefix: '', - flatOptions: { - force: false, - silent: false, - loglevel: 'silly', - }, + config, output: (...msg) => { result += msg.join('\n') }, -} +}) const mocks = { npmlog: { silly () {}, verbose () {} }, libnpmaccess: { lsPackages: noop }, @@ -28,16 +30,16 @@ const mocks = { t.afterEach(cb => { result = '' - npm.flatOptions.force = false - npm.flatOptions.loglevel = 'silly' - npm.flatOptions.silent = false + config.force = false + config.loglevel = 'silly' + config.silent = false cb() }) t.test('no args --force', t => { t.plan(9) - npm.flatOptions.force = true + config.force = true const npmlog = { silly (title) { @@ -67,9 +69,6 @@ t.test('no args --force', t => { t.deepEqual( opts, { - force: true, - silent: false, - loglevel: 'silly', publishConfig: undefined, }, 'should unpublish with expected opts' @@ -102,7 +101,7 @@ t.test('no args --force', t => { }) t.test('no args --force missing package.json', t => { - npm.flatOptions.force = true + config.force = true const Unpublish = requireInject('../../lib/unpublish.js', { ...mocks, @@ -124,7 +123,7 @@ t.test('no args --force missing package.json', t => { }) t.test('no args --force unknown error reading package.json', t => { - npm.flatOptions.force = true + config.force = true const Unpublish = requireInject('../../lib/unpublish.js', { ...mocks, @@ -200,11 +199,7 @@ t.test('unpublish <pkg>@version', t => { t.equal(spec, pa, 'should unpublish expected parsed spec') t.deepEqual( opts, - { - force: false, - silent: false, - loglevel: 'silly', - }, + {}, 'should unpublish with expected opts' ) }, @@ -231,7 +226,7 @@ t.test('unpublish <pkg>@version', t => { }) t.test('no version found in package.json', t => { - npm.flatOptions.force = true + config.force = true const npa = () => ({ name: 'pkg', @@ -263,7 +258,7 @@ t.test('no version found in package.json', t => { }) t.test('unpublish <pkg> --force no version set', t => { - npm.flatOptions.force = true + config.force = true const Unpublish = requireInject('../../lib/unpublish.js', { ...mocks, @@ -289,7 +284,7 @@ t.test('unpublish <pkg> --force no version set', t => { }) t.test('silent', t => { - npm.flatOptions.loglevel = 'silent' + config.loglevel = 'silent' const npa = () => ({ name: 'pkg', diff --git a/deps/npm/test/lib/update.js b/deps/npm/test/lib/update.js index 15195573f5..695218a7f6 100644 --- a/deps/npm/test/lib/update.js +++ b/deps/npm/test/lib/update.js @@ -1,16 +1,18 @@ const { resolve } = require('path') const t = require('tap') const requireInject = require('require-inject') +const mockNpm = require('../fixtures/mock-npm') +const config = { + depth: 0, + global: false, +} const noop = () => null -const npm = { +const npm = mockNpm({ globalDir: '', - flatOptions: { - depth: 0, - global: false, - }, + config, prefix: '', -} +}) const mocks = { npmlog: { warn () {} }, '@npmcli/arborist': class { @@ -22,7 +24,7 @@ const mocks = { t.afterEach(cb => { npm.prefix = '' - npm.flatOptions.global = false + config.global = false npm.globalDir = '' cb() }) @@ -99,7 +101,7 @@ t.test('update --depth=<number>', t => { t.plan(2) npm.prefix = '/project/a' - npm.flatOptions.depth = 1 + config.depth = 1 const Update = requireInject('../../lib/update.js', { ...mocks, @@ -131,7 +133,7 @@ t.test('update --global', t => { npm.prefix = '/project/a' npm.globalDir = resolve(process.cwd(), 'global/lib/node_modules') - npm.flatOptions.global = true + config.global = true class Arborist { constructor (args) { diff --git a/deps/npm/test/lib/utils/config.js b/deps/npm/test/lib/utils/config.js deleted file mode 100644 index 4d4b1a1d1a..0000000000 --- a/deps/npm/test/lib/utils/config.js +++ /dev/null @@ -1,143 +0,0 @@ -const t = require('tap') -const requireInject = require('require-inject') - -// have to fake the node version, or else it'll only pass on this one -Object.defineProperty(process, 'version', { - value: 'v14.8.0', -}) - -t.formatSnapshot = obj => { - if (typeof obj !== 'object' || !obj || !obj.types) - return obj - - return { - ...obj, - defaults: { - ...obj.defaults, - cache: '{CACHE DIR} ' + path.basename(obj.defaults.cache), - }, - types: formatTypes(obj.types), - } -} - -const path = require('path') -const url = require('url') -const semver = require('semver') - -const formatTypes = (types) => Object.entries(types).map(([key, value]) => { - return [key, formatTypeValue(value)] -}).reduce((set, [key, value]) => { - set[key] = value - return set -}, {}) - -const formatTypeValue = (value) => { - if (Array.isArray(value)) - return value.map(formatTypeValue) - else if (value === url) - return '{URL MODULE}' - else if (value === path) - return '{PATH MODULE}' - else if (value === semver) - return '{SEMVER MODULE}' - else if (typeof value === 'function') - return `{${value.name} TYPE}` - else - return value -} - -process.env.ComSpec = 'cmd.exe' -process.env.SHELL = '/usr/local/bin/bash' -process.env.LANG = 'UTF-8' -delete process.env.LC_ALL -delete process.env.LC_CTYPE -process.env.EDITOR = 'vim' -process.env.VISUAL = 'mate' - -const networkInterfacesThrow = () => { - throw new Error('no network interfaces for some reason') -} -const networkInterfaces = () => ({ - eth420: [{ address: '127.0.0.1' }], - eth69: [{ address: 'no place like home' }], -}) -const tmpdir = () => '/tmp' -const os = { networkInterfaces, tmpdir } -const pkg = { version: '7.0.0' } - -t.test('working network interfaces, not windows', t => { - const config = requireInject('../../../lib/utils/config.js', { - os, - '@npmcli/ci-detect': () => false, - '../../../lib/utils/is-windows.js': false, - '../../../package.json': pkg, - }) - t.matchSnapshot(config) - t.end() -}) - -t.test('no working network interfaces, on windows', t => { - const config = requireInject('../../../lib/utils/config.js', { - os: { tmpdir, networkInterfaces: networkInterfacesThrow }, - '@npmcli/ci-detect': () => false, - '../../../lib/utils/is-windows.js': true, - '../../../package.json': pkg, - }) - t.matchSnapshot(config) - t.end() -}) - -t.test('no comspec on windows', t => { - delete process.env.ComSpec - const config = requireInject('../../../lib/utils/config.js', { - os: { tmpdir, networkInterfaces: networkInterfacesThrow }, - '@npmcli/ci-detect': () => false, - '../../../lib/utils/is-windows.js': true, - }) - t.equal(config.defaults.shell, 'cmd') - t.end() -}) - -t.test('no shell on posix', t => { - delete process.env.SHELL - const config = requireInject('../../../lib/utils/config.js', { - os, - '@npmcli/ci-detect': () => false, - '../../../lib/utils/is-windows.js': false, - }) - t.equal(config.defaults.shell, 'sh') - t.end() -}) - -t.test('no EDITOR env, use VISUAL', t => { - delete process.env.EDITOR - const config = requireInject('../../../lib/utils/config.js', { - os, - '@npmcli/ci-detect': () => false, - '../../../lib/utils/is-windows.js': false, - }) - t.equal(config.defaults.editor, 'mate') - t.end() -}) - -t.test('no VISUAL, use system default, not windows', t => { - delete process.env.VISUAL - const config = requireInject('../../../lib/utils/config.js', { - os, - '@npmcli/ci-detect': () => false, - '../../../lib/utils/is-windows.js': false, - }) - t.equal(config.defaults.editor, 'vi') - t.end() -}) - -t.test('no VISUAL, use system default, not windows', t => { - delete process.env.VISUAL - const config = requireInject('../../../lib/utils/config.js', { - os, - '@npmcli/ci-detect': () => false, - '../../../lib/utils/is-windows.js': true, - }) - t.equal(config.defaults.editor, 'notepad.exe') - t.end() -}) diff --git a/deps/npm/test/lib/utils/config/definition.js b/deps/npm/test/lib/utils/config/definition.js new file mode 100644 index 0000000000..56e10da0cb --- /dev/null +++ b/deps/npm/test/lib/utils/config/definition.js @@ -0,0 +1,185 @@ +const t = require('tap') +const Definition = require('../../../../lib/utils/config/definition.js') +const { + typeDefs: { + semver: { type: semver }, + Umask: { type: Umask }, + url: { type: url }, + path: { type: path }, + }, +} = require('@npmcli/config') + +t.test('basic definition', async t => { + const def = new Definition('key', { + default: 'some default value', + type: [Number, String], + description: 'just a test thingie', + }) + t.same(def, { + constructor: Definition, + key: 'key', + default: 'some default value', + defaultDescription: '"some default value"', + type: [Number, String], + hint: '<key>', + usage: '--key <key>|--key <key>', + typeDescription: 'Number or String', + description: 'just a test thingie', + }) + t.matchSnapshot(def.describe(), 'human-readable description') + + const deprecated = new Definition('deprecated', { + deprecated: 'do not use this', + default: 1234, + description: ' it should not be used\n ever\n\n not even once.\n\n', + type: Number, + defaultDescription: 'A number bigger than 1', + typeDescription: 'An expression of a numeric quantity using numerals', + }) + t.matchSnapshot(deprecated.describe(), 'description of deprecated thing') + + const nullOrUmask = new Definition('key', { + default: null, + type: [null, Umask], + description: 'asdf', + }) + t.equal(nullOrUmask.typeDescription, 'null or Octal numeric string in range 0000..0777 (0..511)') + const nullDateOrBool = new Definition('key', { + default: 7, + type: [null, Date, Boolean], + description: 'asdf', + }) + t.equal(nullDateOrBool.typeDescription, 'null, Date, or Boolean') + const manyPaths = new Definition('key', { + default: ['asdf'], + type: [path, Array], + description: 'asdf', + }) + t.equal(manyPaths.typeDescription, 'Path (can be set multiple times)') + const pathOrUrl = new Definition('key', { + default: ['https://example.com'], + type: [path, url], + description: 'asdf', + }) + t.equal(pathOrUrl.typeDescription, 'Path or URL') + const multi12 = new Definition('key', { + default: [], + type: [1, 2, Array], + description: 'asdf', + }) + t.equal(multi12.typeDescription, '1 or 2 (can be set multiple times)') + const multi123 = new Definition('key', { + default: [], + type: [1, 2, 3, Array], + description: 'asdf', + }) + t.equal(multi123.typeDescription, '1, 2, or 3 (can be set multiple times)') + const multi123Semver = new Definition('key', { + default: [], + type: [1, 2, 3, Array, semver], + description: 'asdf', + }) + t.equal(multi123Semver.typeDescription, '1, 2, 3, or SemVer string (can be set multiple times)') + const hasUsage = new Definition('key', { + default: 'test default', + type: String, + description: 'test description', + usage: 'test usage', + }) + t.equal(hasUsage.usage, 'test usage') + const hasShort = new Definition('key', { + default: 'test default', + short: 't', + type: String, + description: 'test description', + }) + t.equal(hasShort.usage, '-t|--key <key>') + const hardCodedTypes = new Definition('key', { + default: 'test default', + type: ['string1', 'string2'], + description: 'test description', + }) + t.equal(hardCodedTypes.usage, '--key <string1|string2>') + const hardCodedOptionalTypes = new Definition('key', { + default: 'test default', + type: [null, 'string1', 'string2'], + description: 'test description', + }) + t.equal(hardCodedOptionalTypes.usage, '--key <string1|string2>') + const hasHint = new Definition('key', { + default: 'test default', + type: String, + description: 'test description', + hint: '<testparam>', + }) + t.equal(hasHint.usage, '--key <testparam>') +}) + +t.test('missing fields', async t => { + t.throws(() => new Definition('lacks-default', { + description: 'no default', + type: String, + }), { message: 'config lacks default: lacks-default' }) + t.throws(() => new Definition('lacks-type', { + description: 'no type', + default: 1234, + }), { message: 'config lacks type: lacks-type' }) + t.throws(() => new Definition(null, { + description: 'falsey key', + default: 1234, + type: Number, + }), { message: 'config lacks key: null' }) + t.throws(() => new Definition('extra-field', { + type: String, + default: 'extra', + extra: 'more than is wanted', + description: 'this is not ok', + }), { message: 'config defines unknown field extra: extra-field' }) +}) + +t.test('long description', async t => { + const { stdout: { columns } } = process + t.teardown(() => process.stdout.columns = columns) + + const long = new Definition('walden', { + description: ` + WHEN I WROTE the following pages, or rather the bulk of them, I lived + alone, in the woods, a mile from any neighbor, in a house which I had + built myself, on the shore of Walden Pond, in Concord, Massachusetts, and + earned my living by the labor of my hands only. I lived there two years + and two months. At present I am a sojourner in civilized life again. + + I should not obtrude my affairs so much on the notice of my readers if + very particular inquiries had not been made by my townsmen concerning my + mode of life, which some would call impertinent, though they do not + appear to me at all impertinent, but, considering the circumstances, very + natural and pertinent. + + \`\`\` + this.is('a', { + code: 'sample', + }) + + with (multiple) { + blocks() + } + \`\`\` + `, + default: true, + type: Boolean, + }) + process.stdout.columns = 40 + t.matchSnapshot(long.describe(), 'cols=40') + + process.stdout.columns = 9000 + t.matchSnapshot(long.describe(), 'cols=9000') + + process.stdout.columns = 0 + t.matchSnapshot(long.describe(), 'cols=0') + + process.stdout.columns = -1 + t.matchSnapshot(long.describe(), 'cols=-1') + + process.stdout.columns = NaN + t.matchSnapshot(long.describe(), 'cols=NaN') +}) diff --git a/deps/npm/test/lib/utils/config/definitions.js b/deps/npm/test/lib/utils/config/definitions.js new file mode 100644 index 0000000000..3169feefb8 --- /dev/null +++ b/deps/npm/test/lib/utils/config/definitions.js @@ -0,0 +1,697 @@ +const t = require('tap') + +const requireInject = require('require-inject') +const { resolve } = require('path') + +// have to fake the node version, or else it'll only pass on this one +Object.defineProperty(process, 'version', { + value: 'v14.8.0', +}) + +// also fake the npm version, so that it doesn't get reset every time +const pkg = require('../../../../package.json') + +// this is a pain to keep typing +const defpath = '../../../../lib/utils/config/definitions.js' + +// set this in the test when we need it +delete process.env.NODE_ENV +const definitions = require(defpath) + +const isWin = '../../../../lib/utils/is-windows.js' + +// snapshot these just so we note when they change +t.matchSnapshot(Object.keys(definitions), 'all config keys') +t.matchSnapshot(Object.keys(definitions).filter(d => d.flatten), + 'all config keys that are shared to flatOptions') + +t.equal(definitions['npm-version'].default, pkg.version, 'npm-version default') +t.equal(definitions['node-version'].default, process.version, 'node-version default') + +t.test('basic flattening function camelCases from css-case', t => { + const flat = {} + const obj = { 'always-auth': true } + definitions['always-auth'].flatten('always-auth', obj, flat) + t.strictSame(flat, { alwaysAuth: true }) + t.end() +}) + +t.test('editor', t => { + t.test('has EDITOR and VISUAL, use EDITOR', t => { + process.env.EDITOR = 'vim' + process.env.VISUAL = 'mate' + const defs = requireInject(defpath) + t.equal(defs.editor.default, 'vim') + t.end() + }) + t.test('has VISUAL but no EDITOR, use VISUAL', t => { + delete process.env.EDITOR + process.env.VISUAL = 'mate' + const defs = requireInject(defpath) + t.equal(defs.editor.default, 'mate') + t.end() + }) + t.test('has neither EDITOR nor VISUAL, system specific', t => { + delete process.env.EDITOR + delete process.env.VISUAL + const defsWin = requireInject(defpath, { + [isWin]: true, + }) + t.equal(defsWin.editor.default, 'notepad.exe') + const defsNix = requireInject(defpath, { + [isWin]: false, + }) + t.equal(defsNix.editor.default, 'vi') + t.end() + }) + t.end() +}) + +t.test('shell', t => { + t.test('windows, env.ComSpec then cmd.exe', t => { + process.env.ComSpec = 'command.com' + const defsComSpec = requireInject(defpath, { + [isWin]: true, + }) + t.equal(defsComSpec.shell.default, 'command.com') + delete process.env.ComSpec + const defsNoComSpec = requireInject(defpath, { + [isWin]: true, + }) + t.equal(defsNoComSpec.shell.default, 'cmd') + t.end() + }) + + t.test('nix, SHELL then sh', t => { + process.env.SHELL = '/usr/local/bin/bash' + const defsShell = requireInject(defpath, { + [isWin]: false, + }) + t.equal(defsShell.shell.default, '/usr/local/bin/bash') + delete process.env.SHELL + const defsNoShell = requireInject(defpath, { + [isWin]: false, + }) + t.equal(defsNoShell.shell.default, 'sh') + t.end() + }) + + t.end() +}) + +t.test('local-address allowed types', t => { + t.test('get list from os.networkInterfaces', t => { + const os = { + tmpdir: () => '/tmp', + networkInterfaces: () => ({ + eth420: [{ address: '127.0.0.1' }], + eth69: [{ address: 'no place like home' }], + }), + } + const defs = requireInject(defpath, { os }) + t.same(defs['local-address'].type, [ + null, + '127.0.0.1', + 'no place like home', + ]) + t.end() + }) + t.test('handle os.networkInterfaces throwing', t => { + const os = { + tmpdir: () => '/tmp', + networkInterfaces: () => { + throw new Error('no network interfaces for some reason') + }, + } + const defs = requireInject(defpath, { os }) + t.same(defs['local-address'].type, [null]) + t.end() + }) + t.end() +}) + +t.test('unicode allowed?', t => { + const { LC_ALL, LC_CTYPE, LANG } = process.env + t.teardown(() => Object.assign(process.env, { LC_ALL, LC_CTYPE, LANG })) + + process.env.LC_ALL = 'utf8' + process.env.LC_CTYPE = 'UTF-8' + process.env.LANG = 'Unicode utf-8' + + const lcAll = requireInject(defpath) + t.equal(lcAll.unicode.default, true) + process.env.LC_ALL = 'no unicode for youUUUU!' + const noLcAll = requireInject(defpath) + t.equal(noLcAll.unicode.default, false) + + delete process.env.LC_ALL + const lcCtype = requireInject(defpath) + t.equal(lcCtype.unicode.default, true) + process.env.LC_CTYPE = 'something other than unicode version 8' + const noLcCtype = requireInject(defpath) + t.equal(noLcCtype.unicode.default, false) + + delete process.env.LC_CTYPE + const lang = requireInject(defpath) + t.equal(lang.unicode.default, true) + process.env.LANG = 'ISO-8859-1' + const noLang = requireInject(defpath) + t.equal(noLang.unicode.default, false) + t.end() +}) + +t.test('cache', t => { + process.env.LOCALAPPDATA = 'app/data/local' + const defsWinLocalAppData = requireInject(defpath, { + [isWin]: true, + }) + t.equal(defsWinLocalAppData.cache.default, 'app/data/local/npm-cache') + + delete process.env.LOCALAPPDATA + const defsWinNoLocalAppData = requireInject(defpath, { + [isWin]: true, + }) + t.equal(defsWinNoLocalAppData.cache.default, '~/npm-cache') + + const defsNix = requireInject(defpath, { + [isWin]: false, + }) + t.equal(defsNix.cache.default, '~/.npm') + + const flat = {} + defsNix.cache.flatten('cache', { cache: '/some/cache/value' }, flat) + const {join} = require('path') + t.equal(flat.cache, join('/some/cache/value', '_cacache')) + + t.end() +}) + +t.test('flatteners that populate flat.omit array', t => { + t.test('also', t => { + const flat = {} + const obj = {} + + // ignored if setting is not dev or development + obj.also = 'ignored' + definitions.also.flatten('also', obj, flat) + t.strictSame(obj, {also: 'ignored'}, 'nothing done') + t.strictSame(flat, {}, 'nothing done') + + obj.also = 'development' + definitions.also.flatten('also', obj, flat) + t.strictSame(obj, { also: 'development', include: ['dev'] }, 'marked dev as included') + t.strictSame(flat, { omit: [] }, 'nothing omitted, so nothing changed') + + obj.omit = ['dev', 'optional'] + obj.include = [] + definitions.also.flatten('also', obj, flat) + t.strictSame(obj, { also: 'development', omit: ['dev', 'optional'], include: ['dev'] }, 'marked dev as included') + t.strictSame(flat, { omit: ['optional'] }, 'removed dev from omit') + t.end() + }) + + t.test('include', t => { + const flat = {} + const obj = { include: ['dev'] } + definitions.include.flatten('include', obj, flat) + t.strictSame(flat, {omit: []}, 'not omitting anything') + obj.omit = ['optional', 'dev'] + definitions.include.flatten('include', obj, flat) + t.strictSame(flat, {omit: ['optional']}, 'only omitting optional') + t.end() + }) + + t.test('omit', t => { + const flat = {} + const obj = { include: ['dev'], omit: ['dev', 'optional'] } + definitions.omit.flatten('omit', obj, flat) + t.strictSame(flat, { omit: ['optional'] }, 'do not omit what is included') + + process.env.NODE_ENV = 'production' + const defProdEnv = requireInject(defpath) + t.strictSame(defProdEnv.omit.default, ['dev'], 'omit dev in production') + t.end() + }) + + t.test('only', t => { + const flat = {} + const obj = { only: 'asdf' } + definitions.only.flatten('only', obj, flat) + t.strictSame(flat, {}, 'ignored if value is not production') + + obj.only = 'prod' + definitions.only.flatten('only', obj, flat) + t.strictSame(flat, {omit: ['dev']}, 'omit dev when --only=prod') + + obj.include = ['dev'] + flat.omit = [] + definitions.only.flatten('only', obj, flat) + t.strictSame(flat, {omit: []}, 'do not omit when included') + + t.end() + }) + + t.test('optional', t => { + const flat = {} + const obj = { optional: null } + + definitions.optional.flatten('optional', obj, flat) + t.strictSame(obj, { optional: null }, 'do nothing by default') + t.strictSame(flat, {}, 'do nothing by default') + + obj.optional = true + definitions.optional.flatten('optional', obj, flat) + t.strictSame(obj, {include: ['optional'], optional: true}, 'include optional when set') + t.strictSame(flat, {omit: []}, 'nothing to omit in flatOptions') + + delete obj.include + obj.optional = false + definitions.optional.flatten('optional', obj, flat) + t.strictSame(obj, {omit: ['optional'], optional: false}, 'omit optional when set false') + t.strictSame(flat, {omit: ['optional']}, 'omit optional when set false') + + t.end() + }) + + t.test('production', t => { + const flat = {} + const obj = {production: true} + definitions.production.flatten('production', obj, flat) + t.strictSame(obj, {production: true, omit: ['dev']}, '--production sets --omit=dev') + t.strictSame(flat, {omit: ['dev']}, '--production sets --omit=dev') + + delete obj.omit + obj.production = false + delete flat.omit + definitions.production.flatten('production', obj, flat) + t.strictSame(obj, {production: false}, '--no-production has no effect') + t.strictSame(flat, {}, '--no-production has no effect') + + obj.production = true + obj.include = ['dev'] + definitions.production.flatten('production', obj, flat) + t.strictSame(obj, {production: true, include: ['dev'], omit: ['dev']}, 'omit and include dev') + t.strictSame(flat, {omit: []}, 'do not omit dev when included') + + t.end() + }) + + t.end() +}) + +t.test('cache-max', t => { + const flat = {} + const obj = { 'cache-max': 10342 } + definitions['cache-max'].flatten('cache-max', obj, flat) + t.strictSame(flat, {}, 'no effect if not <= 0') + obj['cache-max'] = 0 + definitions['cache-max'].flatten('cache-max', obj, flat) + t.strictSame(flat, {preferOnline: true}, 'preferOnline if <= 0') + t.end() +}) + +t.test('cache-min', t => { + const flat = {} + const obj = { 'cache-min': 123 } + definitions['cache-min'].flatten('cache-min', obj, flat) + t.strictSame(flat, {}, 'no effect if not >= 9999') + obj['cache-min'] = 9999 + definitions['cache-min'].flatten('cache-min', obj, flat) + t.strictSame(flat, {preferOffline: true}, 'preferOffline if >=9999') + t.end() +}) + +t.test('color', t => { + const { isTTY } = process.stdout + t.teardown(() => process.stdout.isTTY = isTTY) + + const flat = {} + const obj = { color: 'always' } + + definitions.color.flatten('color', obj, flat) + t.strictSame(flat, {color: true}, 'true when --color=always') + + obj.color = false + definitions.color.flatten('color', obj, flat) + t.strictSame(flat, {color: false}, 'true when --no-color') + + process.stdout.isTTY = false + obj.color = true + definitions.color.flatten('color', obj, flat) + t.strictSame(flat, {color: false}, 'no color when stdout not tty') + process.stdout.isTTY = true + definitions.color.flatten('color', obj, flat) + t.strictSame(flat, {color: true}, '--color turns on color when stdout is tty') + + delete process.env.NO_COLOR + const defsAllowColor = requireInject(defpath) + t.equal(defsAllowColor.color.default, true, 'default true when no NO_COLOR env') + + process.env.NO_COLOR = '0' + const defsNoColor0 = requireInject(defpath) + t.equal(defsNoColor0.color.default, true, 'default true when no NO_COLOR=0') + + process.env.NO_COLOR = '1' + const defsNoColor1 = requireInject(defpath) + t.equal(defsNoColor1.color.default, false, 'default false when no NO_COLOR=1') + + t.end() +}) + +t.test('retry options', t => { + const obj = {} + // <config>: flat.retry[<option>] + const mapping = { + 'fetch-retries': 'retries', + 'fetch-retry-factor': 'factor', + 'fetch-retry-maxtimeout': 'maxTimeout', + 'fetch-retry-mintimeout': 'minTimeout', + } + for (const [config, option] of Object.entries(mapping)) { + const msg = `${config} -> retry.${option}` + const flat = {} + obj[config] = 99 + definitions[config].flatten(config, obj, flat) + t.strictSame(flat, {retry: {[option]: 99}}, msg) + delete obj[config] + } + t.end() +}) + +t.test('search options', t => { + const obj = {} + // <config>: flat.search[<option>] + const mapping = { + description: 'description', + searchexclude: 'exclude', + searchlimit: 'limit', + searchstaleness: 'staleness', + } + + for (const [config, option] of Object.entries(mapping)) { + const msg = `${config} -> search.${option}` + const flat = {} + obj[config] = 99 + definitions[config].flatten(config, obj, flat) + t.strictSame(flat, { search: { limit: 20, [option]: 99 }}, msg) + delete obj[config] + } + + const flat = {} + obj.searchopts = 'a=b&b=c' + definitions.searchopts.flatten('searchopts', obj, flat) + t.strictSame(flat, { + search: { + limit: 20, + opts: Object.assign(Object.create(null), { + a: 'b', + b: 'c', + }), + }, + }, 'searchopts -> querystring.parse() -> search.opts') + delete obj.searchopts + + t.end() +}) + +t.test('noProxy', t => { + const obj = { noproxy: ['1.2.3.4,2.3.4.5', '3.4.5.6'] } + const flat = {} + definitions.noproxy.flatten('noproxy', obj, flat) + t.strictSame(flat, { noProxy: '1.2.3.4,2.3.4.5,3.4.5.6' }) + t.end() +}) + +t.test('maxSockets', t => { + const obj = { maxsockets: 123 } + const flat = {} + definitions.maxsockets.flatten('maxsockets', obj, flat) + t.strictSame(flat, { maxSockets: 123 }) + t.end() +}) + +t.test('projectScope', t => { + const obj = { scope: 'asdf' } + const flat = {} + definitions.scope.flatten('scope', obj, flat) + t.strictSame(flat, { projectScope: '@asdf' }, 'prepend @ if needed') + + obj.scope = '@asdf' + definitions.scope.flatten('scope', obj, flat) + t.strictSame(flat, { projectScope: '@asdf' }, 'leave untouched if has @') + + t.end() +}) + +t.test('strictSSL', t => { + const obj = { 'strict-ssl': false } + const flat = {} + definitions['strict-ssl'].flatten('strict-ssl', obj, flat) + t.strictSame(flat, { strictSSL: false }) + obj['strict-ssl'] = true + definitions['strict-ssl'].flatten('strict-ssl', obj, flat) + t.strictSame(flat, { strictSSL: true }) + t.end() +}) + +t.test('shrinkwrap/package-lock', t => { + const obj = { shrinkwrap: false } + const flat = {} + definitions.shrinkwrap.flatten('shrinkwrap', obj, flat) + t.strictSame(flat, {packageLock: false}) + obj.shrinkwrap = true + definitions.shrinkwrap.flatten('shrinkwrap', obj, flat) + t.strictSame(flat, {packageLock: true}) + + delete obj.shrinkwrap + obj['package-lock'] = false + definitions['package-lock'].flatten('package-lock', obj, flat) + t.strictSame(flat, {packageLock: false}) + obj['package-lock'] = true + definitions['package-lock'].flatten('package-lock', obj, flat) + t.strictSame(flat, {packageLock: true}) + + t.end() +}) + +t.test('scriptShell', t => { + const obj = { 'script-shell': null } + const flat = {} + definitions['script-shell'].flatten('script-shell', obj, flat) + t.ok(Object.prototype.hasOwnProperty.call(flat, 'scriptShell'), + 'should set it to undefined explicitly') + t.strictSame(flat, { scriptShell: undefined }, 'no other fields') + + obj['script-shell'] = 'asdf' + definitions['script-shell'].flatten('script-shell', obj, flat) + t.strictSame(flat, { scriptShell: 'asdf' }, 'sets if not falsey') + + t.end() +}) + +t.test('defaultTag', t => { + const obj = { tag: 'next' } + const flat = {} + definitions.tag.flatten('tag', obj, flat) + t.strictSame(flat, {defaultTag: 'next'}) + t.end() +}) + +t.test('timeout', t => { + const obj = { 'fetch-timeout': 123 } + const flat = {} + definitions['fetch-timeout'].flatten('fetch-timeout', obj, flat) + t.strictSame(flat, {timeout: 123}) + t.end() +}) + +t.test('saveType', t => { + t.test('save-prod', t => { + const obj = { 'save-prod': false } + const flat = {} + definitions['save-prod'].flatten('save-prod', obj, flat) + t.strictSame(flat, {}, 'no effect if false and missing') + flat.saveType = 'prod' + definitions['save-prod'].flatten('save-prod', obj, flat) + t.strictSame(flat, {}, 'remove if false and set to prod') + flat.saveType = 'dev' + definitions['save-prod'].flatten('save-prod', obj, flat) + t.strictSame(flat, {saveType: 'dev'}, 'ignore if false and not already prod') + obj['save-prod'] = true + definitions['save-prod'].flatten('save-prod', obj, flat) + t.strictSame(flat, {saveType: 'prod'}, 'set to prod if true') + t.end() + }) + + t.test('save-dev', t => { + const obj = { 'save-dev': false } + const flat = {} + definitions['save-dev'].flatten('save-dev', obj, flat) + t.strictSame(flat, {}, 'no effect if false and missing') + flat.saveType = 'dev' + definitions['save-dev'].flatten('save-dev', obj, flat) + t.strictSame(flat, {}, 'remove if false and set to dev') + flat.saveType = 'prod' + obj['save-dev'] = false + definitions['save-dev'].flatten('save-dev', obj, flat) + t.strictSame(flat, {saveType: 'prod'}, 'ignore if false and not already dev') + obj['save-dev'] = true + definitions['save-dev'].flatten('save-dev', obj, flat) + t.strictSame(flat, {saveType: 'dev'}, 'set to dev if true') + t.end() + }) + + t.test('save-bundle', t => { + const obj = { 'save-bundle': true } + const flat = {} + definitions['save-bundle'].flatten('save-bundle', obj, flat) + t.strictSame(flat, {saveBundle: true}, 'set the saveBundle flag') + + obj['save-bundle'] = false + definitions['save-bundle'].flatten('save-bundle', obj, flat) + t.strictSame(flat, {saveBundle: false}, 'unset the saveBundle flag') + + obj['save-bundle'] = true + obj['save-peer'] = true + definitions['save-bundle'].flatten('save-bundle', obj, flat) + t.strictSame(flat, {saveBundle: false}, 'false if save-peer is set') + + t.end() + }) + + t.test('save-peer', t => { + const obj = { 'save-peer': false} + const flat = {} + definitions['save-peer'].flatten('save-peer', obj, flat) + t.strictSame(flat, {}, 'no effect if false and not yet set') + + obj['save-peer'] = true + definitions['save-peer'].flatten('save-peer', obj, flat) + t.strictSame(flat, {saveType: 'peer'}, 'set saveType to peer if unset') + + flat.saveType = 'optional' + definitions['save-peer'].flatten('save-peer', obj, flat) + t.strictSame(flat, {saveType: 'peerOptional'}, 'set to peerOptional if optional already') + + definitions['save-peer'].flatten('save-peer', obj, flat) + t.strictSame(flat, {saveType: 'peerOptional'}, 'no effect if already peerOptional') + + obj['save-peer'] = false + definitions['save-peer'].flatten('save-peer', obj, flat) + t.strictSame(flat, {saveType: 'optional'}, 'switch peerOptional to optional if false') + + obj['save-peer'] = false + flat.saveType = 'peer' + definitions['save-peer'].flatten('save-peer', obj, flat) + t.strictSame(flat, {}, 'remove saveType if peer and setting false') + + t.end() + }) + + t.test('save-optional', t => { + const obj = { 'save-optional': false} + const flat = {} + definitions['save-optional'].flatten('save-optional', obj, flat) + t.strictSame(flat, {}, 'no effect if false and not yet set') + + obj['save-optional'] = true + definitions['save-optional'].flatten('save-optional', obj, flat) + t.strictSame(flat, {saveType: 'optional'}, 'set saveType to optional if unset') + + flat.saveType = 'peer' + definitions['save-optional'].flatten('save-optional', obj, flat) + t.strictSame(flat, {saveType: 'peerOptional'}, 'set to peerOptional if peer already') + + definitions['save-optional'].flatten('save-optional', obj, flat) + t.strictSame(flat, {saveType: 'peerOptional'}, 'no effect if already peerOptional') + + obj['save-optional'] = false + definitions['save-optional'].flatten('save-optional', obj, flat) + t.strictSame(flat, {saveType: 'peer'}, 'switch peerOptional to peer if false') + + flat.saveType = 'optional' + definitions['save-optional'].flatten('save-optional', obj, flat) + t.strictSame(flat, {}, 'remove saveType if optional and setting false') + + t.end() + }) + + t.end() +}) + +t.test('cafile -> flat.ca', t => { + const path = t.testdir({ + cafile: ` +-----BEGIN CERTIFICATE----- +XXXX +XXXX +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +YYYY\r +YYYY\r +-----END CERTIFICATE----- +`, + }) + const cafile = resolve(path, 'cafile') + + const obj = {} + const flat = {} + definitions.cafile.flatten('cafile', obj, flat) + t.strictSame(flat, {}, 'no effect if no cafile set') + obj.cafile = resolve(path, 'no/cafile/here') + definitions.cafile.flatten('cafile', obj, flat) + t.strictSame(flat, {}, 'no effect if cafile not found') + obj.cafile = cafile + definitions.cafile.flatten('cafile', obj, flat) + t.strictSame(flat, { + ca: [ + '-----BEGIN CERTIFICATE-----\nXXXX\nXXXX\n-----END CERTIFICATE-----', + '-----BEGIN CERTIFICATE-----\nYYYY\nYYYY\n-----END CERTIFICATE-----', + ], + }) + t.test('error other than ENOENT gets thrown', t => { + const poo = new Error('poo') + const defnReadFileThrows = requireInject(defpath, { + fs: { + ...require('fs'), + readFileSync: () => { + throw poo + }, + }, + }) + t.throws(() => defnReadFileThrows.cafile.flatten('cafile', obj, {}), poo) + t.end() + }) + + t.end() +}) + +t.test('detect CI', t => { + const defnNoCI = requireInject(defpath, { + '@npmcli/ci-detect': () => false, + }) + const defnCIFoo = requireInject(defpath, { + '@npmcli/ci-detect': () => 'foo', + }) + t.equal(defnNoCI['ci-name'].default, null, 'null when not in CI') + t.equal(defnCIFoo['ci-name'].default, 'foo', 'name of CI when in CI') + t.end() +}) + +t.test('user-agent', t => { + const obj = { + 'user-agent': definitions['user-agent'].default, + 'npm-version': '1.2.3', + 'node-version': '9.8.7', + } + const flat = {} + const expectNoCI = `npm/1.2.3 node/9.8.7 ` + + `${process.platform} ${process.arch}` + definitions['user-agent'].flatten('user-agent', obj, flat) + t.equal(flat.userAgent, expectNoCI) + obj['ci-name'] = 'foo' + const expectCI = `${expectNoCI} ci/foo` + definitions['user-agent'].flatten('user-agent', obj, flat) + t.equal(flat.userAgent, expectCI) + t.end() +}) diff --git a/deps/npm/test/lib/utils/config/describe-all.js b/deps/npm/test/lib/utils/config/describe-all.js new file mode 100644 index 0000000000..814d92ac95 --- /dev/null +++ b/deps/npm/test/lib/utils/config/describe-all.js @@ -0,0 +1,6 @@ +const t = require('tap') +const describeAll = require('../../../../lib/utils/config/describe-all.js') +// this basically ends up being a duplicate of the helpdoc dumped into +// a snapshot, but it verifies that we get the same help output on every +// platform where we run CI. +t.matchSnapshot(describeAll()) diff --git a/deps/npm/test/lib/utils/config/flatten.js b/deps/npm/test/lib/utils/config/flatten.js new file mode 100644 index 0000000000..9fac0820cb --- /dev/null +++ b/deps/npm/test/lib/utils/config/flatten.js @@ -0,0 +1,34 @@ +const t = require('tap') +const flatten = require('../../../../lib/utils/config/flatten.js') + +require.main.filename = '/path/to/npm' +delete process.env.NODE +process.execPath = '/path/to/node' + +const obj = { + 'save-dev': true, + '@foobar:registry': 'https://foo.bar.com/', + '//foo.bar.com:_authToken': 'foobarbazquuxasdf', + userconfig: '/path/to/.npmrc', +} + +const flat = flatten(obj) +t.strictSame(flat, { + saveType: 'dev', + '@foobar:registry': 'https://foo.bar.com/', + '//foo.bar.com:_authToken': 'foobarbazquuxasdf', + npmBin: '/path/to/npm', + nodeBin: '/path/to/node', + hashAlgorithm: 'sha1', +}) + +// now flatten something else on top of it. +process.env.NODE = '/usr/local/bin/node.exe' +flatten({ 'save-dev': false }, flat) +t.strictSame(flat, { + '@foobar:registry': 'https://foo.bar.com/', + '//foo.bar.com:_authToken': 'foobarbazquuxasdf', + npmBin: '/path/to/npm', + nodeBin: '/usr/local/bin/node.exe', + hashAlgorithm: 'sha1', +}) diff --git a/deps/npm/test/lib/utils/config/index.js b/deps/npm/test/lib/utils/config/index.js new file mode 100644 index 0000000000..75d72e784f --- /dev/null +++ b/deps/npm/test/lib/utils/config/index.js @@ -0,0 +1,24 @@ +const t = require('tap') +const config = require('../../../../lib/utils/config/index.js') +const flatten = require('../../../../lib/utils/config/flatten.js') +const definitions = require('../../../../lib/utils/config/definitions.js') +const describeAll = require('../../../../lib/utils/config/describe-all.js') +t.matchSnapshot(config.shorthands, 'shorthands') + +// just spot check a few of these to show that we got defaults assembled +t.match(config.defaults, { + registry: definitions.registry.default, + 'init-module': definitions['init-module'].default, +}) + +// is a getter, so changes are reflected +definitions.registry.default = 'https://example.com' +t.strictSame(config.defaults.registry, 'https://example.com') + +t.strictSame(config, { + defaults: config.defaults, + shorthands: config.shorthands, + flatten, + definitions, + describeAll, +}) diff --git a/deps/npm/test/lib/utils/did-you-mean.js b/deps/npm/test/lib/utils/did-you-mean.js index 0c9c95c7f9..68893a800f 100644 --- a/deps/npm/test/lib/utils/did-you-mean.js +++ b/deps/npm/test/lib/utils/did-you-mean.js @@ -1,7 +1,39 @@ const t = require('tap') +const requireInject = require('require-inject') +const npm = requireInject('../../../lib/npm.js') + const dym = require('../../../lib/utils/did-you-mean.js') -t.equal(dym('asdfa', ['asdf', 'asfd', 'adfs', 'safd', 'foobarbaz', 'foobar']), - '\nDid you mean this?\n asdf') -t.equal(dym('asdfa', ['asdf', 'sdfa', 'foo', 'bar', 'fdsa']), - '\nDid you mean one of these?\n asdf\n sdfa') -t.equal(dym('asdfa', ['install', 'list', 'test']), '') +t.test('did-you-mean', t => { + npm.load(err => { + t.notOk(err) + t.test('nistall', async t => { + const result = await dym(npm, npm.localPrefix, 'nistall') + t.match(result, 'npm install') + }) + t.test('sttest', async t => { + const result = await dym(npm, npm.localPrefix, 'sttest') + t.match(result, 'npm test') + t.match(result, 'npm run posttest') + }) + t.test('npz', async t => { + const result = await dym(npm, npm.localPrefix, 'npxx') + t.match(result, 'npm exec npx') + }) + t.test('qwuijbo', async t => { + const result = await dym(npm, npm.localPrefix, 'qwuijbo') + t.match(result, '') + }) + t.end() + }) +}) + +t.test('missing bin and script properties', async t => { + const path = t.testdir({ + 'package.json': JSON.stringify({ + name: 'missing-bin', + }), + }) + + const result = await dym(npm, path, 'nistall') + t.match(result, 'npm install') +}) diff --git a/deps/npm/test/lib/utils/flat-options.js b/deps/npm/test/lib/utils/flat-options.js deleted file mode 100644 index 6f580fabc4..0000000000 --- a/deps/npm/test/lib/utils/flat-options.js +++ /dev/null @@ -1,359 +0,0 @@ -const t = require('tap') - -process.env.NODE = '/path/to/some/node' -process.env.NODE_ENV = 'development' - -const logs = [] -const log = require('npmlog') -log.warn = (...args) => logs.push(['warn', ...args]) -log.verbose = (...args) => logs.push(['verbose', ...args]) - -class Mocknpm { - constructor (opts = {}) { - this.modes = { - exec: 0o777, - file: 0o666, - umask: 0o22, - } - this.color = true - this.projectScope = '@npmcli' - this.tmp = '/tmp' - this.command = null - this.globalPrefix = '/usr/local' - this.localPrefix = '/path/to/npm/cli' - this.prefix = this.localPrefix - this.version = '7.6.5' - this.config = new MockConfig(opts) - this.flatOptions = null - } -} - -class MockConfig { - constructor (opts = {}) { - this.list = [{ - cache: 'cache', - 'node-version': '1.2.3', - global: 'global', - registry: 'registry', - access: 'access', - 'always-auth': 'always-auth', - audit: 'audit', - 'audit-level': 'audit-level', - 'auth-type': 'auth-type', - before: 'before', - browser: 'browser', - ca: 'ca', - cafile: 'cafile', - call: 'call', - cert: 'cert', - key: 'key', - 'cache-lock-retries': 'cache-lock-retries', - 'cache-lock-stale': 'cache-lock-stale', - 'cache-lock-wait': 'cache-lock-wait', - cidr: 'cidr', - 'read-only': 'read-only', - preid: 'preid', - 'tag-version-prefix': 'tag-version-prefix', - 'allow-same-version': 'allow-same-version', - message: 'message', - 'commit-hooks': 'commit-hooks', - 'git-tag-version': 'git-tag-version', - 'sign-git-commit': 'sign-git-commit', - 'sign-git-tag': 'sign-git-tag', - depth: 'depth', - description: 'description', - searchexclude: 'searchexclude', - searchlimit: 'searchlimit', - searchopts: 'from=1', - searchstaleness: 'searchstaleness', - 'dry-run': 'dry-run', - 'engine-strict': 'engine-strict', - 'fetch-retries': 'fetch-retries', - 'fetch-retry-factor': 'fetch-retry-factor', - 'fetch-retry-mintimeout': 'fetch-retry-mintimeout', - 'fetch-retry-maxtimeout': 'fetch-retry-maxtimeout', - 'fetch-timeout': 'fetch-timeout', - force: 'force', - 'format-package-lock': 'format-package-lock', - fund: 'fund', - git: 'git', - viewer: 'viewer', - editor: 'editor', - 'bin-links': 'bin-links', - 'rebuild-bundle': 'rebuild-bundle', - package: 'package', - 'package-lock': 'package-lock', - 'package-lock-only': 'package-lock-only', - 'global-style': 'global-style', - 'legacy-bundling': 'legacy-bundling', - 'script-shell': 'script-shell', - omit: [], - include: [], - save: 'save', - 'save-bundle': 'save-bundle', - 'save-dev': 'save-dev', - 'save-optional': 'save-optional', - 'save-peer': 'save-peer', - 'save-prod': 'save-prod', - 'save-exact': 'save-exact', - 'save-prefix': 'save-prefix', - otp: 'otp', - offline: 'offline', - 'prefer-online': 'prefer-online', - 'prefer-offline': 'prefer-offline', - 'cache-max': 'cache-max', - 'cache-min': 'cache-min', - 'strict-ssl': 'strict-ssl', - scope: '', - tag: 'tag', - 'user-agent': 'user-agent', - '@scope:registry': '@scope:registry', - '//nerf.dart:_authToken': '//nerf.dart:_authToken', - proxy: 'proxy', - noproxy: 'noproxy', - ...opts, - }] - } - - get (key) { - return this.list[0][key] - } - - set (key, val) { - this.list[0][key] = val - } -} - -const flatOptions = require('../../../lib/utils/flat-options.js') -t.match(logs, [[ - 'verbose', - 'npm-session', - /^[0-9a-f]{16}$/, -]], 'logged npm session verbosely') -logs.length = 0 - -t.test('basic', t => { - const npm = new Mocknpm() - const generatedFlat = flatOptions(npm) - const clean = { - ...generatedFlat, - npmBin: '/path/to/npm/bin.js', - log: {}, - npmSession: '12345', - cache: generatedFlat.cache.replace(/\\/g, '/'), - } - t.matchSnapshot(clean, 'flat options') - t.equal(generatedFlat.npmCommand, null, 'command not set yet') - npm.command = 'view' - t.equal(generatedFlat.npmCommand, 'view', 'command updated via getter') - t.equal(generatedFlat.npmBin, require.main.filename) - // test the object is frozen - generatedFlat.newField = 'asdf' - t.equal(generatedFlat.newField, undefined, 'object is frozen') - const preExistingOpts = { flat: 'options' } - npm.flatOptions = preExistingOpts - t.equal(flatOptions(npm), preExistingOpts, 'use pre-existing npm.flatOptions') - t.end() -}) - -t.test('get preferOffline from cache-min', t => { - const npm = new Mocknpm({ - 'cache-min': 9999999, - 'prefer-offline': undefined, - }) - const opts = flatOptions(npm) - t.equal(opts.preferOffline, true, 'got preferOffline from cache min') - logs.length = 0 - t.equal(opts.cacheMin, undefined, 'opts.cacheMin is not set') - t.match(logs, []) - logs.length = 0 - t.end() -}) - -t.test('get preferOnline from cache-max', t => { - const npm = new Mocknpm({ - 'cache-max': -1, - 'prefer-online': undefined, - }) - const opts = flatOptions(npm) - t.equal(opts.preferOnline, true, 'got preferOnline from cache min') - logs.length = 0 - t.equal(opts.cacheMax, undefined, 'opts.cacheMax is not set') - t.match(logs, []) - logs.length = 0 - t.end() -}) - -t.test('tag emits warning', t => { - const npm = new Mocknpm({ tag: 'foobar' }) - t.equal(flatOptions(npm).tag, 'foobar', 'tag is foobar') - t.match(logs, []) - logs.length = 0 - t.end() -}) - -t.test('omit/include options', t => { - t.test('omit explicitly', t => { - const { NODE_ENV } = process.env - const npm = new Mocknpm({ - omit: ['dev', 'optional', 'peer'], - }) - t.strictSame(flatOptions(npm).omit, ['dev', 'optional', 'peer']) - t.equal(process.env.NODE_ENV, 'production') - process.env.NODE_ENV = NODE_ENV - t.end() - }) - - t.test('omit and include some', t => { - const { NODE_ENV } = process.env - const npm = new Mocknpm({ - omit: ['dev', 'optional', 'peer'], - include: ['peer'], - }) - t.strictSame(flatOptions(npm).omit, ['dev', 'optional']) - t.equal(process.env.NODE_ENV, 'production') - process.env.NODE_ENV = NODE_ENV - t.end() - }) - - t.test('dev flag', t => { - const { NODE_ENV } = process.env - const npm = new Mocknpm({ - omit: ['dev', 'optional', 'peer'], - include: [], - dev: true, - }) - t.strictSame(flatOptions(npm).omit, ['optional', 'peer']) - t.equal(process.env.NODE_ENV, NODE_ENV) - process.env.NODE_ENV = NODE_ENV - t.end() - }) - - t.test('production flag', t => { - const { NODE_ENV } = process.env - const npm = new Mocknpm({ - omit: [], - include: [], - production: true, - }) - t.strictSame(flatOptions(npm).omit, ['dev']) - t.equal(process.env.NODE_ENV, 'production') - process.env.NODE_ENV = NODE_ENV - t.end() - }) - - t.test('only', t => { - const { NODE_ENV } = process.env - const cases = ['prod', 'production'] - t.plan(cases.length) - cases.forEach(c => t.test(c, t => { - const npm = new Mocknpm({ - omit: [], - include: [], - only: c, - }) - t.strictSame(flatOptions(npm).omit, ['dev']) - t.equal(process.env.NODE_ENV, 'production') - process.env.NODE_ENV = NODE_ENV - t.end() - })) - }) - - t.test('also dev', t => { - const { NODE_ENV } = process.env - const npm = new Mocknpm({ - omit: ['dev', 'optional', 'peer'], - also: 'dev', - }) - t.strictSame(flatOptions(npm).omit, ['optional', 'peer']) - t.equal(process.env.NODE_ENV, NODE_ENV) - process.env.NODE_ENV = NODE_ENV - t.end() - }) - - t.test('no-optional', t => { - const { NODE_ENV } = process.env - const npm = new Mocknpm({ - optional: false, - omit: null, - include: null, - }) - t.strictSame(flatOptions(npm).omit, ['optional']) - t.equal(process.env.NODE_ENV, NODE_ENV) - process.env.NODE_ENV = NODE_ENV - t.end() - }) - - t.end() -}) - -t.test('get the node without the environ', t => { - delete process.env.NODE - t.equal(flatOptions(new Mocknpm()).nodeBin, process.execPath) - t.end() -}) - -t.test('various default values and falsey fallbacks', t => { - const npm = new Mocknpm({ - 'script-shell': false, - registry: 'http://example.com', - searchlimit: 0, - 'save-exact': false, - 'save-prefix': '>=', - }) - const opts = flatOptions(npm) - t.equal(opts.scriptShell, undefined, 'scriptShell is undefined if falsey') - t.equal(opts.search.limit, 20, 'searchLimit defaults to 20') - t.equal(opts.savePrefix, '>=', 'save-prefix respected if no save-exact') - t.equal(opts.scope, '', 'scope defaults to empty string') - logs.length = 0 - 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, - 'save-peer': false, - 'save-dev': false, - 'save-prod': false, - } - const cases = [ - ['peerOptional', { - 'save-optional': true, - 'save-peer': true, - }], - ['optional', { - 'save-optional': true, - }], - ['dev', { - 'save-dev': true, - }], - ['peer', { - 'save-peer': true, - }], - ['prod', { - 'save-prod': true, - }], - [null, {}], - ] - for (const [expect, options] of cases) { - const opts = flatOptions(new Mocknpm({ - ...base, - ...options, - })) - t.equal(opts.saveType, expect, JSON.stringify(options)) - } - t.end() -}) diff --git a/deps/npm/test/lib/utils/lifecycle-cmd.js b/deps/npm/test/lib/utils/lifecycle-cmd.js index 3e3a7da434..862c87a8e0 100644 --- a/deps/npm/test/lib/utils/lifecycle-cmd.js +++ b/deps/npm/test/lib/utils/lifecycle-cmd.js @@ -10,6 +10,7 @@ const npm = { }, } t.test('create a lifecycle command', t => { + t.plan(5) class TestStage extends LifecycleCmd { static get name () { return 'test-stage' @@ -20,6 +21,9 @@ t.test('create a lifecycle command', t => { cmd.exec(['some', 'args'], (er, result) => { t.same(runArgs, ['test-stage', 'some', 'args']) t.strictSame(result, 'called npm.commands.run') - t.end() + }) + cmd.execWorkspaces(['some', 'args'], [], (er, result) => { + t.same(runArgs, ['test-stage', 'some', 'args']) + t.strictSame(result, 'called npm.commands.run') }) }) diff --git a/deps/npm/test/lib/utils/npm-usage.js b/deps/npm/test/lib/utils/npm-usage.js index fbc453811e..ebf637ae1c 100644 --- a/deps/npm/test/lib/utils/npm-usage.js +++ b/deps/npm/test/lib/utils/npm-usage.js @@ -1,12 +1,5 @@ const t = require('tap') - -const OUTPUT = [] -const output = (...msg) => OUTPUT.push(msg) -const requireInject = require('require-inject') -const usage = require('../../../lib/utils/npm-usage.js') - -const npm = requireInject('../../../lib/npm.js') -npm.output = output +const npm = require('../../../lib/npm.js') t.test('usage', t => { t.afterEach((cb) => { @@ -29,61 +22,19 @@ t.test('usage', t => { npm.config.set('userconfig', '/some/config/file/.npmrc') t.test('basic usage', t => { - usage(npm) - t.equal(OUTPUT.length, 1) - t.equal(OUTPUT[0].length, 1) - t.matchSnapshot(OUTPUT[0][0]) - OUTPUT.length = 0 + t.matchSnapshot(npm.usage) t.end() }) t.test('with browser', t => { npm.config.set('viewer', 'browser') - usage(npm) - t.equal(OUTPUT.length, 1) - t.equal(OUTPUT[0].length, 1) - t.matchSnapshot(OUTPUT[0][0]) - OUTPUT.length = 0 - npm.config.set('viewer', null) + t.matchSnapshot(npm.usage) t.end() }) t.test('with long', t => { npm.config.set('long', true) - usage(npm) - t.equal(OUTPUT.length, 1) - t.equal(OUTPUT[0].length, 1) - t.matchSnapshot(OUTPUT[0][0]) - OUTPUT.length = 0 - npm.config.set('long', false) - t.end() - }) - - t.test('did you mean?', t => { - npm.argv.push('unistnall') - usage(npm) - t.equal(OUTPUT.length, 2) - t.equal(OUTPUT[0].length, 1) - t.equal(OUTPUT[1].length, 1) - t.matchSnapshot(OUTPUT[0][0]) - t.matchSnapshot(OUTPUT[1][0]) - OUTPUT.length = 0 - npm.argv.length = 0 - t.end() - }) - - t.test('did you mean?', t => { - npm.argv.push('unistnall') - const { exitCode } = process - t.teardown(() => { - if (t.passing()) - process.exitCode = exitCode - }) - // make sure it fails when invalid - usage(npm, false) - t.equal(process.exitCode, 1) - OUTPUT.length = 0 - npm.argv.length = 0 + t.matchSnapshot(npm.usage) t.end() }) @@ -106,11 +57,7 @@ t.test('usage', t => { configurable: true, writable: true, }) - usage(npm) - t.equal(OUTPUT.length, 1) - t.equal(OUTPUT[0].length, 1) - t.matchSnapshot(OUTPUT[0][0]) - OUTPUT.length = 0 + t.matchSnapshot(npm.usage) t.end() }) } diff --git a/deps/npm/test/lib/utils/read-local-package.js b/deps/npm/test/lib/utils/read-local-package.js index 9ae21f7d62..4b693afb48 100644 --- a/deps/npm/test/lib/utils/read-local-package.js +++ b/deps/npm/test/lib/utils/read-local-package.js @@ -1,22 +1,17 @@ const requireInject = require('require-inject') const { test } = require('tap') +const mockNpm = require('../../fixtures/mock-npm') -let prefix -const _flatOptions = { +const config = { json: false, global: false, - get prefix () { - return prefix - }, } +const npm = mockNpm({ config }) const readLocalPackageName = requireInject('../../../lib/utils/read-local-package.js') -const npm = { - flatOptions: _flatOptions, -} test('read local package.json', async (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: 'my-local-package', version: '1.0.0', @@ -31,7 +26,7 @@ test('read local package.json', async (t) => { }) test('read local scoped-package.json', async (t) => { - prefix = t.testdir({ + npm.prefix = t.testdir({ 'package.json': JSON.stringify({ name: '@my-scope/my-local-package', version: '1.0.0', @@ -46,13 +41,13 @@ test('read local scoped-package.json', async (t) => { }) test('read using --global', async (t) => { - prefix = t.testdir({}) - _flatOptions.global = true + npm.prefix = t.testdir({}) + config.global = true const packageName = await readLocalPackageName(npm) t.equal( packageName, undefined, 'should not retrieve a package name' ) - _flatOptions.global = false + config.global = false }) diff --git a/deps/npm/test/lib/utils/tar.js b/deps/npm/test/lib/utils/tar.js index b780a73e5e..d9b8c5584a 100644 --- a/deps/npm/test/lib/utils/tar.js +++ b/deps/npm/test/lib/utils/tar.js @@ -101,9 +101,9 @@ test('should getContents of a tarball', async (t) => { id: 'my-cool-pkg@1.0.0', name: 'my-cool-pkg', version: '1.0.0', - size: 149, + size: 146, unpackedSize: 49, - shasum: 'c0bfd67a5142104e429afda09119eedd6a30d2fc', + shasum: 'b8379c5e69693cdda73aec3d81dae1d11c1e75bd', integrity: ssri.parse(integrity.sha512[0]), filename: 'my-cool-pkg-1.0.0.tgz', files: [{ path: 'package.json', size: 49, mode: 420 }], diff --git a/deps/npm/test/lib/version.js b/deps/npm/test/lib/version.js index a8fcd831fb..35d3d92cd2 100644 --- a/deps/npm/test/lib/version.js +++ b/deps/npm/test/lib/version.js @@ -1,21 +1,23 @@ const t = require('tap') const requireInject = require('require-inject') +const mockNpm = require('../fixtures/mock-npm') let result = [] const noop = () => null -const npm = { - flatOptions: { - tagVersionPrefix: 'v', - json: false, - }, +const config = { + 'tag-version-prefix': 'v', + json: false, +} +const npm = mockNpm({ + config, prefix: '', version: '1.0.0', output: (...msg) => { for (const m of msg) result.push(m) }, -} +}) const mocks = { libnpmversion: noop, } @@ -25,7 +27,7 @@ const version = new Version(npm) const _processVersions = process.versions t.afterEach(cb => { - npm.flatOptions.json = false + config.json = false npm.prefix = '' process.versions = _processVersions result = [] @@ -116,7 +118,7 @@ t.test('failure reading package.json', t => { t.test('--json option', t => { const prefix = t.testdir({}) - npm.flatOptions.json = true + config.json = true npm.prefix = prefix Object.defineProperty(process, 'versions', { value: {} }) @@ -140,8 +142,6 @@ t.test('with one arg', t => { t.deepEqual( opts, { - tagVersionPrefix: 'v', - json: false, path: '', }, 'should forward expected options' diff --git a/deps/npm/test/lib/view.js b/deps/npm/test/lib/view.js index 1363a5b9f9..d136a1f418 100644 --- a/deps/npm/test/lib/view.js +++ b/deps/npm/test/lib/view.js @@ -1,5 +1,6 @@ const t = require('tap') const requireInject = require('require-inject') +const mockNpm = require('../fixtures/mock-npm') let logs const cleanLogs = (done) => { @@ -243,34 +244,33 @@ t.test('should log package info', t => { packument, }, }) - const view = new View({ - flatOptions: { - global: false, - }, + const npm = mockNpm({ + config: { global: false }, }) + const view = new View(npm) const ViewJson = requireInject('../../lib/view.js', { pacote: { packument, }, }) - const viewJson = new ViewJson({ - flatOptions: { - json: true, - }, + const jsonNpm = mockNpm({ + config: { json: true }, }) + const viewJson = new ViewJson(jsonNpm) const ViewUnicode = requireInject('../../lib/view.js', { pacote: { packument, }, }) - const viewUnicode = new ViewUnicode({ - flatOptions: { + const unicodeNpm = mockNpm({ + config: { global: false, unicode: true, }, }) + const viewUnicode = new ViewUnicode(unicodeNpm) t.test('package with license, bugs, repository and other fields', t => { view.exec(['green@1.0.0'], () => { @@ -351,13 +351,14 @@ t.test('should log info of package in current working dir', t => { packument, }, }) - const view = new View({ + const npm = mockNpm({ prefix: testDir, - flatOptions: { - defaultTag: '1.0.0', + config: { + tag: '1.0.0', global: false, }, }) + const view = new View(npm) t.test('specific version', t => { view.exec(['.@1.0.0'], () => { @@ -382,23 +383,24 @@ t.test('should log info by field name', t => { packument, }, }) - const viewJson = new ViewJson({ - flatOptions: { + const jsonNpm = mockNpm({ + config: { json: true, global: false, }, }) + const viewJson = new ViewJson(jsonNpm) + const View = requireInject('../../lib/view.js', { pacote: { packument, }, }) - const view = new View({ - flatOptions: { - global: false, - }, + const npm = mockNpm({ + config: { global: false }, }) + const view = new View(npm) t.test('readme', t => { view.exec(['yellow@1.0.0', 'readme'], () => { @@ -468,11 +470,10 @@ t.test('should log info by field name', t => { t.test('throw error if global mode', (t) => { const View = requireInject('../../lib/view.js') - const view = new View({ - flatOptions: { - global: true, - }, + const npm = mockNpm({ + config: { global: true }, }) + const view = new View(npm) view.exec([], (err) => { t.equals(err.message, 'Cannot use view command in global mode.') t.end() @@ -483,12 +484,11 @@ t.test('throw ENOENT error if package.json misisng', (t) => { const testDir = t.testdir({}) const View = requireInject('../../lib/view.js') - const view = new View({ + const npm = mockNpm({ prefix: testDir, - flatOptions: { - global: false, - }, + config: { global: false }, }) + const view = new View(npm) view.exec([], (err) => { t.match(err, { code: 'ENOENT' }) t.end() @@ -501,12 +501,11 @@ t.test('throw EJSONPARSE error if package.json not json', (t) => { }) const View = requireInject('../../lib/view.js') - const view = new View({ + const npm = mockNpm({ prefix: testDir, - flatOptions: { - global: false, - }, + config: { global: false }, }) + const view = new View(npm) view.exec([], (err) => { t.match(err, { code: 'EJSONPARSE' }) t.end() @@ -519,12 +518,11 @@ t.test('throw error if package.json has no name', (t) => { }) const View = requireInject('../../lib/view.js') - const view = new View({ + const npm = mockNpm({ prefix: testDir, - flatOptions: { - global: false, - }, + config: { global: false }, }) + const view = new View(npm) view.exec([], (err) => { t.equals(err.message, 'Invalid package.json, no "name" field') t.end() @@ -537,12 +535,13 @@ t.test('throws when unpublished', (t) => { packument, }, }) - const view = new View({ - flatOptions: { - defaultTag: '1.0.1', + const npm = mockNpm({ + config: { + tag: '1.0.1', global: false, }, }) + const view = new View(npm) view.exec(['red'], (err) => { t.equals(err.code, 'E404') t.end() @@ -555,12 +554,13 @@ t.test('completion', async t => { packument, }, }) - const view = new View({ - flatOptions: { - defaultTag: '1.0.1', + const npm = mockNpm({ + config: { + tag: '1.0.1', global: false, }, }) + const view = new View(npm) const res = await view.completion({ conf: { argv: { remain: ['npm', 'view', 'green@1.0.0'] } }, }) @@ -570,11 +570,13 @@ t.test('completion', async t => { t.test('no registry completion', async t => { const View = requireInject('../../lib/view.js') - const view = new View({ - flatOptions: { - defaultTag: '1.0.1', + const npm = mockNpm({ + config: { + tag: '1.0.1', + global: false, }, }) + const view = new View(npm) const res = await view.completion({conf: { argv: { remain: ['npm', 'view'] } } }) t.notOk(res, 'there is no package completion') t.end() diff --git a/deps/npm/test/lib/whoami.js b/deps/npm/test/lib/whoami.js index 1a1ecd2574..b242ea8941 100644 --- a/deps/npm/test/lib/whoami.js +++ b/deps/npm/test/lib/whoami.js @@ -1,18 +1,21 @@ const { test } = require('tap') const requireInject = require('require-inject') +const mockNpm = require('../fixtures/mock-npm') test('whoami', (t) => { t.plan(3) const Whoami = requireInject('../../lib/whoami.js', { '../../lib/utils/get-identity.js': () => Promise.resolve('foo'), }) - const whoami = new Whoami({ - flatOptions: {}, + const npm = mockNpm({ + config: { json: false }, output: (output) => { t.equal(output, 'foo', 'should output the username') }, }) + const whoami = new Whoami(npm) + whoami.exec([], (err) => { t.ifError(err, 'npm whoami') t.ok('should successfully print username') @@ -24,12 +27,13 @@ test('whoami json', (t) => { const Whoami = requireInject('../../lib/whoami.js', { '../../lib/utils/get-identity.js': () => Promise.resolve('foo'), }) - const whoami = new Whoami({ - flatOptions: { json: true }, + const npm = mockNpm({ + config: { json: true }, output: (output) => { - t.equal(output, '"foo"', 'should output the username as json') + t.equal(output, '"foo"', 'should output the username') }, }) + const whoami = new Whoami(npm) whoami.exec([], (err) => { t.ifError(err, 'npm whoami') diff --git a/deps/npm/test/lib/workspaces/get-workspaces.js b/deps/npm/test/lib/workspaces/get-workspaces.js new file mode 100644 index 0000000000..ebed9dd35c --- /dev/null +++ b/deps/npm/test/lib/workspaces/get-workspaces.js @@ -0,0 +1,199 @@ +const { resolve } = require('path') +const t = require('tap') +const getWorkspaces = require('../../../lib/workspaces/get-workspaces.js') + +const normalizePath = p => p + .replace(/\\+/g, '/') + .replace(/\r\n/g, '\n') + +const cleanOutput = (str, path) => normalizePath(str) + .replace(normalizePath(path), '{PATH}') + +const clean = (res, path) => { + const cleaned = new Map() + for (const [key, value] of res.entries()) + cleaned.set(key, cleanOutput(value, path)) + return cleaned +} + +t.test('get-workspaces', async t => { + const path = t.testdir({ + packages: { + a: { + 'package.json': JSON.stringify({ + name: 'a', + version: '1.0.0', + scripts: { glorp: 'echo a doing the glerp glop' }, + }), + }, + b: { + 'package.json': JSON.stringify({ + name: 'b', + version: '2.0.0', + scripts: { glorp: 'echo b doing the glerp glop' }, + }), + }, + c: { + 'package.json': JSON.stringify({ + name: 'c', + version: '1.0.0', + scripts: { + test: 'exit 0', + posttest: 'echo posttest', + lorem: 'echo c lorem', + }, + }), + }, + d: { + 'package.json': JSON.stringify({ + name: 'd', + version: '1.0.0', + scripts: { + test: 'exit 0', + posttest: 'echo posttest', + }, + }), + }, + e: { + 'package.json': JSON.stringify({ + name: 'e', + scripts: { test: 'exit 0', start: 'echo start something' }, + }), + }, + noscripts: { + 'package.json': JSON.stringify({ + name: 'noscripts', + version: '1.0.0', + }), + }, + }, + 'package.json': JSON.stringify({ + name: 'x', + version: '1.2.3', + workspaces: ['packages/*'], + }), + }) + + let workspaces + + workspaces = await getWorkspaces(['a', 'b'], { path }) + t.deepEqual( + clean(workspaces, path), + new Map(Object.entries({ + a: '{PATH}/packages/a', + b: '{PATH}/packages/b', + })), + 'should filter by package name' + ) + + workspaces = await getWorkspaces(['./packages/c'], { path }) + t.deepEqual( + clean(workspaces, path), + new Map(Object.entries({ + c: '{PATH}/packages/c', + })), + 'should filter by package directory' + ) + + workspaces = await getWorkspaces(['packages/c'], { path }) + t.deepEqual( + clean(workspaces, path), + new Map(Object.entries({ + c: '{PATH}/packages/c', + })), + 'should filter by rel package directory' + ) + + workspaces = await getWorkspaces([resolve(path, 'packages/c')], { path }) + t.deepEqual( + clean(workspaces, path), + new Map(Object.entries({ + c: '{PATH}/packages/c', + })), + 'should filter by absolute package directory' + ) + + workspaces = await getWorkspaces(['packages'], { path }) + t.deepEqual( + clean(workspaces, path), + new Map(Object.entries({ + a: '{PATH}/packages/a', + b: '{PATH}/packages/b', + c: '{PATH}/packages/c', + d: '{PATH}/packages/d', + e: '{PATH}/packages/e', + noscripts: '{PATH}/packages/noscripts', + })), + 'should filter by parent directory name' + ) + + workspaces = await getWorkspaces(['./packages/'], { path }) + t.deepEqual( + clean(workspaces, path), + new Map(Object.entries({ + a: '{PATH}/packages/a', + b: '{PATH}/packages/b', + c: '{PATH}/packages/c', + d: '{PATH}/packages/d', + e: '{PATH}/packages/e', + noscripts: '{PATH}/packages/noscripts', + })), + 'should filter by parent directory path' + ) + + workspaces = await getWorkspaces([resolve(path, './packages')], { path }) + t.deepEqual( + clean(workspaces, path), + new Map(Object.entries({ + a: '{PATH}/packages/a', + b: '{PATH}/packages/b', + c: '{PATH}/packages/c', + d: '{PATH}/packages/d', + e: '{PATH}/packages/e', + noscripts: '{PATH}/packages/noscripts', + })), + 'should filter by absolute parent directory path' + ) + + workspaces = await getWorkspaces([], { path }) + t.deepEqual( + clean(workspaces, path), + new Map(Object.entries({ + a: '{PATH}/packages/a', + b: '{PATH}/packages/b', + c: '{PATH}/packages/c', + d: '{PATH}/packages/d', + e: '{PATH}/packages/e', + noscripts: '{PATH}/packages/noscripts', + })), + 'should return all workspaces if no filter set' + ) + + try { + await getWorkspaces(['missing'], { path }) + throw new Error('missed throw') + } catch (err) { + t.match( + err, + /No workspaces found/, + 'should throw no workspaces found error' + ) + } + + const unconfiguredWorkspaces = t.testdir({ + 'package.json': JSON.stringify({ + name: 'no-configured-workspaces', + version: '1.0.0', + }), + }) + try { + await getWorkspaces([], { path: unconfiguredWorkspaces }) + throw new Error('missed throw') + } catch (err) { + t.match( + err, + /No workspaces found/, + 'should throw no workspaces found error' + ) + } +}) |