diff options
author | npm team <ops+robot@npmjs.com> | 2021-07-15 23:09:18 +0300 |
---|---|---|
committer | Ruy Adorno <ruyadorno@hotmail.com> | 2021-07-21 05:50:42 +0300 |
commit | 65234bbce024dec9d5490b17137abe381a979a28 (patch) | |
tree | 854a54f4afb74e254a800de7f9bcc482723e4942 /deps/npm | |
parent | ad5dc4c4698356e83a9f06eb5fbd337d9cb1317e (diff) |
deps: upgrade npm to 7.20.0
PR-URL: https://github.com/nodejs/node/pull/39403
Reviewed-By: Ruy Adorno <ruyadorno@github.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Diffstat (limited to 'deps/npm')
162 files changed, 4752 insertions, 953 deletions
diff --git a/deps/npm/docs/content/commands/npm-audit.md b/deps/npm/docs/content/commands/npm-audit.md index 704d7a15fb8..94b16b27bd7 100644 --- a/deps/npm/docs/content/commands/npm-audit.md +++ b/deps/npm/docs/content/commands/npm-audit.md @@ -232,6 +232,7 @@ mistakes, unnecessary performance degradation, and malicious input. * Allow unpublishing all versions of a published package. * Allow conflicting peerDependencies to be installed in the root project. * Implicitly set `--yes` during `npm init`. +* Allow clobbering existing values in `npm pkg` 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! @@ -243,6 +244,9 @@ recommended that you do not use this option! Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. #### `package-lock-only` diff --git a/deps/npm/docs/content/commands/npm-ci.md b/deps/npm/docs/content/commands/npm-ci.md index 9645bae7e2f..31c92b13c5c 100644 --- a/deps/npm/docs/content/commands/npm-ci.md +++ b/deps/npm/docs/content/commands/npm-ci.md @@ -69,6 +69,16 @@ cache: <!-- AUTOGENERATED CONFIG DESCRIPTIONS START --> <!-- automatically generated, do not edit manually --> +#### `audit` + +* Default: true +* Type: Boolean + +When "true" submit audit reports alongside the current npm command 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. + #### `ignore-scripts` * Default: false diff --git a/deps/npm/docs/content/commands/npm-config.md b/deps/npm/docs/content/commands/npm-config.md index f2868cb8909..9e76a23671e 100644 --- a/deps/npm/docs/content/commands/npm-config.md +++ b/deps/npm/docs/content/commands/npm-config.md @@ -104,6 +104,9 @@ global config. Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. #### `global` @@ -128,6 +131,14 @@ folder instead of the current working directory. See The command to run for `npm edit` and `npm config edit`. +#### `location` + +* Default: "user" unless `--global` is passed, which will also set this value + to "global" +* Type: "global", "user", or "project" + +When passed to `npm config` this refers to which config file to use. + #### `long` * Default: false diff --git a/deps/npm/docs/content/commands/npm-dedupe.md b/deps/npm/docs/content/commands/npm-dedupe.md index fbccc410532..324e6a71b7a 100644 --- a/deps/npm/docs/content/commands/npm-dedupe.md +++ b/deps/npm/docs/content/commands/npm-dedupe.md @@ -164,9 +164,10 @@ will *not* run any pre- or post-scripts. * 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. +When "true" submit audit reports alongside the current npm command 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. #### `bin-links` diff --git a/deps/npm/docs/content/commands/npm-explain.md b/deps/npm/docs/content/commands/npm-explain.md index 0e50d7ae433..3a87ee8e438 100644 --- a/deps/npm/docs/content/commands/npm-explain.md +++ b/deps/npm/docs/content/commands/npm-explain.md @@ -63,6 +63,9 @@ node_modules/nyc/node_modules/find-up Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. #### `workspace` diff --git a/deps/npm/docs/content/commands/npm-find-dupes.md b/deps/npm/docs/content/commands/npm-find-dupes.md index 28281d5678a..3b28f6443de 100644 --- a/deps/npm/docs/content/commands/npm-find-dupes.md +++ b/deps/npm/docs/content/commands/npm-find-dupes.md @@ -107,9 +107,10 @@ will *not* run any pre- or post-scripts. * 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. +When "true" submit audit reports alongside the current npm command 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. #### `bin-links` diff --git a/deps/npm/docs/content/commands/npm-fund.md b/deps/npm/docs/content/commands/npm-fund.md index 3dc5292b490..ec5f5a37fdb 100644 --- a/deps/npm/docs/content/commands/npm-fund.md +++ b/deps/npm/docs/content/commands/npm-fund.md @@ -73,6 +73,9 @@ test-workspaces-fund@1.0.0 Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. #### `browser` diff --git a/deps/npm/docs/content/commands/npm-init.md b/deps/npm/docs/content/commands/npm-init.md index 23e8e70d9e9..54c3bdb4b74 100644 --- a/deps/npm/docs/content/commands/npm-init.md +++ b/deps/npm/docs/content/commands/npm-init.md @@ -175,6 +175,7 @@ mistakes, unnecessary performance degradation, and malicious input. * Allow unpublishing all versions of a published package. * Allow conflicting peerDependencies to be installed in the root project. * Implicitly set `--yes` during `npm init`. +* Allow clobbering existing values in `npm pkg` 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! diff --git a/deps/npm/docs/content/commands/npm-install-ci-test.md b/deps/npm/docs/content/commands/npm-install-ci-test.md index c337905a056..2640311cf94 100644 --- a/deps/npm/docs/content/commands/npm-install-ci-test.md +++ b/deps/npm/docs/content/commands/npm-install-ci-test.md @@ -20,6 +20,16 @@ This command runs `npm ci` followed immediately by `npm test`. <!-- AUTOGENERATED CONFIG DESCRIPTIONS START --> <!-- automatically generated, do not edit manually --> +#### `audit` + +* Default: true +* Type: Boolean + +When "true" submit audit reports alongside the current npm command 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. + #### `ignore-scripts` * Default: false diff --git a/deps/npm/docs/content/commands/npm-install-test.md b/deps/npm/docs/content/commands/npm-install-test.md index deefbd96b52..c8533cafedd 100644 --- a/deps/npm/docs/content/commands/npm-install-test.md +++ b/deps/npm/docs/content/commands/npm-install-test.md @@ -149,9 +149,10 @@ will *not* run any pre- or post-scripts. * 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. +When "true" submit audit reports alongside the current npm command 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. #### `bin-links` diff --git a/deps/npm/docs/content/commands/npm-install.md b/deps/npm/docs/content/commands/npm-install.md index e5091e6604c..70d4c0d46ff 100644 --- a/deps/npm/docs/content/commands/npm-install.md +++ b/deps/npm/docs/content/commands/npm-install.md @@ -533,9 +533,10 @@ will *not* run any pre- or post-scripts. * 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. +When "true" submit audit reports alongside the current npm command 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. #### `bin-links` diff --git a/deps/npm/docs/content/commands/npm-link.md b/deps/npm/docs/content/commands/npm-link.md index b1c6066768a..c7b38500951 100644 --- a/deps/npm/docs/content/commands/npm-link.md +++ b/deps/npm/docs/content/commands/npm-link.md @@ -233,9 +233,10 @@ will *not* run any pre- or post-scripts. * 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. +When "true" submit audit reports alongside the current npm command 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. #### `bin-links` diff --git a/deps/npm/docs/content/commands/npm-ls.md b/deps/npm/docs/content/commands/npm-ls.md index 1f401fa956f..350f40a9991 100644 --- a/deps/npm/docs/content/commands/npm-ls.md +++ b/deps/npm/docs/content/commands/npm-ls.md @@ -91,6 +91,9 @@ upon by the current project. Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. #### `long` diff --git a/deps/npm/docs/content/commands/npm-org.md b/deps/npm/docs/content/commands/npm-org.md index e6df560acfb..269f5cc3ee5 100644 --- a/deps/npm/docs/content/commands/npm-org.md +++ b/deps/npm/docs/content/commands/npm-org.md @@ -87,6 +87,9 @@ password, npm will prompt on the command line for one. Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. #### `parseable` diff --git a/deps/npm/docs/content/commands/npm-outdated.md b/deps/npm/docs/content/commands/npm-outdated.md index bc9263d7aed..40e5feafd4c 100644 --- a/deps/npm/docs/content/commands/npm-outdated.md +++ b/deps/npm/docs/content/commands/npm-outdated.md @@ -104,6 +104,9 @@ upon by the current project. Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. #### `long` diff --git a/deps/npm/docs/content/commands/npm-pack.md b/deps/npm/docs/content/commands/npm-pack.md index 95070262784..cd4a175919e 100644 --- a/deps/npm/docs/content/commands/npm-pack.md +++ b/deps/npm/docs/content/commands/npm-pack.md @@ -34,6 +34,9 @@ Note: This is NOT honored by other network related commands, eg `dist-tags`, Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. #### `pack-destination` diff --git a/deps/npm/docs/content/commands/npm-pkg.md b/deps/npm/docs/content/commands/npm-pkg.md new file mode 100644 index 00000000000..78b13cf9e9a --- /dev/null +++ b/deps/npm/docs/content/commands/npm-pkg.md @@ -0,0 +1,245 @@ +--- +title: npm-pkg +section: 1 +description: Manages your package.json +--- + +### Synopsis + +```bash +npm pkg get [<field> [.<subfield> ...]] +npm pkg set <field>=<value> [.<subfield>=<value> ...] +npm pkg delete <field> [.<subfield> ...] +``` + +### Description + +A command that automates the management of `package.json` files. +`npm pkg` provide 3 different sub commands that allow you to modify or retrieve +values for given object keys in your `packge.json`. + +The syntax to retrieve and set fields is a dot separated representation of +the nested object properties to be found within your `package.json`, it's the +same notation used in [`npm view`](/commands/npm-view) to retrieve information +from the registry manifest, below you can find more examples on how to use it. + +Returned values are always in **json** format. + +* `npm pkg get <field>` + + Retrieves a value `key`, defined in your `package.json` file. + + For example, in order to retrieve the name of the current package, you + can run: + + ```bash + npm pkg get name + ``` + + It's also possible to retrieve multiple values at once: + + ```bash + npm pkg get name version + ``` + + You can view child fields by separating them with a period. To retrieve + the value of a test `script` value, you would run the following command: + + ```bash + npm pkg get scripts.test + ``` + + For fields that are arrays, requesting a non-numeric field will return + all of the values from the objects in the list. For example, to get all + the contributor emails for a package, you would run: + + ```bash + npm pkg get contributors.email + ``` + + You may also use numeric indices in square braces to specifically select + an item in an array field. To just get the email address of the first + contributor in the list, you can run: + + ```bash + npm pkg get contributors[0].email + ``` + +* `npm pkg set <field>=<value>` + + Sets a `value` in your `package.json` based on the `field` value. When + saving to your `package.json` file the same set of rules used during + `npm install` and other cli commands that touches the `package.json` file + are used, making sure to respect the existing indentation and possibly + applying some validation prior to saving values to the file. + + The same syntax used to retrieve values from your package can also be used + to define new properties or overriding existing ones, below are some + examples of how the dot separated syntax can be used to edit your + `package.json` file. + + Defining a new bin named `mynewcommand` in your `package.json` that points + to a file `cli.js`: + + ```bash + npm pkg set bin.mynewcommand=cli.js + ``` + + Setting multiple fields at once is also possible: + + ```bash + npm pkg set description='Awesome package' engines.node='>=10' + ``` + + It's also possible to add to array values, for example to add a new + contributor entry: + + ```bash + npm pkg set contributors[0].name='Foo' contributors[0].email='foo@bar.ca' + ``` + + You may also append items to the end of an array using the special + empty bracket notation: + + ```bash + npm pkg set contributors[].name='Foo' contributors[].name='Bar' + ``` + + It's also possible to parse values as json prior to saving them to your + `package.json` file, for example in order to set a `"private": true` + property: + + ```bash + npm pkg set private=true --json + ``` + + It also enables saving values as numbers: + + ```bash + npm pkg set tap.timeout=60 --json + ``` + +* `npm pkg delete <key>` + + Deletes a `key` from your `package.json` + + The same syntax used to set values from your package can also be used + to remove existing ones. For example, in order to remove a script named + build: + + ```bash + npm pkg delete scripts.build + ``` + +### Workspaces support + +You can set/get/delete items across your configured workspaces by using the +`workspace` or `workspaces` config options. + +For example, setting a `funding` value across all configured workspaces +of a project: + +```bash +npm pkg set funding=https://example.com --ws +``` + +When using `npm pkg get` to retrieve info from your configured workspaces, the +returned result will be in a json format in which top level keys are the +names of each workspace, the values of these keys will be the result values +returned from each of the configured workspaces, e.g: + +``` +npm pkg get name version --ws +{ + "a": { + "name": "a", + "version": "1.0.0" + }, + "b": { + "name": "b", + "version": "1.0.0" + } +} +``` + +### Configuration + +<!-- AUTOGENERATED CONFIG DESCRIPTIONS START --> +<!-- automatically generated, do not edit manually --> +#### `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. +* Implicitly set `--yes` during `npm init`. +* Allow clobbering existing values in `npm pkg` + +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! + +#### `json` + +* Default: false +* Type: Boolean + +Whether or not to output JSON data, rather than the normal output. + +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + +Not supported by all npm commands. + +#### `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) + +When set for the `npm init` command, this may be set to the folder of a +workspace which does not yet exist, to create the folder and set it up as a +brand new workspace within the project. + +This value is not exported to the environment for child processes. + +#### `workspaces` + +* Default: false +* Type: Boolean + +Enable running a command in the context of **all** the configured +workspaces. + +This value is not exported to the environment for child processes. + +<!-- AUTOGENERATED CONFIG DESCRIPTIONS END --> +## See Also + +* [npm install](/commands/npm-install) +* [npm init](/commands/npm-init) +* [npm config](/commands/npm-config) +* [npm set-script](/commands/npm-set-script) +* [workspaces](/using-npm/workspaces) diff --git a/deps/npm/docs/content/commands/npm-profile.md b/deps/npm/docs/content/commands/npm-profile.md index 63aa46540d3..079440d7858 100644 --- a/deps/npm/docs/content/commands/npm-profile.md +++ b/deps/npm/docs/content/commands/npm-profile.md @@ -91,6 +91,9 @@ The base URL of the npm registry. Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. #### `parseable` diff --git a/deps/npm/docs/content/commands/npm-prune.md b/deps/npm/docs/content/commands/npm-prune.md index ecb6bdcd6cb..d9b5b068f7a 100644 --- a/deps/npm/docs/content/commands/npm-prune.md +++ b/deps/npm/docs/content/commands/npm-prune.md @@ -75,6 +75,9 @@ Note: This is NOT honored by other network related commands, eg `dist-tags`, Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. #### `workspace` diff --git a/deps/npm/docs/content/commands/npm-search.md b/deps/npm/docs/content/commands/npm-search.md index 08c955e64b5..e30287635b5 100644 --- a/deps/npm/docs/content/commands/npm-search.md +++ b/deps/npm/docs/content/commands/npm-search.md @@ -55,6 +55,9 @@ Show extended information in `ls`, `search`, and `help-search`. Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. #### `color` diff --git a/deps/npm/docs/content/commands/npm-team.md b/deps/npm/docs/content/commands/npm-team.md index 31b09c7ce22..c7d5defcc63 100644 --- a/deps/npm/docs/content/commands/npm-team.md +++ b/deps/npm/docs/content/commands/npm-team.md @@ -138,6 +138,9 @@ Output parseable results from commands that write to standard output. For Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. <!-- AUTOGENERATED CONFIG DESCRIPTIONS END --> diff --git a/deps/npm/docs/content/commands/npm-unpublish.md b/deps/npm/docs/content/commands/npm-unpublish.md index bc8fbc7a53b..82779ab6593 100644 --- a/deps/npm/docs/content/commands/npm-unpublish.md +++ b/deps/npm/docs/content/commands/npm-unpublish.md @@ -82,6 +82,7 @@ mistakes, unnecessary performance degradation, and malicious input. * Allow unpublishing all versions of a published package. * Allow conflicting peerDependencies to be installed in the root project. * Implicitly set `--yes` during `npm init`. +* Allow clobbering existing values in `npm pkg` 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! diff --git a/deps/npm/docs/content/commands/npm-update.md b/deps/npm/docs/content/commands/npm-update.md index 4c9271c6633..c4f7694e19a 100644 --- a/deps/npm/docs/content/commands/npm-update.md +++ b/deps/npm/docs/content/commands/npm-update.md @@ -15,7 +15,9 @@ aliases: up, upgrade ### Description This command will update all the packages listed to the latest version -(specified by the `tag` config), respecting semver. +(specified by the `tag` config), respecting the semver constraints of +both your package and its dependencies (if they also require the same +package). It will also install missing packages. @@ -101,6 +103,39 @@ Then `npm update` will install `dep1@0.4.1`, because that is the highest-sorting version that satisfies `^0.4.0` (`>= 0.4.0 <0.5.0`) +#### Subdependencies + +Suppose your app now also has a dependency on `dep2` + +```json +{ + "name": "my-app", + "dependencies": { + "dep1": "^1.0.0", + "dep2": "1.0.0" + } +} +``` + +and `dep2` itself depends on this limited range of `dep1` + +```json +{ +"name": "dep2", + "dependencies": { + "dep1": "~1.1.1" + } +} +``` + +Then `npm update` will install `dep1@1.1.2` because that is the highest +version that `dep2` allows. npm will prioritize having a single version +of `dep1` in your tree rather than two when that single version can +satisfy the semver requirements of multiple dependencies in your tree. +In this case if you really did need your package to use a newer version +you would need to use `npm install`. + + #### Updating Globally-Installed Packages `npm update -g` will apply the `update` action to each globally installed @@ -220,9 +255,10 @@ will *not* run any pre- or post-scripts. * 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. +When "true" submit audit reports alongside the current npm command 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. #### `bin-links` diff --git a/deps/npm/docs/content/commands/npm-version.md b/deps/npm/docs/content/commands/npm-version.md index d24207d1e7e..a3e34153a06 100644 --- a/deps/npm/docs/content/commands/npm-version.md +++ b/deps/npm/docs/content/commands/npm-version.md @@ -47,6 +47,9 @@ Tag the commit when using the `npm version` command. Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. #### `preid` diff --git a/deps/npm/docs/content/commands/npm-view.md b/deps/npm/docs/content/commands/npm-view.md index 8cbd3267b4b..b3d5df86e34 100644 --- a/deps/npm/docs/content/commands/npm-view.md +++ b/deps/npm/docs/content/commands/npm-view.md @@ -49,7 +49,7 @@ npm view opts@$(npm view ronn dependencies.opts) For fields that are arrays, requesting a non-numeric field will return all of the values from the objects in the list. For example, to get all -the contributor names for the `express` package, you would run: +the contributor email addresses for the `express` package, you would run: ```bash npm view express contributors.email @@ -105,6 +105,9 @@ npm view connect versions Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. #### `workspace` diff --git a/deps/npm/docs/content/configuring-npm/folders.md b/deps/npm/docs/content/configuring-npm/folders.md index 75e31cd7331..218870765b2 100644 --- a/deps/npm/docs/content/configuring-npm/folders.md +++ b/deps/npm/docs/content/configuring-npm/folders.md @@ -45,14 +45,16 @@ Global installs on Windows go to `{prefix}/node_modules` (that is, no Scoped packages are installed the same way, except they are grouped together in a sub-folder of the relevant `node_modules` folder with the name of that scope prefix by the @ symbol, e.g. `npm install @myorg/package` would place -the package in `{prefix}/node_modules/@myorg/package`. See [`scope`](/using-npm/scope) for more details. +the package in `{prefix}/node_modules/@myorg/package`. See +[`scope`](/using-npm/scope) for more details. If you wish to `require()` a package, then install it locally. #### Executables When in global mode, executables are linked into `{prefix}/bin` on Unix, -or directly into `{prefix}` on Windows. +or directly into `{prefix}` on Windows. Ensure that path is in your +terminal's `PATH` environment to run them. When in local mode, executables are linked into `./node_modules/.bin` so that they can be made available to scripts run diff --git a/deps/npm/docs/content/configuring-npm/package-json.md b/deps/npm/docs/content/configuring-npm/package-json.md index 5cacf68ba17..0fc5dc5075e 100644 --- a/deps/npm/docs/content/configuring-npm/package-json.md +++ b/deps/npm/docs/content/configuring-npm/package-json.md @@ -341,9 +341,12 @@ install into the PATH. npm makes this pretty easy (in fact, it uses this feature to install the "npm" executable.) To use this, supply a `bin` field in your package.json which is a map of -command name to local file name. On install, npm will symlink that file -into `prefix/bin` for global installs, or `./node_modules/.bin/` for local -installs. +command name to local file name. When this package is installed +globally, that file will be linked where global bins go so it is +available to run by name. When this package is installed as a +dependency in another package, the file will be linked where it will be +available to that package either directly by `npm exec` or by name in other +scripts when invoking them via `npm run-script`. For example, myapp could have this: @@ -388,6 +391,9 @@ executable! Note that you can also set the executable files using [directories.bin](#directoriesbin). +See [folders](/configuring-npm/folders#executables) for more info on +executables. + ### man Specify either a single file or an array of filenames to put in place for diff --git a/deps/npm/docs/content/using-npm/config.md b/deps/npm/docs/content/using-npm/config.md index 1036895101f..c4d1afed35c 100644 --- a/deps/npm/docs/content/using-npm/config.md +++ b/deps/npm/docs/content/using-npm/config.md @@ -67,6 +67,7 @@ The following shorthands are parsed on the command-line: * `--desc`: `--description` * `-f`: `--force` * `-g`: `--global` +* `-L`: `--location` * `-d`: `--loglevel info` * `-s`: `--loglevel silent` * `--silent`: `--loglevel silent` @@ -170,9 +171,10 @@ to the same value as the current version. * 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. +When "true" submit audit reports alongside the current npm command 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` @@ -495,6 +497,7 @@ mistakes, unnecessary performance degradation, and malicious input. * Allow unpublishing all versions of a published package. * Allow conflicting peerDependencies to be installed in the root project. * Implicitly set `--yes` during `npm init`. +* Allow clobbering existing values in `npm pkg` 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! @@ -694,6 +697,9 @@ number, if not already set in package.json. Whether or not to output JSON data, rather than the normal output. +* In `npm pkg set` it enables parsing set values with JSON.parse() before + saving them to your `package.json`. + Not supported by all npm commands. #### `key` @@ -753,6 +759,14 @@ Used with `npm ls`, limiting output to only those packages that are linked. 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. +#### `location` + +* Default: "user" unless `--global` is passed, which will also set this value + to "global" +* Type: "global", "user", or "project" + +When passed to `npm config` this refers to which config file to use. + #### `loglevel` * Default: "notice" diff --git a/deps/npm/docs/content/using-npm/scripts.md b/deps/npm/docs/content/using-npm/scripts.md index 8df9660ca8f..8fd5c5c0dbc 100644 --- a/deps/npm/docs/content/using-npm/scripts.md +++ b/deps/npm/docs/content/using-npm/scripts.md @@ -54,7 +54,8 @@ situations. These scripts happen in addition to the `pre<event>`, `post<event>`, the prepare script will be run, before the package is packaged and installed. -* As of `npm@7` these scripts run in the background +* As of `npm@7` these scripts run in the background. + To see the output, run with: `--foreground-scripts`. **prepublish** (DEPRECATED) * Does not run during `npm publish`, but does run during `npm ci` @@ -303,8 +304,8 @@ Scripts are run by passing the line as a script argument to `sh`. If the script exits with a code other than 0, then this will abort the process. -Note that these script files don't have to be nodejs or even -javascript programs. They just have to be some kind of executable +Note that these script files don't have to be Node.js or even +JavaScript programs. They just have to be some kind of executable file. ### Best Practices diff --git a/deps/npm/docs/content/using-npm/workspaces.md b/deps/npm/docs/content/using-npm/workspaces.md index 829168864ab..7cc125b3c7a 100644 --- a/deps/npm/docs/content/using-npm/workspaces.md +++ b/deps/npm/docs/content/using-npm/workspaces.md @@ -37,7 +37,7 @@ Workspaces are usually defined via the `workspaces` property of the Given the above `package.json` example living at a current working directory `.` that contains a folder named `workspace-a` that itself contains -a `package.json` inside it, defining a nodejs package, e.g: +a `package.json` inside it, defining a Node.js package, e.g: ``` . diff --git a/deps/npm/docs/output/commands/npm-audit.html b/deps/npm/docs/output/commands/npm-audit.html index a1c58d89633..5cffb546dc7 100644 --- a/deps/npm/docs/output/commands/npm-audit.html +++ b/deps/npm/docs/output/commands/npm-audit.html @@ -309,6 +309,7 @@ range (including SemVer-major changes).</li> <li>Allow unpublishing all versions of a published package.</li> <li>Allow conflicting peerDependencies to be installed in the root project.</li> <li>Implicitly set <code>--yes</code> during <code>npm init</code>.</li> +<li>Allow clobbering existing values in <code>npm pkg</code></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> @@ -318,6 +319,10 @@ recommended that you do not use this option!</p> <li>Type: Boolean</li> </ul> <p>Whether or not to output JSON data, rather than the normal output.</p> +<ul> +<li>In <code>npm pkg set</code> it enables parsing set values with JSON.parse() before +saving them to your <code>package.json</code>.</li> +</ul> <p>Not supported by all npm commands.</p> <h4 id="package-lock-only"><code>package-lock-only</code></h4> <ul> diff --git a/deps/npm/docs/output/commands/npm-ci.html b/deps/npm/docs/output/commands/npm-ci.html index 82049f7287d..9f5c85b3637 100644 --- a/deps/npm/docs/output/commands/npm-ci.html +++ b/deps/npm/docs/output/commands/npm-ci.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="#example">Example</a></li><li><a href="#configuration">Configuration</a></li><ul><li><a href="#ignore-scripts"><code>ignore-scripts</code></a></li><li><a href="#script-shell"><code>script-shell</code></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="#example">Example</a></li><li><a href="#configuration">Configuration</a></li><ul><li><a href="#audit"><code>audit</code></a></li><li><a href="#ignore-scripts"><code>ignore-scripts</code></a></li><li><a href="#script-shell"><code>script-shell</code></a></li></ul><li><a href="#see-also">See Also</a></li></ul></div> </section> <div id="_content"><h3 id="synopsis">Synopsis</h3> @@ -193,6 +193,15 @@ cache: <h3 id="configuration">Configuration</h3> <!-- raw HTML omitted --> <!-- raw HTML omitted --> +<h4 id="audit"><code>audit</code></h4> +<ul> +<li>Default: true</li> +<li>Type: Boolean</li> +</ul> +<p>When “true” submit audit reports alongside the current npm command 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="ignore-scripts"><code>ignore-scripts</code></h4> <ul> <li>Default: false</li> diff --git a/deps/npm/docs/output/commands/npm-config.html b/deps/npm/docs/output/commands/npm-config.html index 385d5d4ee15..8d6e1620720 100644 --- a/deps/npm/docs/output/commands/npm-config.html +++ b/deps/npm/docs/output/commands/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="#synopsis">Synopsis</a></li><li><a href="#description">Description</a></li><li><a href="#sub-commands">Sub-commands</a></li><ul><li><a href="#set">set</a></li><li><a href="#get">get</a></li><li><a href="#list">list</a></li><li><a href="#delete">delete</a></li><li><a href="#edit2">edit</a></li></ul><li><a href="#configuration">Configuration</a></li><ul><li><a href="#json"><code>json</code></a></li><li><a href="#global"><code>global</code></a></li><li><a href="#editor"><code>editor</code></a></li><li><a href="#long"><code>long</code></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="#sub-commands">Sub-commands</a></li><ul><li><a href="#set">set</a></li><li><a href="#get">get</a></li><li><a href="#list">list</a></li><li><a href="#delete">delete</a></li><li><a href="#edit2">edit</a></li></ul><li><a href="#configuration">Configuration</a></li><ul><li><a href="#json"><code>json</code></a></li><li><a href="#global"><code>global</code></a></li><li><a href="#editor"><code>editor</code></a></li><li><a href="#location"><code>location</code></a></li><li><a href="#long"><code>long</code></a></li></ul><li><a href="#see-also">See Also</a></li></ul></div> </section> <div id="_content"><h3 id="synopsis">Synopsis</h3> @@ -206,6 +206,10 @@ global config.</p> <li>Type: Boolean</li> </ul> <p>Whether or not to output JSON data, rather than the normal output.</p> +<ul> +<li>In <code>npm pkg set</code> it enables parsing set values with JSON.parse() before +saving them to your <code>package.json</code>.</li> +</ul> <p>Not supported by all npm commands.</p> <h4 id="global"><code>global</code></h4> <ul> @@ -228,6 +232,13 @@ 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="location"><code>location</code></h4> +<ul> +<li>Default: “user” unless <code>--global</code> is passed, which will also set this value +to “global”</li> +<li>Type: “global”, “user”, or “project”</li> +</ul> +<p>When passed to <code>npm config</code> this refers to which config file to use.</p> <h4 id="long"><code>long</code></h4> <ul> <li>Default: false</li> diff --git a/deps/npm/docs/output/commands/npm-dedupe.html b/deps/npm/docs/output/commands/npm-dedupe.html index c1fe98aeead..9de232141e1 100644 --- a/deps/npm/docs/output/commands/npm-dedupe.html +++ b/deps/npm/docs/output/commands/npm-dedupe.html @@ -269,9 +269,10 @@ will <em>not</em> run any pre- or post-scripts.</p> <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> +<p>When “true” submit audit reports alongside the current npm command 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="bin-links"><code>bin-links</code></h4> <ul> <li>Default: true</li> diff --git a/deps/npm/docs/output/commands/npm-explain.html b/deps/npm/docs/output/commands/npm-explain.html index 1c3afda5a16..decfd4d556e 100644 --- a/deps/npm/docs/output/commands/npm-explain.html +++ b/deps/npm/docs/output/commands/npm-explain.html @@ -190,6 +190,10 @@ node_modules/nyc/node_modules/find-up <li>Type: Boolean</li> </ul> <p>Whether or not to output JSON data, rather than the normal output.</p> +<ul> +<li>In <code>npm pkg set</code> it enables parsing set values with JSON.parse() before +saving them to your <code>package.json</code>.</li> +</ul> <p>Not supported by all npm commands.</p> <h4 id="workspace"><code>workspace</code></h4> <ul> diff --git a/deps/npm/docs/output/commands/npm-find-dupes.html b/deps/npm/docs/output/commands/npm-find-dupes.html index d727f561dfe..9f6c4de7857 100644 --- a/deps/npm/docs/output/commands/npm-find-dupes.html +++ b/deps/npm/docs/output/commands/npm-find-dupes.html @@ -228,9 +228,10 @@ will <em>not</em> run any pre- or post-scripts.</p> <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> +<p>When “true” submit audit reports alongside the current npm command 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="bin-links"><code>bin-links</code></h4> <ul> <li>Default: true</li> diff --git a/deps/npm/docs/output/commands/npm-fund.html b/deps/npm/docs/output/commands/npm-fund.html index a37ff56e145..074ac105735 100644 --- a/deps/npm/docs/output/commands/npm-fund.html +++ b/deps/npm/docs/output/commands/npm-fund.html @@ -195,6 +195,10 @@ test-workspaces-fund@1.0.0 <li>Type: Boolean</li> </ul> <p>Whether or not to output JSON data, rather than the normal output.</p> +<ul> +<li>In <code>npm pkg set</code> it enables parsing set values with JSON.parse() before +saving them to your <code>package.json</code>.</li> +</ul> <p>Not supported by all npm commands.</p> <h4 id="browser"><code>browser</code></h4> <ul> diff --git a/deps/npm/docs/output/commands/npm-init.html b/deps/npm/docs/output/commands/npm-init.html index 79538c36ace..eaa5dfe0f72 100644 --- a/deps/npm/docs/output/commands/npm-init.html +++ b/deps/npm/docs/output/commands/npm-init.html @@ -273,6 +273,7 @@ range (including SemVer-major changes).</li> <li>Allow unpublishing all versions of a published package.</li> <li>Allow conflicting peerDependencies to be installed in the root project.</li> <li>Implicitly set <code>--yes</code> during <code>npm init</code>.</li> +<li>Allow clobbering existing values in <code>npm pkg</code></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> diff --git a/deps/npm/docs/output/commands/npm-install-ci-test.html b/deps/npm/docs/output/commands/npm-install-ci-test.html index 3982ad2da20..d7414ff56cf 100644 --- a/deps/npm/docs/output/commands/npm-install-ci-test.html +++ b/deps/npm/docs/output/commands/npm-install-ci-test.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="#configuration">Configuration</a></li><ul><li><a href="#ignore-scripts"><code>ignore-scripts</code></a></li><li><a href="#script-shell"><code>script-shell</code></a></li></ul><li><a href="#see-also">See Also</a></li></ul></div> +<div id="_table_of_contents"><ul><li><a href="#synopsis">Synopsis</a></li><li><a href="#description">Description</a></li><li><a href="#configuration">Configuration</a></li><ul><li><a href="#audit"><code>audit</code></a></li><li><a href="#ignore-scripts"><code>ignore-scripts</code></a></li><li><a href="#script-shell"><code>script-shell</code></a></li></ul><li><a href="#see-also">See Also</a></li></ul></div> </section> <div id="_content"><h3 id="synopsis">Synopsis</h3> @@ -154,6 +154,15 @@ alias: npm cit <h3 id="configuration">Configuration</h3> <!-- raw HTML omitted --> <!-- raw HTML omitted --> +<h4 id="audit"><code>audit</code></h4> +<ul> +<li>Default: true</li> +<li>Type: Boolean</li> +</ul> +<p>When “true” submit audit reports alongside the current npm command 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="ignore-scripts"><code>ignore-scripts</code></h4> <ul> <li>Default: false</li> diff --git a/deps/npm/docs/output/commands/npm-install-test.html b/deps/npm/docs/output/commands/npm-install-test.html index be781628967..d2f536e5d81 100644 --- a/deps/npm/docs/output/commands/npm-install-test.html +++ b/deps/npm/docs/output/commands/npm-install-test.html @@ -267,9 +267,10 @@ will <em>not</em> run any pre- or post-scripts.</p> <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> +<p>When “true” submit audit reports alongside the current npm command 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="bin-links"><code>bin-links</code></h4> <ul> <li>Default: true</li> diff --git a/deps/npm/docs/output/commands/npm-install.html b/deps/npm/docs/output/commands/npm-install.html index a081c98e1b2..cebc5ac780e 100644 --- a/deps/npm/docs/output/commands/npm-install.html +++ b/deps/npm/docs/output/commands/npm-install.html @@ -589,9 +589,10 @@ will <em>not</em> run any pre- or post-scripts.</p> <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> +<p>When “true” submit audit reports alongside the current npm command 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="bin-links"><code>bin-links</code></h4> <ul> <li>Default: true</li> diff --git a/deps/npm/docs/output/commands/npm-link.html b/deps/npm/docs/output/commands/npm-link.html index d558cb9d0a5..6ac2699867e 100644 --- a/deps/npm/docs/output/commands/npm-link.html +++ b/deps/npm/docs/output/commands/npm-link.html @@ -323,9 +323,10 @@ will <em>not</em> run any pre- or post-scripts.</p> <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> +<p>When “true” submit audit reports alongside the current npm command 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="bin-links"><code>bin-links</code></h4> <ul> <li>Default: true</li> diff --git a/deps/npm/docs/output/commands/npm-ls.html b/deps/npm/docs/output/commands/npm-ls.html index e79b119cee8..8af88b78dd5 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.19.1 /path/to/npm +<pre lang="bash"><code>npm@7.20.0 /path/to/npm └─┬ init-package-json@0.0.4 └── promzard@0.1.5 </code></pre> @@ -208,6 +208,10 @@ upon by the current project.</p> <li>Type: Boolean</li> </ul> <p>Whether or not to output JSON data, rather than the normal output.</p> +<ul> +<li>In <code>npm pkg set</code> it enables parsing set values with JSON.parse() before +saving them to your <code>package.json</code>.</li> +</ul> <p>Not supported by all npm commands.</p> <h4 id="long"><code>long</code></h4> <ul> diff --git a/deps/npm/docs/output/commands/npm-org.html b/deps/npm/docs/output/commands/npm-org.html index 3b6df5123f9..b9b976f05f9 100644 --- a/deps/npm/docs/output/commands/npm-org.html +++ b/deps/npm/docs/output/commands/npm-org.html @@ -197,6 +197,10 @@ password, npm will prompt on the command line for one.</p> <li>Type: Boolean</li> </ul> <p>Whether or not to output JSON data, rather than the normal output.</p> +<ul> +<li>In <code>npm pkg set</code> it enables parsing set values with JSON.parse() before +saving them to your <code>package.json</code>.</li> +</ul> <p>Not supported by all npm commands.</p> <h4 id="parseable"><code>parseable</code></h4> <ul> diff --git a/deps/npm/docs/output/commands/npm-outdated.html b/deps/npm/docs/output/commands/npm-outdated.html index 3a45257b3d1..2584460fe6b 100644 --- a/deps/npm/docs/output/commands/npm-outdated.html +++ b/deps/npm/docs/output/commands/npm-outdated.html @@ -230,6 +230,10 @@ upon by the current project.</p> <li>Type: Boolean</li> </ul> <p>Whether or not to output JSON data, rather than the normal output.</p> +<ul> +<li>In <code>npm pkg set</code> it enables parsing set values with JSON.parse() before +saving them to your <code>package.json</code>.</li> +</ul> <p>Not supported by all npm commands.</p> <h4 id="long"><code>long</code></h4> <ul> diff --git a/deps/npm/docs/output/commands/npm-pack.html b/deps/npm/docs/output/commands/npm-pack.html index 622d88306ca..a569ff799aa 100644 --- a/deps/npm/docs/output/commands/npm-pack.html +++ b/deps/npm/docs/output/commands/npm-pack.html @@ -167,6 +167,10 @@ commands that modify your local installation, eg, <code>install</code>, <code>up <li>Type: Boolean</li> </ul> <p>Whether or not to output JSON data, rather than the normal output.</p> +<ul> +<li>In <code>npm pkg set</code> it enables parsing set values with JSON.parse() before +saving them to your <code>package.json</code>.</li> +</ul> <p>Not supported by all npm commands.</p> <h4 id="pack-destination"><code>pack-destination</code></h4> <ul> diff --git a/deps/npm/docs/output/commands/npm-pkg.html b/deps/npm/docs/output/commands/npm-pkg.html new file mode 100644 index 00000000000..1f8a86e76e5 --- /dev/null +++ b/deps/npm/docs/output/commands/npm-pkg.html @@ -0,0 +1,343 @@ +<html><head> +<title>npm-pkg</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-pkg">npm-pkg</h1> +<span class="description">Manages your package.json</span> +</header> + +<section id="table_of_contents"> +<h2 id="table-of-contents">Table of contents</h2> +<div id="_table_of_contents"><ul><li><a href="#see-also">See Also</a></li></ul></div> +</section> + +<div id="_content"><h3 id="synopsis">Synopsis</h3> +<pre lang="bash"><code>npm pkg get [<field> [.<subfield> ...]] +npm pkg set <field>=<value> [.<subfield>=<value> ...] +npm pkg delete <field> [.<subfield> ...] +</code></pre> +<h3 id="description">Description</h3> +<p>A command that automates the management of <code>package.json</code> files. +<code>npm pkg</code> provide 3 different sub commands that allow you to modify or retrieve +values for given object keys in your <code>packge.json</code>.</p> +<p>The syntax to retrieve and set fields is a dot separated representation of +the nested object properties to be found within your <code>package.json</code>, it’s the +same notation used in <a href="../commands/npm-view.html"><code>npm view</code></a> to retrieve information +from the registry manifest, below you can find more examples on how to use it.</p> +<p>Returned values are always in <strong>json</strong> format.</p> +<ul> +<li> +<p><code>npm pkg get <field></code></p> +<p>Retrieves a value <code>key</code>, defined in your <code>package.json</code> file.</p> +<p>For example, in order to retrieve the name of the current package, you +can run:</p> +<pre lang="bash"><code>npm pkg get name +</code></pre> +<p>It’s also possible to retrieve multiple values at once:</p> +<pre lang="bash"><code>npm pkg get name version +</code></pre> +<p>You can view child fields by separating them with a period. To retrieve +the value of a test <code>script</code> value, you would run the following command:</p> +<pre lang="bash"><code>npm pkg get scripts.test +</code></pre> +<p>For fields that are arrays, requesting a non-numeric field will return +all of the values from the objects in the list. For example, to get all +the contributor emails for a package, you would run:</p> +<pre lang="bash"><code>npm pkg get contributors.email +</code></pre> +<p>You may also use numeric indices in square braces to specifically select +an item in an array field. To just get the email address of the first +contributor in the list, you can run:</p> +<pre lang="bash"><code>npm pkg get contributors[0].email +</code></pre> +</li> +<li> +<p><code>npm pkg set <field>=<value></code></p> +<p>Sets a <code>value</code> in your <code>package.json</code> based on the <code>field</code> value. When +saving to your <code>package.json</code> file the same set of rules used during +<code>npm install</code> and other cli commands that touches the <code>package.json</code> file +are used, making sure to respect the existing indentation and possibly +applying some validation prior to saving values to the file.</p> +<p>The same syntax used to retrieve values from your package can also be used +to define new properties or overriding existing ones, below are some +examples of how the dot separated syntax can be used to edit your +<code>package.json</code> file.</p> +<p>Defining a new bin named <code>mynewcommand</code> in your <code>package.json</code> that points +to a file <code>cli.js</code>:</p> +<pre lang="bash"><code>npm pkg set bin.mynewcommand=cli.js +</code></pre> +<p>Setting multiple fields at once is also possible:</p> +<pre lang="bash"><code>npm pkg set description='Awesome package' engines.node='>=10' +</code></pre> +<p>It’s also possible to add to array values, for example to add a new +contributor entry:</p> +<pre lang="bash"><code>npm pkg set contributors[0].name='Foo' contributors[0].email='foo@bar.ca' +</code></pre> +<p>You may also append items to the end of an array using the special +empty bracket notation:</p> +<pre lang="bash"><code>npm pkg set contributors[].name='Foo' contributors[].name='Bar' +</code></pre> +<p>It’s also possible to parse values as json prior to saving them to your +<code>package.json</code> file, for example in order to set a <code>"private": true</code> +property:</p> +<pre lang="bash"><code>npm pkg set private=true --json +</code></pre> +<p>It also enables saving values as numbers:</p> +<pre lang="bash"><code>npm pkg set tap.timeout=60 --json +</code></pre> +</li> +<li> +<p><code>npm pkg delete <key></code></p> +<p>Deletes a <code>key</code> from your <code>package.json</code></p> +<p>The same syntax used to set values from your package can also be used +to remove existing ones. For example, in order to remove a script named +build:</p> +<pre lang="bash"><code>npm pkg delete scripts.build +</code></pre> +</li> +</ul> +<h3 id="workspaces-support">Workspaces support</h3> +<p>You can set/get/delete items across your configured workspaces by using the +<code>workspace</code> or <code>workspaces</code> config options.</p> +<p>For example, setting a <code>funding</code> value across all configured workspaces +of a project:</p> +<pre lang="bash"><code>npm pkg set funding=https://example.com --ws +</code></pre> +<p>When using <code>npm pkg get</code> to retrieve info from your configured workspaces, the +returned result will be in a json format in which top level keys are the +names of each workspace, the values of these keys will be the result values +returned from each of the configured workspaces, e.g:</p> +<pre><code>npm pkg get name version --ws +{ + "a": { + "name": "a", + "version": "1.0.0" + }, + "b": { + "name": "b", + "version": "1.0.0" + } +} +</code></pre> +<h3 id="configuration">Configuration</h3> +<!-- raw HTML omitted --> +<!-- raw HTML omitted --> +<h4 id="force"><code>force</code></h4> +<ul> +<li>Default: false</li> +<li>Type: Boolean</li> +</ul> +<p>Removes various protections against unfortunate side effects, common +mistakes, unnecessary performance degradation, and malicious input.</p> +<ul> +<li>Allow clobbering non-npm files in global installs.</li> +<li>Allow the <code>npm version</code> command to work on an unclean git repository.</li> +<li>Allow deleting the cache folder with <code>npm cache clean</code>.</li> +<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>--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 unpublishing all versions of a published package.</li> +<li>Allow conflicting peerDependencies to be installed in the root project.</li> +<li>Implicitly set <code>--yes</code> during <code>npm init</code>.</li> +<li>Allow clobbering existing values in <code>npm pkg</code></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="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> +<ul> +<li>In <code>npm pkg set</code> it enables parsing set values with JSON.parse() before +saving them to your <code>package.json</code>.</li> +</ul> +<p>Not supported by all npm commands.</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:</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 +nested workspaces)</li> +</ul> +<p>When set for the <code>npm init</code> command, this may be set to the folder of a +workspace which does not yet exist, to create the folder and set it up as a +brand new workspace within the project.</p> +<p>This value is not exported to the environment for child processes.</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> +<p>This value is not exported to the environment for child processes.</p> +<!-- raw HTML omitted --> +<h2 id="see-also">See Also</h2> +<ul> +<li><a href="../commands/npm-install.html">npm install</a></li> +<li><a href="../commands/npm-init.html">npm init</a></li> +<li><a href="../commands/npm-config.html">npm config</a></li> +<li><a href="../commands/npm-set-script.html">npm set-script</a></li> +<li><a href="../using-npm/workspaces.html">workspaces</a></li> +</ul> +</div> + +<footer id="edit"> +<a href="https://github.com/npm/cli/edit/latest/docs/content/commands/npm-pkg.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-profile.html b/deps/npm/docs/output/commands/npm-profile.html index 3f79af93ea3..0c24fffead7 100644 --- a/deps/npm/docs/output/commands/npm-profile.html +++ b/deps/npm/docs/output/commands/npm-profile.html @@ -227,6 +227,10 @@ dist-tag, or changing access via <code>npm access</code> and <code>npm owner</co <li>Type: Boolean</li> </ul> <p>Whether or not to output JSON data, rather than the normal output.</p> +<ul> +<li>In <code>npm pkg set</code> it enables parsing set values with JSON.parse() before +saving them to your <code>package.json</code>.</li> +</ul> <p>Not supported by all npm commands.</p> <h4 id="parseable"><code>parseable</code></h4> <ul> diff --git a/deps/npm/docs/output/commands/npm-prune.html b/deps/npm/docs/output/commands/npm-prune.html index 6011d914b00..2dcfe0e1ce5 100644 --- a/deps/npm/docs/output/commands/npm-prune.html +++ b/deps/npm/docs/output/commands/npm-prune.html @@ -197,6 +197,10 @@ commands that modify your local installation, eg, <code>install</code>, <code>up <li>Type: Boolean</li> </ul> <p>Whether or not to output JSON data, rather than the normal output.</p> +<ul> +<li>In <code>npm pkg set</code> it enables parsing set values with JSON.parse() before +saving them to your <code>package.json</code>.</li> +</ul> <p>Not supported by all npm commands.</p> <h4 id="workspace"><code>workspace</code></h4> <ul> diff --git a/deps/npm/docs/output/commands/npm-search.html b/deps/npm/docs/output/commands/npm-search.html index e3bcffc665f..634229987f2 100644 --- a/deps/npm/docs/output/commands/npm-search.html +++ b/deps/npm/docs/output/commands/npm-search.html @@ -183,6 +183,10 @@ expression characters in most shells.)</p> <li>Type: Boolean</li> </ul> <p>Whether or not to output JSON data, rather than the normal output.</p> +<ul> +<li>In <code>npm pkg set</code> it enables parsing set values with JSON.parse() before +saving them to your <code>package.json</code>.</li> +</ul> <p>Not supported by all npm commands.</p> <h4 id="color"><code>color</code></h4> <ul> diff --git a/deps/npm/docs/output/commands/npm-team.html b/deps/npm/docs/output/commands/npm-team.html index 5f848d56638..3e0d06db228 100644 --- a/deps/npm/docs/output/commands/npm-team.html +++ b/deps/npm/docs/output/commands/npm-team.html @@ -247,6 +247,10 @@ password, npm will prompt on the command line for one.</p> <li>Type: Boolean</li> </ul> <p>Whether or not to output JSON data, rather than the normal output.</p> +<ul> +<li>In <code>npm pkg set</code> it enables parsing set values with JSON.parse() before +saving them to your <code>package.json</code>.</li> +</ul> <p>Not supported by all npm commands.</p> <!-- raw HTML omitted --> <h3 id="see-also">See Also</h3> diff --git a/deps/npm/docs/output/commands/npm-unpublish.html b/deps/npm/docs/output/commands/npm-unpublish.html index 59beb148dfd..3d330e9db5f 100644 --- a/deps/npm/docs/output/commands/npm-unpublish.html +++ b/deps/npm/docs/output/commands/npm-unpublish.html @@ -202,6 +202,7 @@ range (including SemVer-major changes).</li> <li>Allow unpublishing all versions of a published package.</li> <li>Allow conflicting peerDependencies to be installed in the root project.</li> <li>Implicitly set <code>--yes</code> during <code>npm init</code>.</li> +<li>Allow clobbering existing values in <code>npm pkg</code></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> diff --git a/deps/npm/docs/output/commands/npm-update.html b/deps/npm/docs/output/commands/npm-update.html index 044345ab35e..f2491347aee 100644 --- a/deps/npm/docs/output/commands/npm-update.html +++ b/deps/npm/docs/output/commands/npm-update.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="#example">Example</a></li><ul><li><a href="#caret-dependencies">Caret Dependencies</a></li><li><a href="#tilde-dependencies">Tilde Dependencies</a></li><li><a href="#caret-dependencies-below-100">Caret Dependencies below 1.0.0</a></li><li><a href="#updating-globally-installed-packages">Updating Globally-Installed Packages</a></li></ul><li><a href="#configuration">Configuration</a></li><ul><li><a href="#global"><code>global</code></a></li><li><a href="#global-style"><code>global-style</code></a></li><li><a href="#legacy-bundling"><code>legacy-bundling</code></a></li><li><a href="#strict-peer-deps"><code>strict-peer-deps</code></a></li><li><a href="#package-lock"><code>package-lock</code></a></li><li><a href="#omit"><code>omit</code></a></li><li><a href="#ignore-scripts"><code>ignore-scripts</code></a></li><li><a href="#audit"><code>audit</code></a></li><li><a href="#bin-links"><code>bin-links</code></a></li><li><a href="#fund"><code>fund</code></a></li><li><a href="#dry-run"><code>dry-run</code></a></li><li><a href="#workspace"><code>workspace</code></a></li><li><a href="#workspaces"><code>workspaces</code></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="#example">Example</a></li><ul><li><a href="#caret-dependencies">Caret Dependencies</a></li><li><a href="#tilde-dependencies">Tilde Dependencies</a></li><li><a href="#caret-dependencies-below-100">Caret Dependencies below 1.0.0</a></li><li><a href="#subdependencies">Subdependencies</a></li><li><a href="#updating-globally-installed-packages">Updating Globally-Installed Packages</a></li></ul><li><a href="#configuration">Configuration</a></li><ul><li><a href="#global"><code>global</code></a></li><li><a href="#global-style"><code>global-style</code></a></li><li><a href="#legacy-bundling"><code>legacy-bundling</code></a></li><li><a href="#strict-peer-deps"><code>strict-peer-deps</code></a></li><li><a href="#package-lock"><code>package-lock</code></a></li><li><a href="#omit"><code>omit</code></a></li><li><a href="#ignore-scripts"><code>ignore-scripts</code></a></li><li><a href="#audit"><code>audit</code></a></li><li><a href="#bin-links"><code>bin-links</code></a></li><li><a href="#fund"><code>fund</code></a></li><li><a href="#dry-run"><code>dry-run</code></a></li><li><a href="#workspace"><code>workspace</code></a></li><li><a href="#workspaces"><code>workspaces</code></a></li></ul><li><a href="#see-also">See Also</a></li></ul></div> </section> <div id="_content"><h3 id="synopsis">Synopsis</h3> @@ -151,7 +151,9 @@ aliases: up, upgrade </code></pre> <h3 id="description">Description</h3> <p>This command will update all the packages listed to the latest version -(specified by the <code>tag</code> config), respecting semver.</p> +(specified by the <code>tag</code> config), respecting the semver constraints of +both your package and its dependencies (if they also require the same +package).</p> <p>It will also install missing packages.</p> <p>If the <code>-g</code> flag is specified, this command will update globally installed packages.</p> @@ -209,6 +211,30 @@ versions which satisfy <code>^0.2.0</code>.</p> </code></pre> <p>Then <code>npm update</code> will install <code>dep1@0.4.1</code>, because that is the highest-sorting version that satisfies <code>^0.4.0</code> (<code>>= 0.4.0 <0.5.0</code>)</p> +<h4 id="subdependencies">Subdependencies</h4> +<p>Suppose your app now also has a dependency on <code>dep2</code></p> +<pre lang="json"><code>{ + "name": "my-app", + "dependencies": { + "dep1": "^1.0.0", + "dep2": "1.0.0" + } +} +</code></pre> +<p>and <code>dep2</code> itself depends on this limited range of <code>dep1</code></p> +<pre lang="json"><code>{ +"name": "dep2", + "dependencies": { + "dep1": "~1.1.1" + } +} +</code></pre> +<p>Then <code>npm update</code> will install <code>dep1@1.1.2</code> because that is the highest +version that <code>dep2</code> allows. npm will prioritize having a single version +of <code>dep1</code> in your tree rather than two when that single version can +satisfy the semver requirements of multiple dependencies in your tree. +In this case if you really did need your package to use a newer version +you would need to use <code>npm install</code>.</p> <h4 id="updating-globally-installed-packages">Updating Globally-Installed Packages</h4> <p><code>npm update -g</code> will apply the <code>update</code> action to each globally installed package that is <code>outdated</code> – that is, has a version that is different from @@ -310,9 +336,10 @@ will <em>not</em> run any pre- or post-scripts.</p> <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> +<p>When “true” submit audit reports alongside the current npm command 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="bin-links"><code>bin-links</code></h4> <ul> <li>Default: true</li> diff --git a/deps/npm/docs/output/commands/npm-version.html b/deps/npm/docs/output/commands/npm-version.html index 1889060401b..c81569608d5 100644 --- a/deps/npm/docs/output/commands/npm-version.html +++ b/deps/npm/docs/output/commands/npm-version.html @@ -179,6 +179,10 @@ to the same value as the current version.</p> <li>Type: Boolean</li> </ul> <p>Whether or not to output JSON data, rather than the normal output.</p> +<ul> +<li>In <code>npm pkg set</code> it enables parsing set values with JSON.parse() before +saving them to your <code>package.json</code>.</li> +</ul> <p>Not supported by all npm commands.</p> <h4 id="preid"><code>preid</code></h4> <ul> diff --git a/deps/npm/docs/output/commands/npm-view.html b/deps/npm/docs/output/commands/npm-view.html index 54400bd44e8..1a0eba4c143 100644 --- a/deps/npm/docs/output/commands/npm-view.html +++ b/deps/npm/docs/output/commands/npm-view.html @@ -171,7 +171,7 @@ shell scripting. For example, to view all the data about the version of </code></pre> <p>For fields that are arrays, requesting a non-numeric field will return all of the values from the objects in the list. For example, to get all -the contributor names for the <code>express</code> package, you would run:</p> +the contributor email addresses for the <code>express</code> package, you would run:</p> <pre lang="bash"><code>npm view express contributors.email </code></pre> <p>You may also use numeric indices in square braces to specifically select @@ -207,6 +207,10 @@ this:</p> <li>Type: Boolean</li> </ul> <p>Whether or not to output JSON data, rather than the normal output.</p> +<ul> +<li>In <code>npm pkg set</code> it enables parsing set values with JSON.parse() before +saving them to your <code>package.json</code>.</li> +</ul> <p>Not supported by all npm commands.</p> <h4 id="workspace"><code>workspace</code></h4> <ul> diff --git a/deps/npm/docs/output/commands/npm.html b/deps/npm/docs/output/commands/npm.html index 28008c13c9e..e5e0b82ad35 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.19.1</p> +<p>7.20.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/folders.html b/deps/npm/docs/output/configuring-npm/folders.html index 6cdae3cd1ec..929bfe1f770 100644 --- a/deps/npm/docs/output/configuring-npm/folders.html +++ b/deps/npm/docs/output/configuring-npm/folders.html @@ -176,11 +176,13 @@ Global installs on Windows go to <code>{prefix}/node_modules</code> (that is, no <p>Scoped packages are installed the same way, except they are grouped together in a sub-folder of the relevant <code>node_modules</code> folder with the name of that scope prefix by the @ symbol, e.g. <code>npm install @myorg/package</code> would place -the package in <code>{prefix}/node_modules/@myorg/package</code>. See <a href="../using-npm/scope.html"><code>scope</code></a> for more details.</p> +the package in <code>{prefix}/node_modules/@myorg/package</code>. See +<a href="../using-npm/scope.html"><code>scope</code></a> for more details.</p> <p>If you wish to <code>require()</code> a package, then install it locally.</p> <h4 id="executables">Executables</h4> <p>When in global mode, executables are linked into <code>{prefix}/bin</code> on Unix, -or directly into <code>{prefix}</code> on Windows.</p> +or directly into <code>{prefix}</code> on Windows. Ensure that path is in your +terminal’s <code>PATH</code> environment to run them.</p> <p>When in local mode, executables are linked into <code>./node_modules/.bin</code> so that they can be made available to scripts run through npm. (For example, so that a test runner will be in the path diff --git a/deps/npm/docs/output/configuring-npm/package-json.html b/deps/npm/docs/output/configuring-npm/package-json.html index 30712bbe8d7..f7e5555b573 100644 --- a/deps/npm/docs/output/configuring-npm/package-json.html +++ b/deps/npm/docs/output/configuring-npm/package-json.html @@ -403,9 +403,12 @@ rely on primitives that aren’t available in Node.js modules. (e.g. install into the PATH. npm makes this pretty easy (in fact, it uses this feature to install the “npm” executable.)</p> <p>To use this, supply a <code>bin</code> field in your package.json which is a map of -command name to local file name. On install, npm will symlink that file -into <code>prefix/bin</code> for global installs, or <code>./node_modules/.bin/</code> for local -installs.</p> +command name to local file name. When this package is installed +globally, that file will be linked where global bins go so it is +available to run by name. When this package is installed as a +dependency in another package, the file will be linked where it will be +available to that package either directly by <code>npm exec</code> or by name in other +scripts when invoking them via <code>npm run-script</code>.</p> <p>For example, myapp could have this:</p> <pre lang="json"><code>{ "bin": { @@ -436,6 +439,8 @@ package, then you can just supply it as a string. For example:</p> <code>#!/usr/bin/env node</code>, otherwise the scripts are started without the node executable!</p> <p>Note that you can also set the executable files using <a href="#directoriesbin">directories.bin</a>.</p> +<p>See <a href="../configuring-npm/folders#executables.html">folders</a> for more info on +executables.</p> <h3 id="man">man</h3> <p>Specify either a single file or an array of filenames to put in place for the <code>man</code> program to find.</p> diff --git a/deps/npm/docs/output/using-npm/config.html b/deps/npm/docs/output/using-npm/config.html index 784b106e9a8..76a92f5dd1c 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="#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="#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="#pack-destination"><code>pack-destination</code></a></li><li><a href="#package"><code>package</code></a></li><li><a href="#package-lock"><code>package-lock</code></a></li><li><a href="#package-lock-only"><code>package-lock-only</code></a></li><li><a href="#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="#dev"><code>dev</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> +<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="#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="#location"><code>location</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="#pack-destination"><code>pack-destination</code></a></li><li><a href="#package"><code>package</code></a></li><li><a href="#package-lock"><code>package-lock</code></a></li><li><a href="#package-lock-only"><code>package-lock-only</code></a></li><li><a href="#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="#dev"><code>dev</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> @@ -194,6 +194,7 @@ internal to npm, and are defaults if nothing else is specified.</p> <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>-L</code>: <code>--location</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> @@ -284,9 +285,10 @@ to the same value as the current version.</p> <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> +<p>When “true” submit audit reports alongside the current npm command 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"><code>audit-level</code></h4> <ul> <li>Default: null</li> @@ -554,6 +556,7 @@ range (including SemVer-major changes).</li> <li>Allow unpublishing all versions of a published package.</li> <li>Allow conflicting peerDependencies to be installed in the root project.</li> <li>Implicitly set <code>--yes</code> during <code>npm init</code>.</li> +<li>Allow clobbering existing values in <code>npm pkg</code></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> @@ -726,6 +729,10 @@ number, if not already set in package.json.</p> <li>Type: Boolean</li> </ul> <p>Whether or not to output JSON data, rather than the normal output.</p> +<ul> +<li>In <code>npm pkg set</code> it enables parsing set values with JSON.parse() before +saving them to your <code>package.json</code>.</li> +</ul> <p>Not supported by all npm commands.</p> <h4 id="key"><code>key</code></h4> <ul> @@ -773,6 +780,13 @@ that collide, it provides a way to move forward resolving the situation.</p> </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="location"><code>location</code></h4> +<ul> +<li>Default: “user” unless <code>--global</code> is passed, which will also set this value +to “global”</li> +<li>Type: “global”, “user”, or “project”</li> +</ul> +<p>When passed to <code>npm config</code> this refers to which config file to use.</p> <h4 id="loglevel"><code>loglevel</code></h4> <ul> <li>Default: “notice”</li> diff --git a/deps/npm/docs/output/using-npm/scripts.html b/deps/npm/docs/output/using-npm/scripts.html index 320fcb248ce..9b1a2e322e3 100644 --- a/deps/npm/docs/output/using-npm/scripts.html +++ b/deps/npm/docs/output/using-npm/scripts.html @@ -198,7 +198,8 @@ the prepare script will be run, before the package is packaged and installed.</p> </li> <li> -<p>As of <code>npm@7</code> these scripts run in the background</p> +<p>As of <code>npm@7</code> these scripts run in the background. +To see the output, run with: <code>--foreground-scripts</code>.</p> </li> </ul> <p><strong>prepublish</strong> (DEPRECATED)</p> @@ -408,8 +409,8 @@ fine:</p> <p>Scripts are run by passing the line as a script argument to <code>sh</code>.</p> <p>If the script exits with a code other than 0, then this will abort the process.</p> -<p>Note that these script files don’t have to be nodejs or even -javascript programs. They just have to be some kind of executable +<p>Note that these script files don’t have to be Node.js or even +JavaScript programs. They just have to be some kind of executable file.</p> <h3 id="best-practices">Best Practices</h3> <ul> diff --git a/deps/npm/docs/output/using-npm/workspaces.html b/deps/npm/docs/output/using-npm/workspaces.html index 55bdb32ec46..f0a5945d611 100644 --- a/deps/npm/docs/output/using-npm/workspaces.html +++ b/deps/npm/docs/output/using-npm/workspaces.html @@ -169,7 +169,7 @@ file system that is explicitly defined in the <a href="../configuring-npm/packag </code></pre> <p>Given the above <code>package.json</code> example living at a current working directory <code>.</code> that contains a folder named <code>workspace-a</code> that itself contains -a <code>package.json</code> inside it, defining a nodejs package, e.g:</p> +a <code>package.json</code> inside it, defining a Node.js package, e.g:</p> <pre><code>. +-- package.json `-- workspace-a diff --git a/deps/npm/lib/base-command.js b/deps/npm/lib/base-command.js index 4077733a934..870c69acc49 100644 --- a/deps/npm/lib/base-command.js +++ b/deps/npm/lib/base-command.js @@ -75,7 +75,6 @@ class BaseCommand { } async setWorkspaces (filters) { - // TODO npm guards workspaces/global mode so we should use this.npm.prefix? const ws = await getWorkspaces(filters, { path: this.npm.localPrefix }) this.workspaces = ws this.workspaceNames = [...ws.keys()] diff --git a/deps/npm/lib/ci.js b/deps/npm/lib/ci.js index 3ff4b65badb..6634ffcdc19 100644 --- a/deps/npm/lib/ci.js +++ b/deps/npm/lib/ci.js @@ -33,6 +33,7 @@ class CI extends ArboristWorkspaceCmd { /* istanbul ignore next - see test/lib/load-all-commands.js */ static get params () { return [ + 'audit', 'ignore-scripts', 'script-shell', ] diff --git a/deps/npm/lib/config.js b/deps/npm/lib/config.js index d1585f414dc..a56dd92ffbd 100644 --- a/deps/npm/lib/config.js +++ b/deps/npm/lib/config.js @@ -56,6 +56,7 @@ class Config extends BaseCommand { 'json', 'global', 'editor', + 'location', 'long', ] } @@ -137,7 +138,7 @@ class Config extends BaseCommand { if (!args.length) throw this.usageError() - const where = this.npm.config.get('global') ? 'global' : 'user' + const where = this.npm.config.get('location') 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) @@ -167,16 +168,15 @@ class Config extends BaseCommand { if (!keys.length) throw this.usageError() - const where = this.npm.config.get('global') ? 'global' : 'user' + const where = this.npm.config.get('location') for (const key of keys) this.npm.config.delete(key, where) await this.npm.config.save(where) } async edit () { - const global = this.npm.config.get('global') const e = this.npm.config.get('editor') - const where = global ? 'global' : 'user' + const where = this.npm.config.get('location') const file = this.npm.config.data.get(where).source // save first, just to make sure it's synced up diff --git a/deps/npm/lib/install-ci-test.js b/deps/npm/lib/install-ci-test.js index 0d408178b33..871f24b2f32 100644 --- a/deps/npm/lib/install-ci-test.js +++ b/deps/npm/lib/install-ci-test.js @@ -13,14 +13,6 @@ class InstallCITest extends CI { return 'install-ci-test' } - /* istanbul ignore next - see test/lib/load-all-commands.js */ - static get params () { - return [ - 'ignore-scripts', - 'script-shell', - ] - } - exec (args, cb) { this.npm.commands.ci(args, (er) => { if (er) diff --git a/deps/npm/lib/ls.js b/deps/npm/lib/ls.js index 75406929119..91e9a9dd3db 100644 --- a/deps/npm/lib/ls.js +++ b/deps/npm/lib/ls.js @@ -138,7 +138,7 @@ class LS extends ArboristWorkspaceCmd { !(node instanceof Arborist.Node) || (currentDepth > depthToPrint) return (shouldSkipChildren) ? [] - : [...(node.target || node).edgesOut.values()] + : [...(node.target).edgesOut.values()] .filter(filterBySelectedWorkspaces) .filter(filterByEdgesTypes({ currentDepth, diff --git a/deps/npm/lib/npm.js b/deps/npm/lib/npm.js index 7046a84d0bc..db3559a384b 100644 --- a/deps/npm/lib/npm.js +++ b/deps/npm/lib/npm.js @@ -1,12 +1,7 @@ -// The order of the code in this file is relevant, because a lot of things -// require('npm.js'), but also we need to use some of those modules. So, -// we define and instantiate the singleton ahead of loading any modules -// required for its methods. - -// these are all dependencies used in the ctor const EventEmitter = require('events') const { resolve, dirname } = require('path') const Config = require('@npmcli/config') +const log = require('npmlog') // Patch the global fs module here at the app level require('graceful-fs').gracefulify(require('fs')) @@ -37,23 +32,51 @@ const proxyCmds = new Proxy({}, { }, }) +// Timers in progress +const timers = new Map() +// Finished timers +const timings = {} + +const processOnTimeHandler = (name) => { + timers.set(name, Date.now()) +} + +const processOnTimeEndHandler = (name) => { + if (timers.has(name)) { + const ms = Date.now() - timers.get(name) + log.timing(name, `Completed in ${ms}ms`) + timings[name] = ms + timers.delete(name) + } else + log.silly('timing', "Tried to end timer that doesn't exist:", name) +} + const { definitions, flatten, shorthands } = require('./utils/config/index.js') const { shellouts } = require('./utils/cmd-list.js') const usage = require('./utils/npm-usage.js') +const which = require('which') + +const deref = require('./utils/deref-command.js') +const setupLog = require('./utils/setup-log.js') +const cleanUpLogFiles = require('./utils/cleanup-log-files.js') +const getProjectScope = require('./utils/get-project-scope.js') + let warnedNonDashArg = false const _runCmd = Symbol('_runCmd') const _load = Symbol('_load') const _tmpFolder = Symbol('_tmpFolder') const _title = Symbol('_title') + const npm = module.exports = new class extends EventEmitter { constructor () { super() - // TODO make this only ever load once (or unload) in tests - require('./utils/perf.js') this.started = Date.now() this.command = null this.commands = proxyCmds + this.timings = timings + this.timers = timers + this.perfStart() procLogListener() process.emit('time', 'npm') this.version = require('../package.json').version @@ -67,6 +90,16 @@ const npm = module.exports = new class extends EventEmitter { this.updateNotification = null } + perfStart () { + process.on('time', processOnTimeHandler) + process.on('timeEnd', processOnTimeEndHandler) + } + + perfStop () { + process.off('time', processOnTimeHandler) + process.off('timeEnd', processOnTimeEndHandler) + } + get shelloutCommands () { return shellouts } @@ -317,16 +350,5 @@ const npm = module.exports = new class extends EventEmitter { } }() -// now load everything required by the class methods - -const log = require('npmlog') - -const which = require('which') - -const deref = require('./utils/deref-command.js') -const setupLog = require('./utils/setup-log.js') -const cleanUpLogFiles = require('./utils/cleanup-log-files.js') -const getProjectScope = require('./utils/get-project-scope.js') - if (require.main === module) require('./cli.js')(process) diff --git a/deps/npm/lib/outdated.js b/deps/npm/lib/outdated.js index 9d60d143d71..01e268fe96a 100644 --- a/deps/npm/lib/outdated.js +++ b/deps/npm/lib/outdated.js @@ -158,7 +158,7 @@ class Outdated extends ArboristWorkspaceCmd { edge.from && this.filterSet && this.filterSet.size > 0 - && !this.filterSet.has(edge.from.target || edge.from) + && !this.filterSet.has(edge.from.target) if (filteredOut) return diff --git a/deps/npm/lib/pkg.js b/deps/npm/lib/pkg.js new file mode 100644 index 00000000000..9ba92c930e1 --- /dev/null +++ b/deps/npm/lib/pkg.js @@ -0,0 +1,152 @@ +const PackageJson = require('@npmcli/package-json') +const BaseCommand = require('./base-command.js') +const Queryable = require('./utils/queryable.js') + +class Pkg extends BaseCommand { + static get description () { + return 'Manages your package.json' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get name () { + return 'pkg' + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get usage () { + return [ + 'set <key>=<value> [<key>=<value> ...]', + 'get [<key> [<key> ...]]', + 'delete <key> [<key> ...]', + ] + } + + /* istanbul ignore next - see test/lib/load-all-commands.js */ + static get params () { + return [ + 'force', + 'json', + 'workspace', + 'workspaces', + ] + } + + exec (args, cb) { + this.prefix = this.npm.localPrefix + this.pkg(args).then(() => cb()).catch(cb) + } + + execWorkspaces (args, filters, cb) { + this.pkgWorkspaces(args, filters).then(() => cb()).catch(cb) + } + + async pkg (args) { + if (this.npm.config.get('global')) { + throw Object.assign( + new Error(`There's no package.json file to manage on global mode`), + { code: 'EPKGGLOBAL' } + ) + } + + const [cmd, ..._args] = args + switch (cmd) { + case 'get': + return this.get(_args) + case 'set': + return this.set(_args) + case 'delete': + return this.delete(_args) + default: + throw this.usageError() + } + } + + async pkgWorkspaces (args, filters) { + await this.setWorkspaces(filters) + const result = {} + for (const [workspaceName, workspacePath] of this.workspaces.entries()) { + this.prefix = workspacePath + result[workspaceName] = await this.pkg(args) + } + // when running in workspaces names, make sure to key by workspace + // name the results of each value retrieved in each ws + this.npm.output(JSON.stringify(result, null, 2)) + } + + async get (args) { + const pkgJson = await PackageJson.load(this.prefix) + + const { content } = pkgJson + let result = !args.length && content + + if (!result) { + const q = new Queryable(content) + result = q.query(args) + + // in case there's only a single result from the query + // just prints that one element to stdout + if (Object.keys(result).length === 1) + result = result[args] + } + + // only outputs if not running with workspaces config, + // in case you're retrieving info for workspaces the pkgWorkspaces + // will handle the output to make sure it get keyed by ws name + if (!this.workspaces) + this.npm.output(JSON.stringify(result, null, 2)) + + return result + } + + async set (args) { + const setError = () => + Object.assign( + new TypeError('npm pkg set expects a key=value pair of args.'), + { code: 'EPKGSET' } + ) + + if (!args.length) + throw setError() + + const force = this.npm.config.get('force') + const json = this.npm.config.get('json') + const pkgJson = await PackageJson.load(this.prefix) + const q = new Queryable(pkgJson.content) + for (const arg of args) { + const [key, ...rest] = arg.split('=') + const value = rest.join('=') + if (!key || !value) + throw setError() + + q.set(key, json ? JSON.parse(value) : value, { force }) + } + + pkgJson.update(q.toJSON()) + await pkgJson.save() + } + + async delete (args) { + const setError = () => + Object.assign( + new TypeError('npm pkg delete expects key args.'), + { code: 'EPKGDELETE' } + ) + + if (!args.length) + throw setError() + + const pkgJson = await PackageJson.load(this.prefix) + const q = new Queryable(pkgJson.content) + for (const key of args) { + if (!key) + throw setError() + + q.delete(key) + } + + pkgJson.update(q.toJSON()) + await pkgJson.save() + } +} + +module.exports = Pkg diff --git a/deps/npm/lib/publish.js b/deps/npm/lib/publish.js index f35388a30f4..9c747eb5068 100644 --- a/deps/npm/lib/publish.js +++ b/deps/npm/lib/publish.js @@ -66,6 +66,7 @@ class Publish extends BaseCommand { const dryRun = this.npm.config.get('dry-run') const json = this.npm.config.get('json') const defaultTag = this.npm.config.get('tag') + const ignoreScripts = this.npm.config.get('ignore-scripts') const silent = log.level === 'silent' if (semver.validRange(defaultTag)) @@ -82,7 +83,7 @@ class Publish extends BaseCommand { flatten(manifest.publishConfig, opts) // only run scripts for directory type publishes - if (spec.type === 'directory') { + if (spec.type === 'directory' && !ignoreScripts) { await runScript({ event: 'prepublishOnly', path: spec.fetchSpec, @@ -119,7 +120,7 @@ class Publish extends BaseCommand { await otplease(opts, opts => libpub(manifest, tarballData, opts)) } - if (spec.type === 'directory') { + if (spec.type === 'directory' && !ignoreScripts) { await runScript({ event: 'publish', path: spec.fetchSpec, diff --git a/deps/npm/lib/utils/cmd-list.js b/deps/npm/lib/utils/cmd-list.js index c865cdabb40..26da5390065 100644 --- a/deps/npm/lib/utils/cmd-list.js +++ b/deps/npm/lib/utils/cmd-list.js @@ -122,6 +122,7 @@ const cmdList = [ 'diff', 'dist-tag', 'ping', + 'pkg', 'test', 'stop', diff --git a/deps/npm/lib/utils/config/definition.js b/deps/npm/lib/utils/config/definition.js index 507be6a6440..1354851326a 100644 --- a/deps/npm/lib/utils/config/definition.js +++ b/deps/npm/lib/utils/config/definition.js @@ -91,13 +91,27 @@ ${noEnvExport}`) } const describeUsage = (def) => { - let key = `--${def.key}` - if (def.short && typeof def.short === 'string') - key = `-${def.short}|${key}` + let key = '' // Single type - if (!Array.isArray(def.type)) - return `${key}${def.type === Boolean ? '' : ' ' + def.hint}` + if (!Array.isArray(def.type)) { + if (def.short) + key = `-${def.short}|` + + if (def.type === Boolean && def.default !== false) + key = `${key}--no-${def.key}` + else + key = `${key}--${def.key}` + + if (def.type !== Boolean) + key = `${key} ${def.hint}` + + return key + } + + key = `--${def.key}` + if (def.short) + key = `-${def.short}|--${def.key}` // Multiple types let types = def.type @@ -120,8 +134,12 @@ const describeUsage = (def) => { description = def.hint } - if (bool) - key = `${key}|${key}` + if (bool) { + // Currently none of our multi-type configs with boolean values default to + // false so all their hints should show `--no-`, if we ever add ones that + // default to false we can branch the logic here + key = `--no-${def.key}|${key}` + } const usage = `${key} ${description}` if (multiple) diff --git a/deps/npm/lib/utils/config/definitions.js b/deps/npm/lib/utils/config/definitions.js index d540b0fc67e..abe6bda70d8 100644 --- a/deps/npm/lib/utils/config/definitions.js +++ b/deps/npm/lib/utils/config/definitions.js @@ -203,10 +203,10 @@ define('audit', { default: true, type: Boolean, description: ` - When "true" submit audit reports alongside \`npm install\` runs to the + When "true" submit audit reports alongside the current npm command 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. + documentation for [\`npm audit\`](/commands/npm-audit) for details on what + is submitted. `, flatten, }) @@ -440,6 +440,7 @@ define('cidr', { define('color', { default: !process.env.NO_COLOR || process.env.NO_COLOR === '0', + usage: '--color|--no-color|--color always', defaultDescription: ` true unless the NO_COLOR environ is set to something other than '0' `, @@ -715,6 +716,7 @@ define('force', { * Allow unpublishing all versions of a published package. * Allow conflicting peerDependencies to be installed in the root project. * Implicitly set \`--yes\` during \`npm init\`. + * Allow clobbering existing values in \`npm pkg\` 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! @@ -1029,6 +1031,9 @@ define('json', { description: ` Whether or not to output JSON data, rather than the normal output. + * In \`npm pkg set\` it enables parsing set values with JSON.parse() + before saving them to your \`package.json\`. + Not supported by all npm commands. `, flatten, @@ -1103,6 +1108,31 @@ define('local-address', { flatten, }) +define('location', { + default: 'user', + short: 'L', + type: [ + 'global', + 'user', + 'project', + ], + defaultDescription: ` + "user" unless \`--global\` is passed, which will also set this value to "global" + `, + description: ` + When passed to \`npm config\` this refers to which config file to use. + `, + // NOTE: the flattener here deliberately does not alter the value of global + // for now, this is to avoid inadvertently causing any breakage. the value of + // global, however, does modify this flag. + flatten (key, obj, flatOptions) { + // if global is set, we override ourselves + if (obj.global) + obj.location = 'global' + flatOptions.location = obj.location + }, +}) + define('loglevel', { default: 'notice', type: [ @@ -1200,7 +1230,10 @@ define('noproxy', { Also accepts a comma-delimited string. `, flatten (key, obj, flatOptions) { - flatOptions.noProxy = obj[key].join(',') + if (Array.isArray(obj[key])) + flatOptions.noProxy = obj[key].join(',') + else + flatOptions.noProxy = obj[key] }, }) diff --git a/deps/npm/lib/utils/error-message.js b/deps/npm/lib/utils/error-message.js index 125cdf8c535..3b590f712e7 100644 --- a/deps/npm/lib/utils/error-message.js +++ b/deps/npm/lib/utils/error-message.js @@ -269,6 +269,7 @@ module.exports = (er, npm) => { case 'ECONNRESET': case 'ENOTFOUND': case 'ETIMEDOUT': + case 'ERR_SOCKET_TIMEOUT': case 'EAI_FAIL': short.push(['network', er.message]) detail.push([ diff --git a/deps/npm/lib/utils/exit-handler.js b/deps/npm/lib/utils/exit-handler.js index 931527704b9..95c9655a716 100644 --- a/deps/npm/lib/utils/exit-handler.js +++ b/deps/npm/lib/utils/exit-handler.js @@ -1,4 +1,3 @@ -const log = require('npmlog') const os = require('os') const path = require('path') const writeFileAtomic = require('write-file-atomic') @@ -13,8 +12,6 @@ let logFileName let npm // set by the cli let wroteLogFile = false -const timings = {} - const getLogFile = () => { // we call this multiple times, so we need to treat it as a singleton because // the date is part of the name @@ -24,17 +21,15 @@ const getLogFile = () => { return logFileName } -process.on('timing', (name, value) => { - if (timings[name]) - timings[name] += value - else - timings[name] = value -}) - process.on('exit', code => { + // process.emit is synchronous, so the timeEnd handler will run before the + // unfinished timer check below process.emit('timeEnd', 'npm') - log.disableProgress() - if (npm.config && npm.config.loaded && npm.config.get('timing')) { + npm.log.disableProgress() + for (const [name, timers] of npm.timers) + npm.log.verbose('unfinished npm timer', name, timers) + + if (npm.config.loaded && npm.config.get('timing')) { try { const file = path.resolve(npm.config.get('cache'), '_timing.json') const dir = path.dirname(npm.config.get('cache')) @@ -44,7 +39,7 @@ process.on('exit', code => { command: process.argv.slice(2), logfile: getLogFile(), version: npm.version, - ...timings, + ...npm.timings, }) + '\n') const st = fs.lstatSync(path.dirname(npm.config.get('cache'))) @@ -56,27 +51,27 @@ process.on('exit', code => { } if (!code) - log.info('ok') + npm.log.info('ok') else { - log.verbose('code', code) + npm.log.verbose('code', code) if (!exitHandlerCalled) { - log.error('', 'Exit handler never called!') + npm.log.error('', 'Exit handler never called!') console.error('') - log.error('', 'This is an error with npm itself. Please report this error at:') - log.error('', ' <https://github.com/npm/cli/issues>') + npm.log.error('', 'This is an error with npm itself. Please report this error at:') + npm.log.error('', ' <https://github.com/npm/cli/issues>') // TODO this doesn't have an npm.config.loaded guard writeLogFile() } } // In timing mode we always write the log file - if (npm.config && npm.config.loaded && npm.config.get('timing') && !wroteLogFile) + if (npm.config.loaded && npm.config.get('timing') && !wroteLogFile) writeLogFile() if (wroteLogFile) { // just a line break - if (log.levels[log.level] <= log.levels.error) + if (npm.log.levels[npm.log.level] <= npm.log.levels.error) console.error('') - log.error( + npm.log.error( '', [ 'A complete log of this run can be found in:', @@ -88,121 +83,114 @@ process.on('exit', code => { // these are needed for the tests to have a clean slate in each test case exitHandlerCalled = false wroteLogFile = false - - // actually exit. - process.exit(code) }) -const exit = (code, noLog) => { - log.verbose('exit', code || 0) - if (log.level === 'silent') - noLog = true - - // noLog is true if there was an error, including if config wasn't loaded, so - // this doesn't need a config.loaded guard - if (code && !noLog) - writeLogFile() - - // Exit directly -- nothing in the CLI should still be running in the - // background at this point, and this makes sure anything left dangling - // for whatever reason gets thrown away, instead of leaving the CLI open - process.stdout.write('', () => { - process.exit(code) - }) -} - const exitHandler = (err) => { - log.disableProgress() - if (!npm.config || !npm.config.loaded) { - // logging won't work unless we pretend that it's ready + npm.log.disableProgress() + if (!npm.config.loaded) { err = err || new Error('Exit prior to config file resolving.') console.error(err.stack || err.message) } - if (exitHandlerCalled) - err = err || new Error('Exit handler called more than once.') - - // only show the notification if it finished before the other stuff we - // were doing. no need to hang on `npm -v` or something. + // only show the notification if it finished. if (typeof npm.updateNotification === 'string') { - const { level } = log - log.level = log.levels.notice - log.notice('', npm.updateNotification) - log.level = level + const { level } = npm.log + npm.log.level = 'notice' + npm.log.notice('', npm.updateNotification) + npm.log.level = level } exitHandlerCalled = true - if (!err) - return exit() - - // if we got a command that just shells out to something else, then it - // will presumably print its own errors and exit with a proper status - // code if there's a problem. If we got an error with a code=0, then... - // something else went wrong along the way, so maybe an npm problem? - const isShellout = npm.shelloutCommands.includes(npm.command) - const quietShellout = isShellout && typeof err.code === 'number' && err.code - if (quietShellout) - return exit(err.code, true) - else if (typeof err === 'string') { - log.error('', err) - return exit(1, true) - } else if (!(err instanceof Error)) { - log.error('weird error', err) - return exit(1, true) - } - - if (!err.code) { - const matchErrorCode = err.message.match(/^(?:Error: )?(E[A-Z]+)/) - err.code = matchErrorCode && matchErrorCode[1] - } - for (const k of ['type', 'stack', 'statusCode', 'pkgid']) { - const v = err[k] - if (v) - log.verbose(k, replaceInfo(v)) + let exitCode + let noLog + + if (err) { + exitCode = 1 + // if we got a command that just shells out to something else, then it + // will presumably print its own errors and exit with a proper status + // code if there's a problem. If we got an error with a code=0, then... + // something else went wrong along the way, so maybe an npm problem? + const isShellout = npm.shelloutCommands.includes(npm.command) + const quietShellout = isShellout && typeof err.code === 'number' && err.code + if (quietShellout) { + exitCode = err.code + noLog = true + } else if (typeof err === 'string') { + noLog = true + npm.log.error('', err) + } else if (!(err instanceof Error)) { + noLog = true + npm.log.error('weird error', err) + } else { + if (!err.code) { + const matchErrorCode = err.message.match(/^(?:Error: )?(E[A-Z]+)/) + err.code = matchErrorCode && matchErrorCode[1] + } + + for (const k of ['type', 'stack', 'statusCode', 'pkgid']) { + const v = err[k] + if (v) + npm.log.verbose(k, replaceInfo(v)) + } + + npm.log.verbose('cwd', process.cwd()) + + const args = replaceInfo(process.argv) + npm.log.verbose('', os.type() + ' ' + os.release()) + npm.log.verbose('argv', args.map(JSON.stringify).join(' ')) + npm.log.verbose('node', process.version) + npm.log.verbose('npm ', 'v' + npm.version) + + for (const k of ['code', 'syscall', 'file', 'path', 'dest', 'errno']) { + const v = err[k] + if (v) + npm.log.error(k, v) + } + + const msg = errorMessage(err, npm) + for (const errline of [...msg.summary, ...msg.detail]) + npm.log.error(...errline) + + if (npm.config.loaded && npm.config.get('json')) { + const error = { + error: { + code: err.code, + summary: messageText(msg.summary), + detail: messageText(msg.detail), + }, + } + console.error(JSON.stringify(error, null, 2)) + } + + if (typeof err.errno === 'number') + exitCode = err.errno + else if (typeof err.code === 'number') + exitCode = err.code + } } + npm.log.verbose('exit', exitCode || 0) - log.verbose('cwd', process.cwd()) - - const args = replaceInfo(process.argv) - log.verbose('', os.type() + ' ' + os.release()) - log.verbose('argv', args.map(JSON.stringify).join(' ')) - log.verbose('node', process.version) - log.verbose('npm ', 'v' + npm.version) - - for (const k of ['code', 'syscall', 'file', 'path', 'dest', 'errno']) { - const v = err[k] - if (v) - log.error(k, v) - } + if (npm.log.level === 'silent') + noLog = true - const msg = errorMessage(err, npm) - for (const errline of [...msg.summary, ...msg.detail]) - log.error(...errline) - - if (npm.config && npm.config.get('json')) { - const error = { - error: { - code: err.code, - summary: messageText(msg.summary), - detail: messageText(msg.detail), - }, - } - console.error(JSON.stringify(error, null, 2)) - } + // noLog is true if there was an error, including if config wasn't loaded, so + // this doesn't need a config.loaded guard + if (exitCode && !noLog) + writeLogFile() - exit(typeof err.errno === 'number' ? err.errno : typeof err.code === 'number' ? err.code : 1) + // explicitly call process.exit now so we don't hang on things like the + // update notifier, also flush stdout beforehand because process.exit doesn't + // wait for that to happen. + process.stdout.write('', () => process.exit(exitCode)) } const messageText = msg => msg.map(line => line.slice(1).join(' ')).join('\n') const writeLogFile = () => { - if (wroteLogFile) - return - try { let logOutput = '' - log.record.forEach(m => { + npm.log.record.forEach(m => { const p = [m.id, m.level] if (m.prefix) p.push(m.prefix) @@ -225,7 +213,7 @@ const writeLogFile = () => { fs.chownSync(file, st.uid, st.gid) // truncate once it's been written. - log.record.length = 0 + npm.log.record.length = 0 wroteLogFile = true } catch (ex) { diff --git a/deps/npm/lib/utils/perf.js b/deps/npm/lib/utils/perf.js deleted file mode 100644 index 4961054d909..00000000000 --- a/deps/npm/lib/utils/perf.js +++ /dev/null @@ -1,23 +0,0 @@ -const log = require('npmlog') -const timings = new Map() - -process.on('time', (name) => { - timings.set(name, Date.now()) -}) - -process.on('timeEnd', (name) => { - if (timings.has(name)) { - const ms = Date.now() - timings.get(name) - process.emit('timing', name, ms) - log.timing(name, `Completed in ${ms}ms`) - timings.delete(name) - } else - log.silly('timing', "Tried to end timer that doesn't exist:", name) -}) - -// for tests -/* istanbul ignore next */ -exports.reset = () => { - process.removeAllListeners('time') - process.removeAllListeners('timeEnd') -} diff --git a/deps/npm/lib/utils/queryable.js b/deps/npm/lib/utils/queryable.js new file mode 100644 index 00000000000..e10eba3b5f0 --- /dev/null +++ b/deps/npm/lib/utils/queryable.js @@ -0,0 +1,314 @@ +const util = require('util') +const _data = Symbol('data') +const _delete = Symbol('delete') +const _append = Symbol('append') + +const sqBracketsMatcher = str => str.match(/(.+)\[([^\]]+)\]\.?(.*)$/) + +// replaces any occurence of an empty-brackets (e.g: []) with a special +// Symbol(append) to represent it, this is going to be useful for the setter +// method that will push values to the end of the array when finding these +const replaceAppendSymbols = str => { + const matchEmptyBracket = str.match(/^(.*)\[\]\.?(.*)$/) + + if (matchEmptyBracket) { + const [, pre, post] = matchEmptyBracket + return [...replaceAppendSymbols(pre), _append, post].filter(Boolean) + } + + return [str] +} + +const parseKeys = (key) => { + const sqBracketItems = new Set() + sqBracketItems.add(_append) + const parseSqBrackets = (str) => { + const index = sqBracketsMatcher(str) + + // once we find square brackets, we recursively parse all these + if (index) { + const preSqBracketPortion = index[1] + + // we want to have a `new String` wrapper here in order to differentiate + // between multiple occurences of the same string, e.g: + // foo.bar[foo.bar] should split into { foo: { bar: { 'foo.bar': {} } } + /* eslint-disable-next-line no-new-wrappers */ + const foundKey = new String(index[2]) + const postSqBracketPortion = index[3] + + // we keep track of items found during this step to make sure + // we don't try to split-separate keys that were defined within + // square brackets, since the key name itself might contain dots + sqBracketItems.add(foundKey) + + // returns an array that contains either dot-separate items (that will + // be splitted appart during the next step OR the fully parsed keys + // read from square brackets, e.g: + // foo.bar[1.0.0].a.b -> ['foo.bar', '1.0.0', 'a.b'] + return [ + ...parseSqBrackets(preSqBracketPortion), + foundKey, + ...( + postSqBracketPortion + ? parseSqBrackets(postSqBracketPortion) + : [] + ), + ] + } + + // at the end of parsing, any usage of the special empty-bracket syntax + // (e.g: foo.array[]) has not yet been parsed, here we'll take care + // of parsing it and adding a special symbol to represent it in + // the resulting list of keys + return replaceAppendSymbols(str) + } + + const res = [] + // starts by parsing items defined as square brackets, those might be + // representing properties that have a dot in the name or just array + // indexes, e.g: foo[1.0.0] or list[0] + const sqBracketKeys = parseSqBrackets(key.trim()) + + for (const k of sqBracketKeys) { + // keys parsed from square brackets should just be added to list of + // resulting keys as they might have dots as part of the key + if (sqBracketItems.has(k)) + res.push(k) + else { + // splits the dot-sep property names and add them to the list of keys + for (const splitKey of k.split('.')) + /* eslint-disable-next-line no-new-wrappers */ + res.push(new String(splitKey)) + } + } + + // returns an ordered list of strings in which each entry + // represents a key in an object defined by the previous entry + return res +} + +const getter = ({ data, key }) => { + // keys are a list in which each entry represents the name of + // a property that should be walked through the object in order to + // return the final found value + const keys = parseKeys(key) + let _data = data + let label = '' + + for (const k of keys) { + // empty-bracket-shortcut-syntax is not supported on getter + if (k === _append) { + throw Object.assign( + new Error('Empty brackets are not valid syntax for retrieving values.'), + { code: 'EINVALIDSYNTAX' } + ) + } + + // extra logic to take into account printing array, along with its + // special syntax in which using a dot-sep property name after an + // arry will expand it's results, e.g: + // arr.name -> arr[0].name=value, arr[1].name=value, ... + const maybeIndex = Number(k) + if (Array.isArray(_data) && !Number.isInteger(maybeIndex)) { + _data = _data.reduce((acc, i, index) => { + acc[`${label}[${index}].${k}`] = i[k] + return acc + }, {}) + return _data + } else { + // if can't find any more values, it means it's just over + // and there's nothing to return + if (!_data[k]) + return undefined + + // otherwise sets the next value + _data = _data[k] + } + + label += k + } + + // these are some legacy expectations from + // the old API consumed by lib/view.js + if (Array.isArray(_data) && _data.length <= 1) + _data = _data[0] + + return { + [key]: _data, + } +} + +const setter = ({ data, key, value, force }) => { + // setter goes to recursively transform the provided data obj, + // setting properties from the list of parsed keys, e.g: + // ['foo', 'bar', 'baz'] -> { foo: { bar: { baz: {} } } + const keys = parseKeys(key) + const setKeys = (_data, _key) => { + // handles array indexes, converting valid integers to numbers, + // note that occurences of Symbol(append) will throw, + // so we just ignore these for now + let maybeIndex = Number.NaN + try { + maybeIndex = Number(_key) + } catch (err) {} + if (!Number.isNaN(maybeIndex)) + _key = maybeIndex + + // creates new array in case key is an index + // and the array obj is not yet defined + const keyIsAnArrayIndex = _key === maybeIndex || _key === _append + const dataHasNoItems = !Object.keys(_data).length + if (keyIsAnArrayIndex && dataHasNoItems && !Array.isArray(_data)) + _data = [] + + // converting from array to an object is also possible, in case the + // user is using force mode, we should also convert existing arrays + // to an empty object if the current _data is an array + if (force && Array.isArray(_data) && !keyIsAnArrayIndex) + _data = { ..._data } + + // the _append key is a special key that is used to represent + // the empty-bracket notation, e.g: arr[] -> arr[arr.length] + if (_key === _append) { + if (!Array.isArray(_data)) { + throw Object.assign( + new Error(`Can't use append syntax in non-Array element`), + { code: 'ENOAPPEND' } + ) + } + _key = _data.length + } + + // retrieves the next data object to recursively iterate on, + // throws if trying to override a literal value or add props to an array + const next = () => { + const haveContents = + !force && + _data[_key] != null && + value !== _delete + const shouldNotOverrideLiteralValue = + !(typeof _data[_key] === 'object') + // if the next obj to recurse is an array and the next key to be + // appended to the resulting obj is not an array index, then it + // should throw since we can't append arbitrary props to arrays + const shouldNotAddPropsToArrays = + typeof keys[0] !== 'symbol' && + Array.isArray(_data[_key]) && + Number.isNaN(Number(keys[0])) + + const overrideError = + haveContents && + shouldNotOverrideLiteralValue + if (overrideError) { + throw Object.assign( + new Error(`Property ${_key} already exists and is not an Array or Object.`), + { code: 'EOVERRIDEVALUE' } + ) + } + + const addPropsToArrayError = + haveContents && + shouldNotAddPropsToArrays + if (addPropsToArrayError) { + throw Object.assign( + new Error(`Can't add property ${key} to an Array.`), + { code: 'ENOADDPROP' } + ) + } + + return typeof _data[_key] === 'object' ? _data[_key] || {} : {} + } + + // sets items from the parsed array of keys as objects, recurses to + // setKeys in case there are still items to be handled, otherwise it + // just sets the original value set by the user + if (keys.length) + _data[_key] = setKeys(next(), keys.shift()) + else { + // handles special deletion cases for obj props / array items + if (value === _delete) { + if (Array.isArray(_data)) + _data.splice(_key, 1) + else + delete _data[_key] + } else + // finally, sets the value in its right place + _data[_key] = value + } + + return _data + } + + setKeys(data, keys.shift()) +} + +class Queryable { + constructor (obj) { + if (!obj || typeof obj !== 'object') { + throw Object.assign( + new Error('Queryable needs an object to query properties from.'), + { code: 'ENOQUERYABLEOBJ' } + ) + } + + this[_data] = obj + } + + query (queries) { + // this ugly interface here is meant to be a compatibility layer + // with the legacy API lib/view.js is consuming, if at some point + // we refactor that command then we can revisit making this nicer + if (queries === '') + return { '': this[_data] } + + const q = query => getter({ + data: this[_data], + key: query, + }) + + if (Array.isArray(queries)) { + let res = {} + for (const query of queries) + res = { ...res, ...q(query) } + return res + } else + return q(queries) + } + + // return the value for a single query if found, otherwise returns undefined + get (query) { + const obj = this.query(query) + if (obj) + return obj[query] + } + + // creates objects along the way for the provided `query` parameter + // and assigns `value` to the last property of the query chain + set (query, value, { force } = {}) { + setter({ + data: this[_data], + key: query, + value, + force, + }) + } + + // deletes the value of the property found at `query` + delete (query) { + setter({ + data: this[_data], + key: query, + value: _delete, + }) + } + + toJSON () { + return this[_data] + } + + [util.inspect.custom] () { + return this.toJSON() + } +} + +module.exports = Queryable diff --git a/deps/npm/lib/utils/update-notifier.js b/deps/npm/lib/utils/update-notifier.js index ed5806ced2a..14c4fac0d58 100644 --- a/deps/npm/lib/utils/update-notifier.js +++ b/deps/npm/lib/utils/update-notifier.js @@ -33,12 +33,6 @@ const checkTimeout = async (npm, duration) => { return t > st.mtime } -const updateTimeout = async npm => { - // best effort, if this fails, it's ok. - // might be using /dev/null as the cache or something weird like that. - await writeFile(lastCheckedFile(npm), '').catch(() => {}) -} - const updateNotifier = async (npm, spec = 'latest') => { // never check for updates in CI, when updating npm already, or opted out if (!npm.config.get('update-notifier') || @@ -111,15 +105,16 @@ const updateNotifier = async (npm, spec = 'latest') => { `${oldc} -> ${latestc}\n` + `Changelog: ${changelogc}\n` + `Run ${cmdc} to update!\n` - const messagec = !useColor ? message : chalk.bgBlack.white(message) - return messagec + return message } // only update the notification timeout if we actually finished checking module.exports = async npm => { const notification = await updateNotifier(npm) - // intentional. do not await this. it's a best-effort update. - updateTimeout(npm) + // intentional. do not await this. it's a best-effort update. if this + // fails, it's ok. might be using /dev/null as the cache or something weird + // like that. + writeFile(lastCheckedFile(npm), '').catch(() => {}) npm.updateNotification = notification } diff --git a/deps/npm/lib/view.js b/deps/npm/lib/view.js index 788df3ed0b4..47e631f5565 100644 --- a/deps/npm/lib/view.js +++ b/deps/npm/lib/view.js @@ -17,6 +17,7 @@ const { packument } = require('pacote') const readFile = promisify(fs.readFile) const readJson = async file => jsonParse(await readFile(file, 'utf8')) +const Queryable = require('./utils/queryable.js') const BaseCommand = require('./base-command.js') class View extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ @@ -459,56 +460,13 @@ function showFields (data, version, fields) { o[k] = s[k] }) }) - return search(o, fields.split('.'), version.version, fields) -} -function search (data, fields, version, title) { - let field - const tail = fields - while (!field && fields.length) - field = tail.shift() - fields = [field].concat(tail) - let o - if (!field && !tail.length) { - o = {} - o[version] = {} - o[version][title] = data - return o - } - let index = field.match(/(.+)\[([^\]]+)\]$/) - if (index) { - field = index[1] - index = index[2] - if (data[field] && data[field][index]) - return search(data[field][index], tail, version, title) - else - field = field + '[' + index + ']' - } - if (Array.isArray(data)) { - if (data.length === 1) - return search(data[0], fields, version, title) - - let results = [] - data.forEach((data, i) => { - const tl = title.length - const newt = title.substr(0, tl - fields.join('.').length - 1) + - '[' + i + ']' + [''].concat(fields).join('.') - results.push(search(data, fields.slice(), version, newt)) - }) - results = results.reduce(reducer, {}) - return results - } - if (!data[field]) - return undefined - data = data[field] - if (tail.length) { - // there are more fields to deal with. - return search(data, tail, version, title) - } - o = {} - o[version] = {} - o[version][title] = data - return o + const queryable = new Queryable(o) + const s = queryable.query(fields) + const res = { [version.version]: s } + + if (s) + return res } function cleanup (data) { diff --git a/deps/npm/man/man1/npm-audit.1 b/deps/npm/man/man1/npm-audit.1 index ba569a749e9..b1638993cf8 100644 --- a/deps/npm/man/man1/npm-audit.1 +++ b/deps/npm/man/man1/npm-audit.1 @@ -263,6 +263,8 @@ Allow unpublishing all versions of a published package\. Allow conflicting peerDependencies to be installed in the root project\. .IP \(bu 2 Implicitly set \fB\-\-yes\fP during \fBnpm init\fP\|\. +.IP \(bu 2 +Allow clobbering existing values in \fBnpm pkg\fP .RE .P @@ -278,6 +280,12 @@ Type: Boolean .RE .P Whether or not to output JSON data, rather than the normal output\. +.RS 0 +.IP \(bu 2 +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before +saving them to your \fBpackage\.json\fP\|\. + +.RE .P Not supported by all npm commands\. .SS \fBpackage\-lock\-only\fP diff --git a/deps/npm/man/man1/npm-ci.1 b/deps/npm/man/man1/npm-ci.1 index 0d11f277eea..f4ad77607e7 100644 --- a/deps/npm/man/man1/npm-ci.1 +++ b/deps/npm/man/man1/npm-ci.1 @@ -81,6 +81,19 @@ cache: .SS Configuration <!\-\- AUTOGENERATED CONFIG DESCRIPTIONS START \-\-> <!\-\- automatically generated, do not edit manually \-\-> +.SS \fBaudit\fP +.RS 0 +.IP \(bu 2 +Default: true +.IP \(bu 2 +Type: Boolean + +.RE +.P +When "true" submit audit reports alongside the current npm command 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 \fBignore\-scripts\fP .RS 0 .IP \(bu 2 diff --git a/deps/npm/man/man1/npm-config.1 b/deps/npm/man/man1/npm-config.1 index 70a2d136495..405160025f1 100644 --- a/deps/npm/man/man1/npm-config.1 +++ b/deps/npm/man/man1/npm-config.1 @@ -107,6 +107,12 @@ Type: Boolean .RE .P Whether or not to output JSON data, rather than the normal output\. +.RS 0 +.IP \(bu 2 +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before +saving them to your \fBpackage\.json\fP\|\. + +.RE .P Not supported by all npm commands\. .SS \fBglobal\fP @@ -142,6 +148,17 @@ Type: String .RE .P The command to run for \fBnpm edit\fP and \fBnpm config edit\fP\|\. +.SS \fBlocation\fP +.RS 0 +.IP \(bu 2 +Default: "user" unless \fB\-\-global\fP is passed, which will also set this value +to "global" +.IP \(bu 2 +Type: "global", "user", or "project" + +.RE +.P +When passed to \fBnpm config\fP this refers to which config file to use\. .SS \fBlong\fP .RS 0 .IP \(bu 2 diff --git a/deps/npm/man/man1/npm-dedupe.1 b/deps/npm/man/man1/npm-dedupe.1 index 664f973b763..2930a90609d 100644 --- a/deps/npm/man/man1/npm-dedupe.1 +++ b/deps/npm/man/man1/npm-dedupe.1 @@ -188,9 +188,10 @@ 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\. +When "true" submit audit reports alongside the current npm command 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 \fBbin\-links\fP .RS 0 .IP \(bu 2 diff --git a/deps/npm/man/man1/npm-explain.1 b/deps/npm/man/man1/npm-explain.1 index ee436af72df..dee71496115 100644 --- a/deps/npm/man/man1/npm-explain.1 +++ b/deps/npm/man/man1/npm-explain.1 @@ -67,6 +67,12 @@ Type: Boolean .RE .P Whether or not to output JSON data, rather than the normal output\. +.RS 0 +.IP \(bu 2 +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before +saving them to your \fBpackage\.json\fP\|\. + +.RE .P Not supported by all npm commands\. .SS \fBworkspace\fP diff --git a/deps/npm/man/man1/npm-find-dupes.1 b/deps/npm/man/man1/npm-find-dupes.1 index 740ea6b4ce1..285dc3128d8 100644 --- a/deps/npm/man/man1/npm-find-dupes.1 +++ b/deps/npm/man/man1/npm-find-dupes.1 @@ -125,9 +125,10 @@ 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\. +When "true" submit audit reports alongside the current npm command 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 \fBbin\-links\fP .RS 0 .IP \(bu 2 diff --git a/deps/npm/man/man1/npm-fund.1 b/deps/npm/man/man1/npm-fund.1 index 073096e37b1..a1fc486010d 100644 --- a/deps/npm/man/man1/npm-fund.1 +++ b/deps/npm/man/man1/npm-fund.1 @@ -73,6 +73,12 @@ Type: Boolean .RE .P Whether or not to output JSON data, rather than the normal output\. +.RS 0 +.IP \(bu 2 +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before +saving them to your \fBpackage\.json\fP\|\. + +.RE .P Not supported by all npm commands\. .SS \fBbrowser\fP diff --git a/deps/npm/man/man1/npm-init.1 b/deps/npm/man/man1/npm-init.1 index cf630053bd1..bce9c09f6ed 100644 --- a/deps/npm/man/man1/npm-init.1 +++ b/deps/npm/man/man1/npm-init.1 @@ -211,6 +211,8 @@ Allow unpublishing all versions of a published package\. Allow conflicting peerDependencies to be installed in the root project\. .IP \(bu 2 Implicitly set \fB\-\-yes\fP during \fBnpm init\fP\|\. +.IP \(bu 2 +Allow clobbering existing values in \fBnpm pkg\fP .RE .P diff --git a/deps/npm/man/man1/npm-install-ci-test.1 b/deps/npm/man/man1/npm-install-ci-test.1 index b5c9bb4c57a..b2fad00b06b 100644 --- a/deps/npm/man/man1/npm-install-ci-test.1 +++ b/deps/npm/man/man1/npm-install-ci-test.1 @@ -16,6 +16,19 @@ This command runs \fBnpm ci\fP followed immediately by \fBnpm test\fP\|\. .SS Configuration <!\-\- AUTOGENERATED CONFIG DESCRIPTIONS START \-\-> <!\-\- automatically generated, do not edit manually \-\-> +.SS \fBaudit\fP +.RS 0 +.IP \(bu 2 +Default: true +.IP \(bu 2 +Type: Boolean + +.RE +.P +When "true" submit audit reports alongside the current npm command 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 \fBignore\-scripts\fP .RS 0 .IP \(bu 2 diff --git a/deps/npm/man/man1/npm-install-test.1 b/deps/npm/man/man1/npm-install-test.1 index ccd9c6ef055..0b403e8fee7 100644 --- a/deps/npm/man/man1/npm-install-test.1 +++ b/deps/npm/man/man1/npm-install-test.1 @@ -181,9 +181,10 @@ 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\. +When "true" submit audit reports alongside the current npm command 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 \fBbin\-links\fP .RS 0 .IP \(bu 2 diff --git a/deps/npm/man/man1/npm-install.1 b/deps/npm/man/man1/npm-install.1 index b6c5fece489..5ad3b9024fd 100644 --- a/deps/npm/man/man1/npm-install.1 +++ b/deps/npm/man/man1/npm-install.1 @@ -583,9 +583,10 @@ 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\. +When "true" submit audit reports alongside the current npm command 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 \fBbin\-links\fP .RS 0 .IP \(bu 2 diff --git a/deps/npm/man/man1/npm-link.1 b/deps/npm/man/man1/npm-link.1 index 7f4ae29f812..35275122323 100644 --- a/deps/npm/man/man1/npm-link.1 +++ b/deps/npm/man/man1/npm-link.1 @@ -271,9 +271,10 @@ 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\. +When "true" submit audit reports alongside the current npm command 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 \fBbin\-links\fP .RS 0 .IP \(bu 2 diff --git a/deps/npm/man/man1/npm-ls.1 b/deps/npm/man/man1/npm-ls.1 index 3fe8962f231..a1814ca4633 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\.19\.1 /path/to/npm +npm@7\.20\.0 /path/to/npm └─┬ init\-package\-json@0\.0\.4 └── promzard@0\.1\.5 .fi @@ -94,6 +94,12 @@ Type: Boolean .RE .P Whether or not to output JSON data, rather than the normal output\. +.RS 0 +.IP \(bu 2 +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before +saving them to your \fBpackage\.json\fP\|\. + +.RE .P Not supported by all npm commands\. .SS \fBlong\fP diff --git a/deps/npm/man/man1/npm-org.1 b/deps/npm/man/man1/npm-org.1 index faf5beccf77..ca4d12eb3b4 100644 --- a/deps/npm/man/man1/npm-org.1 +++ b/deps/npm/man/man1/npm-org.1 @@ -103,6 +103,12 @@ Type: Boolean .RE .P Whether or not to output JSON data, rather than the normal output\. +.RS 0 +.IP \(bu 2 +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before +saving them to your \fBpackage\.json\fP\|\. + +.RE .P Not supported by all npm commands\. .SS \fBparseable\fP diff --git a/deps/npm/man/man1/npm-outdated.1 b/deps/npm/man/man1/npm-outdated.1 index 44949711c0a..5bea638d57d 100644 --- a/deps/npm/man/man1/npm-outdated.1 +++ b/deps/npm/man/man1/npm-outdated.1 @@ -126,6 +126,12 @@ Type: Boolean .RE .P Whether or not to output JSON data, rather than the normal output\. +.RS 0 +.IP \(bu 2 +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before +saving them to your \fBpackage\.json\fP\|\. + +.RE .P Not supported by all npm commands\. .SS \fBlong\fP diff --git a/deps/npm/man/man1/npm-pack.1 b/deps/npm/man/man1/npm-pack.1 index f881df420ad..7402a53f7c9 100644 --- a/deps/npm/man/man1/npm-pack.1 +++ b/deps/npm/man/man1/npm-pack.1 @@ -37,6 +37,12 @@ Type: Boolean .RE .P Whether or not to output JSON data, rather than the normal output\. +.RS 0 +.IP \(bu 2 +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before +saving them to your \fBpackage\.json\fP\|\. + +.RE .P Not supported by all npm commands\. .SS \fBpack\-destination\fP diff --git a/deps/npm/man/man1/npm-pkg.1 b/deps/npm/man/man1/npm-pkg.1 new file mode 100644 index 00000000000..48044b58ae7 --- /dev/null +++ b/deps/npm/man/man1/npm-pkg.1 @@ -0,0 +1,294 @@ +.TH "NPM\-PKG" "1" "July 2021" "" "" +.SH "NAME" +\fBnpm-pkg\fR \- Manages your package\.json +.SS Synopsis +.P +.RS 2 +.nf +npm pkg get [<field> [\.<subfield> \.\.\.]] +npm pkg set <field>=<value> [\.<subfield>=<value> \.\.\.] +npm pkg delete <field> [\.<subfield> \.\.\.] +.fi +.RE +.SS Description +.P +A command that automates the management of \fBpackage\.json\fP files\. +\fBnpm pkg\fP provide 3 different sub commands that allow you to modify or retrieve +values for given object keys in your \fBpackge\.json\fP\|\. +.P +The syntax to retrieve and set fields is a dot separated representation of +the nested object properties to be found within your \fBpackage\.json\fP, it's the +same notation used in npm help \fBview\fP to retrieve information +from the registry manifest, below you can find more examples on how to use it\. +.P +Returned values are always in \fBjson\fR format\. +.RS 0 +.IP \(bu 2 +\fBnpm pkg get <field>\fP + Retrieves a value \fBkey\fP, defined in your \fBpackage\.json\fP file\. + For example, in order to retrieve the name of the current package, you + can run: +.P +.RS 2 +.nf + npm pkg get name +.fi +.RE + It's also possible to retrieve multiple values at once: +.P +.RS 2 +.nf + npm pkg get name version +.fi +.RE + You can view child fields by separating them with a period\. To retrieve + the value of a test \fBscript\fP value, you would run the following command: +.P +.RS 2 +.nf + npm pkg get scripts\.test +.fi +.RE + For fields that are arrays, requesting a non\-numeric field will return + all of the values from the objects in the list\. For example, to get all + the contributor emails for a package, you would run: +.P +.RS 2 +.nf + npm pkg get contributors\.email +.fi +.RE + You may also use numeric indices in square braces to specifically select + an item in an array field\. To just get the email address of the first + contributor in the list, you can run: +.P +.RS 2 +.nf + npm pkg get contributors[0]\.email +.fi +.RE +.IP \(bu 2 +\fBnpm pkg set <field>=<value>\fP + Sets a \fBvalue\fP in your \fBpackage\.json\fP based on the \fBfield\fP value\. When + saving to your \fBpackage\.json\fP file the same set of rules used during + \fBnpm install\fP and other cli commands that touches the \fBpackage\.json\fP file + are used, making sure to respect the existing indentation and possibly + applying some validation prior to saving values to the file\. + The same syntax used to retrieve values from your package can also be used + to define new properties or overriding existing ones, below are some + examples of how the dot separated syntax can be used to edit your + \fBpackage\.json\fP file\. + Defining a new bin named \fBmynewcommand\fP in your \fBpackage\.json\fP that points + to a file \fBcli\.js\fP: +.P +.RS 2 +.nf + npm pkg set bin\.mynewcommand=cli\.js +.fi +.RE + Setting multiple fields at once is also possible: +.P +.RS 2 +.nf + npm pkg set description='Awesome package' engines\.node='>=10' +.fi +.RE + It's also possible to add to array values, for example to add a new + contributor entry: +.P +.RS 2 +.nf + npm pkg set contributors[0]\.name='Foo' contributors[0]\.email='foo@bar\.ca' +.fi +.RE + You may also append items to the end of an array using the special + empty bracket notation: +.P +.RS 2 +.nf + npm pkg set contributors[]\.name='Foo' contributors[]\.name='Bar' +.fi +.RE + It's also possible to parse values as json prior to saving them to your + \fBpackage\.json\fP file, for example in order to set a \fB"private": true\fP + property: +.P +.RS 2 +.nf + npm pkg set private=true \-\-json +.fi +.RE + It also enables saving values as numbers: +.P +.RS 2 +.nf + npm pkg set tap\.timeout=60 \-\-json +.fi +.RE +.IP \(bu 2 +\fBnpm pkg delete <key>\fP + Deletes a \fBkey\fP from your \fBpackage\.json\fP + The same syntax used to set values from your package can also be used + to remove existing ones\. For example, in order to remove a script named + build: +.P +.RS 2 +.nf + npm pkg delete scripts\.build +.fi +.RE + +.RE +.SS Workspaces support +.P +You can set/get/delete items across your configured workspaces by using the +\fBworkspace\fP or \fBworkspaces\fP config options\. +.P +For example, setting a \fBfunding\fP value across all configured workspaces +of a project: +.P +.RS 2 +.nf +npm pkg set funding=https://example\.com \-\-ws +.fi +.RE +.P +When using \fBnpm pkg get\fP to retrieve info from your configured workspaces, the +returned result will be in a json format in which top level keys are the +names of each workspace, the values of these keys will be the result values +returned from each of the configured workspaces, e\.g: +.P +.RS 2 +.nf +npm pkg get name version \-\-ws +{ + "a": { + "name": "a", + "version": "1\.0\.0" + }, + "b": { + "name": "b", + "version": "1\.0\.0" + } +} +.fi +.RE +.SS Configuration +<!\-\- AUTOGENERATED CONFIG DESCRIPTIONS START \-\-> +<!\-\- automatically generated, do not edit manually \-\-> +.SS \fBforce\fP +.RS 0 +.IP \(bu 2 +Default: false +.IP \(bu 2 +Type: Boolean + +.RE +.P +Removes various protections against unfortunate side effects, common +mistakes, unnecessary performance degradation, and malicious input\. +.RS 0 +.IP \(bu 2 +Allow clobbering non\-npm files in global installs\. +.IP \(bu 2 +Allow the \fBnpm version\fP command to work on an unclean git repository\. +.IP \(bu 2 +Allow deleting the cache folder with \fBnpm cache clean\fP\|\. +.IP \(bu 2 +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\-\-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 unpublishing all versions of a published package\. +.IP \(bu 2 +Allow conflicting peerDependencies to be installed in the root project\. +.IP \(bu 2 +Implicitly set \fB\-\-yes\fP during \fBnpm init\fP\|\. +.IP \(bu 2 +Allow clobbering existing values in \fBnpm pkg\fP + +.RE +.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 \fBjson\fP +.RS 0 +.IP \(bu 2 +Default: false +.IP \(bu 2 +Type: Boolean + +.RE +.P +Whether or not to output JSON data, rather than the normal output\. +.RS 0 +.IP \(bu 2 +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before +saving them to your \fBpackage\.json\fP\|\. + +.RE +.P +Not supported by all npm commands\. +.SS \fBworkspace\fP +.RS 0 +.IP \(bu 2 +Default: +.IP \(bu 2 +Type: String (can be set multiple times) + +.RE +.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 +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 +nested workspaces) + +.RE +.P +When set for the \fBnpm init\fP command, this may be set to the folder of a +workspace which does not yet exist, to create the folder and set it up as a +brand new workspace within the project\. +.P +This value is not exported to the environment for child processes\. +.SS \fBworkspaces\fP +.RS 0 +.IP \(bu 2 +Default: false +.IP \(bu 2 +Type: Boolean + +.RE +.P +Enable running a command in the context of \fBall\fR the configured +workspaces\. +.P +This value is not exported to the environment for child processes\. +<!\-\- AUTOGENERATED CONFIG DESCRIPTIONS END \-\-> +.SH See Also +.RS 0 +.IP \(bu 2 +npm help install +.IP \(bu 2 +npm help init +.IP \(bu 2 +npm help config +.IP \(bu 2 +npm help set\-script +.IP \(bu 2 +npm help workspaces + +.RE diff --git a/deps/npm/man/man1/npm-profile.1 b/deps/npm/man/man1/npm-profile.1 index 5402a125fe6..930fbf2d940 100644 --- a/deps/npm/man/man1/npm-profile.1 +++ b/deps/npm/man/man1/npm-profile.1 @@ -105,6 +105,12 @@ Type: Boolean .RE .P Whether or not to output JSON data, rather than the normal output\. +.RS 0 +.IP \(bu 2 +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before +saving them to your \fBpackage\.json\fP\|\. + +.RE .P Not supported by all npm commands\. .SS \fBparseable\fP diff --git a/deps/npm/man/man1/npm-prune.1 b/deps/npm/man/man1/npm-prune.1 index 863283a87cb..41b7b00a5cd 100644 --- a/deps/npm/man/man1/npm-prune.1 +++ b/deps/npm/man/man1/npm-prune.1 @@ -80,6 +80,12 @@ Type: Boolean .RE .P Whether or not to output JSON data, rather than the normal output\. +.RS 0 +.IP \(bu 2 +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before +saving them to your \fBpackage\.json\fP\|\. + +.RE .P Not supported by all npm commands\. .SS \fBworkspace\fP diff --git a/deps/npm/man/man1/npm-search.1 b/deps/npm/man/man1/npm-search.1 index 9b0b17b433c..d500a4e8ef8 100644 --- a/deps/npm/man/man1/npm-search.1 +++ b/deps/npm/man/man1/npm-search.1 @@ -57,6 +57,12 @@ Type: Boolean .RE .P Whether or not to output JSON data, rather than the normal output\. +.RS 0 +.IP \(bu 2 +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before +saving them to your \fBpackage\.json\fP\|\. + +.RE .P Not supported by all npm commands\. .SS \fBcolor\fP diff --git a/deps/npm/man/man1/npm-team.1 b/deps/npm/man/man1/npm-team.1 index 2fef23d16b0..54e27248b54 100644 --- a/deps/npm/man/man1/npm-team.1 +++ b/deps/npm/man/man1/npm-team.1 @@ -150,6 +150,12 @@ Type: Boolean .RE .P Whether or not to output JSON data, rather than the normal output\. +.RS 0 +.IP \(bu 2 +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before +saving them to your \fBpackage\.json\fP\|\. + +.RE .P Not supported by all npm commands\. <!\-\- AUTOGENERATED CONFIG DESCRIPTIONS END \-\-> diff --git a/deps/npm/man/man1/npm-unpublish.1 b/deps/npm/man/man1/npm-unpublish.1 index 8bee0313fca..edef7115fc0 100644 --- a/deps/npm/man/man1/npm-unpublish.1 +++ b/deps/npm/man/man1/npm-unpublish.1 @@ -93,6 +93,8 @@ Allow unpublishing all versions of a published package\. Allow conflicting peerDependencies to be installed in the root project\. .IP \(bu 2 Implicitly set \fB\-\-yes\fP during \fBnpm init\fP\|\. +.IP \(bu 2 +Allow clobbering existing values in \fBnpm pkg\fP .RE .P diff --git a/deps/npm/man/man1/npm-update.1 b/deps/npm/man/man1/npm-update.1 index 6e1ccbcaadf..ca717f8d02f 100644 --- a/deps/npm/man/man1/npm-update.1 +++ b/deps/npm/man/man1/npm-update.1 @@ -13,7 +13,9 @@ aliases: up, upgrade .SS Description .P This command will update all the packages listed to the latest version -(specified by the \fBtag\fP config), respecting semver\. +(specified by the \fBtag\fP config), respecting the semver constraints of +both your package and its dependencies (if they also require the same +package)\. .P It will also install missing packages\. .P @@ -103,6 +105,41 @@ If the dependence were on \fB^0\.4\.0\fP: .P Then \fBnpm update\fP will install \fBdep1@0\.4\.1\fP, because that is the highest\-sorting version that satisfies \fB^0\.4\.0\fP (\fB>= 0\.4\.0 <0\.5\.0\fP) +.SS Subdependencies +.P +Suppose your app now also has a dependency on \fBdep2\fP +.P +.RS 2 +.nf +{ + "name": "my\-app", + "dependencies": { + "dep1": "^1\.0\.0", + "dep2": "1\.0\.0" + } +} +.fi +.RE +.P +and \fBdep2\fP itself depends on this limited range of \fBdep1\fP +.P +.RS 2 +.nf +{ +"name": "dep2", + "dependencies": { + "dep1": "~1\.1\.1" + } +} +.fi +.RE +.P +Then \fBnpm update\fP will install \fBdep1@1\.1\.2\fP because that is the highest +version that \fBdep2\fP allows\. npm will prioritize having a single version +of \fBdep1\fP in your tree rather than two when that single version can +satisfy the semver requirements of multiple dependencies in your tree\. +In this case if you really did need your package to use a newer version +you would need to use \fBnpm install\fP\|\. .SS Updating Globally\-Installed Packages .P \fBnpm update \-g\fP will apply the \fBupdate\fP action to each globally installed @@ -250,9 +287,10 @@ 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\. +When "true" submit audit reports alongside the current npm command 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 \fBbin\-links\fP .RS 0 .IP \(bu 2 diff --git a/deps/npm/man/man1/npm-version.1 b/deps/npm/man/man1/npm-version.1 index 874337beb37..f798ed97a15 100644 --- a/deps/npm/man/man1/npm-version.1 +++ b/deps/npm/man/man1/npm-version.1 @@ -56,6 +56,12 @@ Type: Boolean .RE .P Whether or not to output JSON data, rather than the normal output\. +.RS 0 +.IP \(bu 2 +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before +saving them to your \fBpackage\.json\fP\|\. + +.RE .P Not supported by all npm commands\. .SS \fBpreid\fP diff --git a/deps/npm/man/man1/npm-view.1 b/deps/npm/man/man1/npm-view.1 index 08d9fe0abd3..a63cab9feec 100644 --- a/deps/npm/man/man1/npm-view.1 +++ b/deps/npm/man/man1/npm-view.1 @@ -55,7 +55,7 @@ npm view opts@$(npm view ronn dependencies\.opts) .P For fields that are arrays, requesting a non\-numeric field will return all of the values from the objects in the list\. For example, to get all -the contributor names for the \fBexpress\fP package, you would run: +the contributor email addresses for the \fBexpress\fP package, you would run: .P .RS 2 .nf @@ -124,6 +124,12 @@ Type: Boolean .RE .P Whether or not to output JSON data, rather than the normal output\. +.RS 0 +.IP \(bu 2 +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before +saving them to your \fBpackage\.json\fP\|\. + +.RE .P Not supported by all npm commands\. .SS \fBworkspace\fP diff --git a/deps/npm/man/man1/npm.1 b/deps/npm/man/man1/npm.1 index d73ecc120df..36f677399d4 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\.19\.1 +7\.20\.0 .SS Description .P npm is the package manager for the Node JavaScript platform\. It puts diff --git a/deps/npm/man/man5/folders.5 b/deps/npm/man/man5/folders.5 index e0f5574b747..80b6db80740 100644 --- a/deps/npm/man/man5/folders.5 +++ b/deps/npm/man/man5/folders.5 @@ -46,13 +46,15 @@ Global installs on Windows go to \fB{prefix}/node_modules\fP (that is, no Scoped packages are installed the same way, except they are grouped together in a sub\-folder of the relevant \fBnode_modules\fP folder with the name of that scope prefix by the @ symbol, e\.g\. \fBnpm install @myorg/package\fP would place -the package in \fB{prefix}/node_modules/@myorg/package\fP\|\. See npm help \fBscope\fP for more details\. +the package in \fB{prefix}/node_modules/@myorg/package\fP\|\. See +npm help \fBscope\fP for more details\. .P If you wish to \fBrequire()\fP a package, then install it locally\. .SS Executables .P When in global mode, executables are linked into \fB{prefix}/bin\fP on Unix, -or directly into \fB{prefix}\fP on Windows\. +or directly into \fB{prefix}\fP on Windows\. Ensure that path is in your +terminal's \fBPATH\fP environment to run them\. .P When in local mode, executables are linked into \fB\|\./node_modules/\.bin\fP so that they can be made available to scripts run diff --git a/deps/npm/man/man5/package-json.5 b/deps/npm/man/man5/package-json.5 index f97a3d2d5fd..323394188a4 100644 --- a/deps/npm/man/man5/package-json.5 +++ b/deps/npm/man/man5/package-json.5 @@ -388,9 +388,12 @@ install into the PATH\. npm makes this pretty easy (in fact, it uses this feature to install the "npm" executable\.) .P To use this, supply a \fBbin\fP field in your package\.json which is a map of -command name to local file name\. On install, npm will symlink that file -into \fBprefix/bin\fP for global installs, or \fB\|\./node_modules/\.bin/\fP for local -installs\. +command name to local file name\. When this package is installed +globally, that file will be linked where global bins go so it is +available to run by name\. When this package is installed as a +dependency in another package, the file will be linked where it will be +available to that package either directly by \fBnpm exec\fP or by name in other +scripts when invoking them via \fBnpm run\-script\fP\|\. .P For example, myapp could have this: .P @@ -439,6 +442,9 @@ Please make sure that your file(s) referenced in \fBbin\fP starts with executable! .P Note that you can also set the executable files using directories\.bin \fI#directoriesbin\fR\|\. +.P +See npm help folders for more info on +executables\. .SS man .P Specify either a single file or an array of filenames to put in place for diff --git a/deps/npm/man/man7/config.7 b/deps/npm/man/man7/config.7 index 048dcf14113..ac0a415f10a 100644 --- a/deps/npm/man/man7/config.7 +++ b/deps/npm/man/man7/config.7 @@ -72,6 +72,8 @@ The following shorthands are parsed on the command\-line: .IP \(bu 2 \fB\-g\fP: \fB\-\-global\fP .IP \(bu 2 +\fB\-L\fP: \fB\-\-location\fP +.IP \(bu 2 \fB\-d\fP: \fB\-\-loglevel info\fP .IP \(bu 2 \fB\-s\fP: \fB\-\-loglevel silent\fP @@ -226,9 +228,10 @@ 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\. +When "true" submit audit reports alongside the current npm command 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 \fBaudit\-level\fP .RS 0 .IP \(bu 2 @@ -663,6 +666,8 @@ Allow unpublishing all versions of a published package\. Allow conflicting peerDependencies to be installed in the root project\. .IP \(bu 2 Implicitly set \fB\-\-yes\fP during \fBnpm init\fP\|\. +.IP \(bu 2 +Allow clobbering existing values in \fBnpm pkg\fP .RE .P @@ -931,6 +936,12 @@ Type: Boolean .RE .P Whether or not to output JSON data, rather than the normal output\. +.RS 0 +.IP \(bu 2 +In \fBnpm pkg set\fP it enables parsing set values with JSON\.parse() before +saving them to your \fBpackage\.json\fP\|\. + +.RE .P Not supported by all npm commands\. .SS \fBkey\fP @@ -1007,6 +1018,17 @@ Type: IP Address .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 \fBlocation\fP +.RS 0 +.IP \(bu 2 +Default: "user" unless \fB\-\-global\fP is passed, which will also set this value +to "global" +.IP \(bu 2 +Type: "global", "user", or "project" + +.RE +.P +When passed to \fBnpm config\fP this refers to which config file to use\. .SS \fBloglevel\fP .RS 0 .IP \(bu 2 diff --git a/deps/npm/man/man7/scripts.7 b/deps/npm/man/man7/scripts.7 index 56a3326b6c4..cac6ab0a2a3 100644 --- a/deps/npm/man/man7/scripts.7 +++ b/deps/npm/man/man7/scripts.7 @@ -60,7 +60,8 @@ script, its \fBdependencies\fP and \fBdevDependencies\fP will be installed, and the prepare script will be run, before the package is packaged and installed\. .IP \(bu 2 -As of \fBnpm@7\fP these scripts run in the background +As of \fBnpm@7\fP these scripts run in the background\. +To see the output, run with: \fB\-\-foreground\-scripts\fP\|\. .RE .P @@ -391,8 +392,8 @@ Scripts are run by passing the line as a script argument to \fBsh\fP\|\. If the script exits with a code other than 0, then this will abort the process\. .P -Note that these script files don't have to be nodejs or even -javascript programs\. They just have to be some kind of executable +Note that these script files don't have to be Node\.js or even +JavaScript programs\. They just have to be some kind of executable file\. .SS Best Practices .RS 0 diff --git a/deps/npm/man/man7/workspaces.7 b/deps/npm/man/man7/workspaces.7 index 70abfd5f972..52128895a4a 100644 --- a/deps/npm/man/man7/workspaces.7 +++ b/deps/npm/man/man7/workspaces.7 @@ -35,7 +35,7 @@ npm help \fBpackage\.json\fP file, e\.g: .P Given the above \fBpackage\.json\fP example living at a current working directory \fB\|\.\fP that contains a folder named \fBworkspace\-a\fP that itself contains -a \fBpackage\.json\fP inside it, defining a nodejs package, e\.g: +a \fBpackage\.json\fP inside it, defining a Node\.js package, e\.g: .P .RS 2 .nf diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js index 5db11eb3832..fdb947dc590 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js @@ -324,7 +324,7 @@ module.exports = cls => class IdealTreeBuilder extends cls { .then(async root => { if (!this[_updateAll] && !this[_global] && !root.meta.loadedFromDisk) { await new this.constructor(this.options).loadActual({ root }) - const tree = root.target || root + const tree = root.target // even though we didn't load it from a package-lock.json FILE, // we still loaded it "from disk", meaning we have to reset // dep flags before assuming that any mutations were reflected. @@ -396,7 +396,7 @@ module.exports = cls => class IdealTreeBuilder extends cls { // update.names request by queueing nodes dependent on those named. async [_applyUserRequests] (options) { process.emit('time', 'idealTree:userRequests') - const tree = this.idealTree.target || this.idealTree + const tree = this.idealTree.target if (!this[_workspaces].length) await this[_applyUserRequestsToNode](tree, options) @@ -532,7 +532,7 @@ module.exports = cls => class IdealTreeBuilder extends cls { /* istanbul ignore else - should also be covered by realpath failure */ if (filepath) { const { name } = spec - const tree = this.idealTree.target || this.idealTree + const tree = this.idealTree.target spec = npa(`file:${relpath(tree.path, filepath)}`, tree.path) spec.name = name } @@ -730,7 +730,7 @@ This is a one-time fix-up, please be patient... // or extraneous. [_buildDeps] () { process.emit('time', 'idealTree:buildDeps') - const tree = this.idealTree.target || this.idealTree + const tree = this.idealTree.target this[_depsQueue].push(tree) this.log.silly('idealTree', 'buildDeps') this.addTracker('idealTree', tree.name, '') @@ -788,7 +788,11 @@ This is a one-time fix-up, please be patient... const Arborist = this.constructor const opt = { ...this.options } await cacache.tmp.withTmp(this.cache, opt, async path => { - await pacote.extract(node.resolved, path, opt) + await pacote.extract(node.resolved, path, { + ...opt, + resolved: node.resolved, + integrity: node.integrity, + }) if (hasShrinkwrap) { await new Arborist({ ...this.options, path }) @@ -914,7 +918,7 @@ This is a one-time fix-up, please be patient... await Promise.all(promises) for (const { to } of node.edgesOut.values()) { - if (to && to.isLink) + if (to && to.isLink && to.target) this[_linkNodes].add(to) } @@ -1293,7 +1297,7 @@ This is a one-time fix-up, please be patient... // when installing globally, or just in global style, we never place // deps above the first level. - const tree = this.idealTree && this.idealTree.target || this.idealTree + const tree = this.idealTree && this.idealTree.target if (this[_globalStyle] && check.resolveParent === tree) break } @@ -1362,7 +1366,7 @@ This is a one-time fix-up, please be patient... integrity: dep.integrity, legacyPeerDeps: this.legacyPeerDeps, error: dep.errors[0], - ...(dep.target ? { target: dep.target, realpath: dep.target.path } : {}), + ...(dep.isLink ? { target: dep.target, realpath: dep.target.path } : {}), }) if (this[_loadFailures].has(dep)) this[_loadFailures].add(newDep) @@ -1421,7 +1425,7 @@ This is a one-time fix-up, please be patient... // prune anything deeper in the tree that can be replaced by this if (this.idealTree) { for (const node of this.idealTree.inventory.query('name', newDep.name)) { - if (node.isDescendantOf(target)) + if (!node.isTop && node.isDescendantOf(target)) this[_pruneDedupable](node, false) } } @@ -1819,7 +1823,7 @@ This is a one-time fix-up, please be patient... const current = target !== entryEdge.from && target.resolve(dep.name) if (current) { for (const edge of current.edgesIn.values()) { - if (edge.from.isDescendantOf(target) && edge.valid) { + if (!edge.from.isTop && edge.from.isDescendantOf(target) && edge.valid) { if (!edge.satisfiedBy(dep)) return CONFLICT } @@ -1876,7 +1880,8 @@ This is a one-time fix-up, please be patient... if (link.root !== this.idealTree) continue - const external = /^\.\.(\/|$)/.test(relpath(this.path, link.realpath)) + const tree = this.idealTree.target + const external = !link.target.isDescendantOf(tree) // outside the root, somebody else's problem, ignore it if (external && !this[_follow]) diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/index.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/index.js index 94501cae12c..b26a26c2be2 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/index.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/index.js @@ -81,7 +81,7 @@ class Arborist extends Base { const dep = edge.to if (dep) { set.add(dep) - if (dep.target) + if (dep.isLink) set.add(dep.target) } } diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-actual.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-actual.js index 9fca7d6425d..86856d868b4 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-actual.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-actual.js @@ -315,7 +315,7 @@ module.exports = cls => class ActualLoader extends cls { [_loadFSTree] (node) { const did = this[_actualTreeLoaded] - node = node.target || node + node = node.target // if a Link target has started, but not completed, then // a Promise will be in the cache to indicate this. diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js index a98ed23b2a4..d1edcaca01d 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js @@ -221,7 +221,7 @@ module.exports = cls => class VirtualLoader extends cls { [assignBundles] (nodes) { for (const [location, node] of nodes) { // Skip assignment of parentage for the root package - if (!location || node.target && !node.target.location) + if (!location || node.isLink && !node.target.location) continue const { name, parent, package: { inBundle }} = node diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/rebuild.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/rebuild.js index d189ad8c99e..8e447bb8f5a 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/rebuild.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/rebuild.js @@ -169,7 +169,7 @@ module.exports = cls => class Builder extends cls { const queue = [...set].sort(sortNodes) for (const node of queue) { - const { package: { bin, scripts = {} } } = node + const { package: { bin, scripts = {} } } = node.target const { preinstall, install, postinstall, prepare } = scripts const tests = { bin, preinstall, install, postinstall, prepare } for (const [key, has] of Object.entries(tests)) { @@ -202,7 +202,7 @@ module.exports = cls => class Builder extends cls { !(meta.originalLockfileVersion >= 2) } - const { package: pkg, hasInstallScript } = node + const { package: pkg, hasInstallScript } = node.target const { gypfile, bin, scripts = {} } = pkg const { preinstall, install, postinstall, prepare } = scripts @@ -263,7 +263,7 @@ module.exports = cls => class Builder extends cls { devOptional, package: pkg, location, - } = node.target || node + } = node.target // skip any that we know we'll be deleting if (this[_trashList].has(path)) 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 f259a69b548..18b5cd65262 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js @@ -289,8 +289,8 @@ module.exports = cls => class Reifier extends cls { const filterNodes = [] if (this[_global] && this.explicitRequests.size) { - const idealTree = this.idealTree.target || this.idealTree - const actualTree = this.actualTree.target || this.actualTree + const idealTree = this.idealTree.target + const actualTree = this.actualTree.target // we ONLY are allowed to make changes in the global top-level // children where there's an explicit request. for (const { name } of this.explicitRequests) { @@ -404,10 +404,9 @@ module.exports = cls => class Reifier extends cls { return process.emit('time', 'reify:trashOmits') - // node.parent is checked to make sure this is a node that's in the tree, and - // not the parent-less top level nodes + const filter = node => - node.isDescendantOf(this.idealTree) && + node.top.isProjectRoot && (node.peer && this[_omitPeer] || node.dev && this[_omitDev] || node.optional && this[_omitOptional] || @@ -664,7 +663,7 @@ module.exports = cls => class Reifier extends cls { const node = diff.ideal if (!node) return - if (node.isProjectRoot || (node.target && node.target.isProjectRoot)) + if (node.isProjectRoot) return const { bundleDependencies } = node.package @@ -887,6 +886,18 @@ module.exports = cls => class Reifier extends cls { filter: diff => diff.action === 'ADD' || diff.action === 'CHANGE', }) + // pick up link nodes from the unchanged list as we want to run their + // scripts in every install despite of having a diff status change + for (const node of this.diff.unchanged) { + const tree = node.root.target + + // skip links that only live within node_modules as they are most + // likely managed by packages we installed, we only want to rebuild + // unchanged links we directly manage + if (node.isLink && node.target.fsTop === tree) + nodes.push(node) + } + return this.rebuild({ nodes, handleOptionalFailure: true }) .then(() => process.emit('timeEnd', 'reify:build')) } diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/calc-dep-flags.js b/deps/npm/node_modules/@npmcli/arborist/lib/calc-dep-flags.js index 21d8ddcf7b4..968fc83c513 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/calc-dep-flags.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/calc-dep-flags.js @@ -29,7 +29,7 @@ const calcDepFlagsStep = (node) => { resetParents(node, 'optional') // for links, map their hierarchy appropriately - if (node.target) { + if (node.isLink) { node.target.dev = node.dev node.target.optional = node.optional node.target.devOptional = node.devOptional @@ -92,10 +92,10 @@ const unsetFlag = (node, flag) => { tree: node, visit: node => { node.extraneous = node[flag] = false - if (node.target) + if (node.isLink) node.target.extraneous = node.target[flag] = false }, - getChildren: node => [...(node.target || node).edgesOut.values()] + getChildren: node => [...node.target.edgesOut.values()] .filter(edge => edge.to && edge.to[flag] && (flag !== 'peer' && edge.type === 'peer' || edge.type === 'prod')) .map(edge => edge.to), diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/diff.js b/deps/npm/node_modules/@npmcli/arborist/lib/diff.js index 1f8eff0f0c4..2008ef7a35b 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/diff.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/diff.js @@ -45,8 +45,7 @@ class Diff { const { root } = filterNode if (root !== ideal && root !== actual) throw new Error('invalid filterNode: outside idealTree/actualTree') - const { target } = root - const rootTarget = target || root + const rootTarget = root.target const edge = [...rootTarget.edgesOut.values()].filter(e => { return e.to && (e.to === filterNode || e.to.target === filterNode) })[0] @@ -56,8 +55,7 @@ class Diff { filterSet.add(actual) if (edge && edge.to) { filterSet.add(edge.to) - if (edge.to.target) - filterSet.add(edge.to.target) + filterSet.add(edge.to.target) } filterSet.add(filterNode) @@ -65,7 +63,7 @@ class Diff { tree: filterNode, visit: node => filterSet.add(node), getChildren: node => { - node = node.target || node + node = node.target const loc = node.location const idealNode = ideal.inventory.get(loc) const ideals = !idealNode ? [] diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/node.js b/deps/npm/node_modules/@npmcli/arborist/lib/node.js index c21bc46cfb5..2ef0a64f088 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/node.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/node.js @@ -409,7 +409,7 @@ class Node { } isDescendantOf (node) { - for (let p = this; p; p = p.parent) { + for (let p = this; p; p = p.resolveParent) { if (p === node) return true } @@ -649,7 +649,7 @@ class Node { }) if (this.isLink) { - const target = node.target || node + const target = node.target this[_target] = target this[_package] = target.package target.linksIn.add(this) @@ -1174,7 +1174,7 @@ class Node { } get target () { - return null + return this } set target (n) { @@ -1197,6 +1197,14 @@ class Node { return this.isTop ? this : this.parent.top } + get isFsTop () { + return !this.fsParent + } + + get fsTop () { + return this.isFsTop ? this : this.fsParent.fsTop + } + get resolveParent () { return this.parent || this.fsParent } diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/shrinkwrap.js b/deps/npm/node_modules/@npmcli/arborist/lib/shrinkwrap.js index b251539a94c..3b2cf0bde10 100644 --- a/deps/npm/node_modules/@npmcli/arborist/lib/shrinkwrap.js +++ b/deps/npm/node_modules/@npmcli/arborist/lib/shrinkwrap.js @@ -802,7 +802,7 @@ class Shrinkwrap { if (this.tree) { if (this.yarnLock) this.yarnLock.fromTree(this.tree) - const root = Shrinkwrap.metaFromNode(this.tree.target || this.tree, this.path) + const root = Shrinkwrap.metaFromNode(this.tree.target, this.path) this.data.packages = {} if (Object.keys(root).length) this.data.packages[''] = root @@ -864,7 +864,7 @@ class Shrinkwrap { const spec = !edge ? rSpec : npa.resolve(node.name, edge.spec, edge.from.realpath) - if (node.target) + if (node.isLink) lock.version = `file:${relpath(this.path, node.realpath)}` else if (spec && (spec.type === 'file' || spec.type === 'remote')) lock.version = spec.saveSpec @@ -888,7 +888,7 @@ class Shrinkwrap { // when we didn't resolve to git, file, or dir, and didn't request // git, file, dir, or remote, then the resolved value is necessary. if (node.resolved && - !node.target && + !node.isLink && rSpec.type !== 'git' && rSpec.type !== 'file' && rSpec.type !== 'directory' && @@ -917,7 +917,7 @@ class Shrinkwrap { lock.optional = true } - const depender = node.target || node + const depender = node.target if (depender.edgesOut.size > 0) { if (node !== this.tree) { lock.requires = [...depender.edgesOut.entries()].reduce((set, [k, v]) => { @@ -942,7 +942,7 @@ class Shrinkwrap { } // now we walk the children, putting them in the 'dependencies' object - const {children} = node.target || node + const {children} = node.target if (!children.size) delete lock.dependencies else { diff --git a/deps/npm/node_modules/@npmcli/arborist/package.json b/deps/npm/node_modules/@npmcli/arborist/package.json index 138d6ec25b4..c45a61086ea 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.6.4", + "version": "2.7.1", "description": "Manage node_modules trees", "dependencies": { "@npmcli/installed-package-contents": "^1.0.7", @@ -16,6 +16,7 @@ "common-ancestor-path": "^1.0.1", "json-parse-even-better-errors": "^2.3.1", "json-stringify-nice": "^1.1.4", + "mkdirp": "^1.0.4", "mkdirp-infer-owner": "^2.0.0", "npm-install-checks": "^4.0.0", "npm-package-arg": "^8.1.0", @@ -28,7 +29,9 @@ "promise-call-limit": "^1.0.1", "read-package-json-fast": "^2.0.2", "readdir-scoped-modules": "^1.1.0", + "rimraf": "^3.0.2", "semver": "^7.3.5", + "ssri": "^8.0.1", "tar": "^6.1.0", "treeverse": "^1.0.4", "walk-up-path": "^1.0.0" diff --git a/deps/npm/node_modules/@npmcli/git/lib/errors.js b/deps/npm/node_modules/@npmcli/git/lib/errors.js new file mode 100644 index 00000000000..25b2b9f9fd6 --- /dev/null +++ b/deps/npm/node_modules/@npmcli/git/lib/errors.js @@ -0,0 +1,36 @@ + +const maxRetry = 3 + +class GitError extends Error { + shouldRetry () { + return false + } +} + +class GitConnectionError extends GitError { + constructor (message) { + super('A git connection error occurred') + } + + shouldRetry (number) { + return number < maxRetry + } +} + +class GitPathspecError extends GitError { + constructor (message) { + super('The git reference could not be found') + } +} + +class GitUnknownError extends GitError { + constructor (message) { + super('An unknown git error occurred') + } +} + +module.exports = { + GitConnectionError, + GitPathspecError, + GitUnknownError +} diff --git a/deps/npm/node_modules/@npmcli/git/lib/index.js b/deps/npm/node_modules/@npmcli/git/lib/index.js index 50fd889b89b..20d7cfd01cf 100644 --- a/deps/npm/node_modules/@npmcli/git/lib/index.js +++ b/deps/npm/node_modules/@npmcli/git/lib/index.js @@ -4,5 +4,6 @@ module.exports = { spawn: require('./spawn.js'), is: require('./is.js'), find: require('./find.js'), - isClean: require('./is-clean.js') + isClean: require('./is-clean.js'), + errors: require('./errors.js') } diff --git a/deps/npm/node_modules/@npmcli/git/lib/make-error.js b/deps/npm/node_modules/@npmcli/git/lib/make-error.js new file mode 100644 index 00000000000..043a8e6e951 --- /dev/null +++ b/deps/npm/node_modules/@npmcli/git/lib/make-error.js @@ -0,0 +1,33 @@ +const { + GitConnectionError, + GitPathspecError, + GitUnknownError +} = require('./errors.js') + +const connectionErrorRe = new RegExp([ + 'remote error: Internal Server Error', + 'The remote end hung up unexpectedly', + 'Connection timed out', + 'Operation timed out', + 'Failed to connect to .* Timed out', + 'Connection reset by peer', + 'SSL_ERROR_SYSCALL', + 'The requested URL returned error: 503' +].join('|')) + +const missingPathspecRe = /pathspec .* did not match any file\(s\) known to git/ + +function makeError (er) { + const message = er.stderr + let gitEr + if (connectionErrorRe.test(message)) { + gitEr = new GitConnectionError(message) + } else if (missingPathspecRe.test(message)) { + gitEr = new GitPathspecError(message) + } else { + gitEr = new GitUnknownError(message) + } + return Object.assign(gitEr, er) +} + +module.exports = makeError diff --git a/deps/npm/node_modules/@npmcli/git/lib/should-retry.js b/deps/npm/node_modules/@npmcli/git/lib/should-retry.js deleted file mode 100644 index 8082bb5d7c6..00000000000 --- a/deps/npm/node_modules/@npmcli/git/lib/should-retry.js +++ /dev/null @@ -1,17 +0,0 @@ -const transientErrors = [ - 'remote error: Internal Server Error', - 'The remote end hung up unexpectedly', - 'Connection timed out', - 'Operation timed out', - 'Failed to connect to .* Timed out', - 'Connection reset by peer', - 'SSL_ERROR_SYSCALL', - 'The requested URL returned error: 503' -].join('|') - -const transientErrorRe = new RegExp(transientErrors) - -const maxRetry = 3 - -module.exports = (error, number) => - transientErrorRe.test(error) && (number < maxRetry) diff --git a/deps/npm/node_modules/@npmcli/git/lib/spawn.js b/deps/npm/node_modules/@npmcli/git/lib/spawn.js index 337164a9a01..1c89a4c53cf 100644 --- a/deps/npm/node_modules/@npmcli/git/lib/spawn.js +++ b/deps/npm/node_modules/@npmcli/git/lib/spawn.js @@ -1,6 +1,6 @@ const spawn = require('@npmcli/promise-spawn') const promiseRetry = require('promise-retry') -const shouldRetry = require('./should-retry.js') +const makeError = require('./make-error.js') const whichGit = require('./which.js') const makeOpts = require('./opts.js') const procLog = require('./proc-log.js') @@ -33,10 +33,11 @@ module.exports = (gitArgs, opts = {}) => { return spawn(gitPath, args, makeOpts(opts)) .catch(er => { - if (!shouldRetry(er.stderr, number)) { - throw er + const gitError = makeError(er) + if (!gitError.shouldRetry(number)) { + throw gitError } - retry(er) + retry(gitError) }) }, retry) } diff --git a/deps/npm/node_modules/@npmcli/git/package.json b/deps/npm/node_modules/@npmcli/git/package.json index 0fe94686ece..9475da5007a 100644 --- a/deps/npm/node_modules/@npmcli/git/package.json +++ b/deps/npm/node_modules/@npmcli/git/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/git", - "version": "2.0.9", + "version": "2.1.0", "main": "lib/index.js", "files": [ "lib/*.js" diff --git a/deps/npm/node_modules/make-fetch-happen/lib/cache/entry.js b/deps/npm/node_modules/make-fetch-happen/lib/cache/entry.js index 41f8a3d215e..a2acea156ee 100644 --- a/deps/npm/node_modules/make-fetch-happen/lib/cache/entry.js +++ b/deps/npm/node_modules/make-fetch-happen/lib/cache/entry.js @@ -48,6 +48,7 @@ const KEEP_RESPONSE_HEADERS = [ // return an object containing all metadata to be written to the index const getMetadata = (request, response, options) => { const metadata = { + time: Date.now(), url: request.url, reqHeaders: {}, resHeaders: {}, @@ -112,9 +113,18 @@ const _policy = Symbol('policy') class CacheEntry { constructor ({ entry, request, response, options }) { - this.entry = entry + if (entry) { + this.key = entry.key + this.entry = entry + // previous versions of this module didn't write an explicit timestamp in + // the metadata, so fall back to the entry's timestamp. we can't use the + // entry timestamp to determine staleness because cacache will update it + // when it verifies its data + this.entry.metadata.time = this.entry.metadata.time || this.entry.time + } else + this.key = cacheKey(request) + this.options = options - this.key = entry ? entry.key : cacheKey(request) // these properties are behind getters that lazily evaluate this[_request] = request @@ -340,13 +350,25 @@ class CacheEntry { const content = await cacache.get.byDigest(this.options.cachePath, this.entry.integrity, { memoize: this.options.memoize }) body.end(content) } catch (err) { + if (err.code === 'EINTEGRITY') + await cacache.rm.content(this.options.cachePath, this.entry.integrity, { memoize: this.options.memoize }) + if (err.code === 'ENOENT' || err.code === 'EINTEGRITY') + await CacheEntry.invalidate(this.request, this.options) body.emit('error', err) } } } else { onResume = () => { const cacheStream = cacache.get.stream.byDigest(this.options.cachePath, this.entry.integrity, { memoize: this.options.memoize }) - cacheStream.on('error', (err) => body.emit('error', err)) + cacheStream.on('error', async (err) => { + cacheStream.pause() + if (err.code === 'EINTEGRITY') + await cacache.rm.content(this.options.cachePath, this.entry.integrity, { memoize: this.options.memoize }) + if (err.code === 'ENOENT' || err.code === 'EINTEGRITY') + await CacheEntry.invalidate(this.request, this.options) + body.emit('error', err) + cacheStream.resume() + }) cacheStream.pipe(body) } } @@ -368,7 +390,7 @@ class CacheEntry { response.headers.set('x-local-cache-key', encodeURIComponent(this.key)) response.headers.set('x-local-cache-mode', shouldBuffer ? 'buffer' : 'stream') response.headers.set('x-local-cache-status', status) - response.headers.set('x-local-cache-time', new Date(this.entry.time).toUTCString()) + response.headers.set('x-local-cache-time', new Date(this.entry.metadata.time).toUTCString()) return response } diff --git a/deps/npm/node_modules/make-fetch-happen/lib/cache/policy.js b/deps/npm/node_modules/make-fetch-happen/lib/cache/policy.js index 189dce80ee6..e0959f64ddf 100644 --- a/deps/npm/node_modules/make-fetch-happen/lib/cache/policy.js +++ b/deps/npm/node_modules/make-fetch-happen/lib/cache/policy.js @@ -67,7 +67,7 @@ class CachePolicy { // this is necessary because the CacheSemantics constructor forces // the value to Date.now() which means a policy created from a // cache entry is likely to always identify itself as stale - this.policy._responseTime = this.entry.time + this.policy._responseTime = this.entry.metadata.time } } diff --git a/deps/npm/node_modules/make-fetch-happen/lib/remote.js b/deps/npm/node_modules/make-fetch-happen/lib/remote.js index e37f39de845..7e4ed24edb5 100644 --- a/deps/npm/node_modules/make-fetch-happen/lib/remote.js +++ b/deps/npm/node_modules/make-fetch-happen/lib/remote.js @@ -14,6 +14,7 @@ const RETRY_ERRORS = [ 'ECONNREFUSED', // remote host refused to open connection 'EADDRINUSE', // failed to bind to a local port (proxy?) 'ETIMEDOUT', // someone in the transaction is WAY TOO SLOW + 'ERR_SOCKET_TIMEOUT', // same as above, but this one comes from agentkeepalive // Known codes we do NOT retry on: // ENOTFOUND (getaddrinfo failure. Either bad hostname, or offline) ] diff --git a/deps/npm/node_modules/make-fetch-happen/package.json b/deps/npm/node_modules/make-fetch-happen/package.json index 44330998bb0..e4a26a9cd94 100644 --- a/deps/npm/node_modules/make-fetch-happen/package.json +++ b/deps/npm/node_modules/make-fetch-happen/package.json @@ -1,6 +1,6 @@ { "name": "make-fetch-happen", - "version": "9.0.3", + "version": "9.0.4", "description": "Opinionated, caching, retrying fetch client", "main": "lib/index.js", "files": [ diff --git a/deps/npm/node_modules/minipass-fetch/lib/index.js b/deps/npm/node_modules/minipass-fetch/lib/index.js index d6ed57942e8..2ffcba85105 100644 --- a/deps/npm/node_modules/minipass-fetch/lib/index.js +++ b/deps/npm/node_modules/minipass-fetch/lib/index.js @@ -94,6 +94,19 @@ const fetch = (url, opts) => { } req.on('error', er => { + // if a 'response' event is emitted before the 'error' event, then by the + // time this handler is run it's too late to reject the Promise for the + // response. instead, we forward the error event to the response stream + // so that the error will surface to the user when they try to consume + // the body. this is done as a side effect of aborting the request except + // for in windows, where we must forward the event manually, otherwise + // there is no longer a ref'd socket attached to the request and the + // stream never ends so the event loop runs out of work and the process + // exits without warning. + // coverage skipped here due to the difficulty in testing + // istanbul ignore next + if (req.res) + req.res.emit('error', er) reject(new FetchError(`request to ${request.url} failed, reason: ${ er.message}`, 'system', er)) finalize() @@ -286,8 +299,16 @@ const fetch = (url, opts) => { // for br - if (codings == 'br' && typeof zlib.BrotliDecompress === 'function') { - const decoder = new zlib.BrotliDecompress() + if (codings == 'br') { + // ignoring coverage so tests don't have to fake support (or lack of) for brotli + // istanbul ignore next + try { + var decoder = new zlib.BrotliDecompress() + } catch (err) { + reject(err) + finalize() + return + } // exceedingly rare that the stream would have an error, // but just in case we proxy it to the stream in use. body.on('error', /* istanbul ignore next */ er => decoder.emit('error', er)).pipe(decoder) diff --git a/deps/npm/node_modules/minipass-fetch/lib/request.js b/deps/npm/node_modules/minipass-fetch/lib/request.js index c5208a7fc13..173f415d18e 100644 --- a/deps/npm/node_modules/minipass-fetch/lib/request.js +++ b/deps/npm/node_modules/minipass-fetch/lib/request.js @@ -77,6 +77,7 @@ class Request extends Body { crl, dhparam, ecdhCurve, + family, honorCipherOrder, key, passphrase, @@ -101,6 +102,7 @@ class Request extends Body { crl, dhparam, ecdhCurve, + family, honorCipherOrder, key, passphrase, @@ -208,6 +210,7 @@ class Request extends Body { crl, dhparam, ecdhCurve, + family, honorCipherOrder, key, passphrase, @@ -234,6 +237,7 @@ class Request extends Body { crl, dhparam, ecdhCurve, + family, honorCipherOrder, key, passphrase, diff --git a/deps/npm/node_modules/minipass-fetch/package.json b/deps/npm/node_modules/minipass-fetch/package.json index df48f372a60..64dab7816bd 100644 --- a/deps/npm/node_modules/minipass-fetch/package.json +++ b/deps/npm/node_modules/minipass-fetch/package.json @@ -1,6 +1,6 @@ { "name": "minipass-fetch", - "version": "1.3.3", + "version": "1.3.4", "description": "An implementation of window.fetch in Node.js using Minipass streams", "license": "MIT", "main": "lib/index.js", diff --git a/deps/npm/node_modules/pacote/lib/fetcher.js b/deps/npm/node_modules/pacote/lib/fetcher.js index d488e88ff72..69dd025b7bd 100644 --- a/deps/npm/node_modules/pacote/lib/fetcher.js +++ b/deps/npm/node_modules/pacote/lib/fetcher.js @@ -119,6 +119,13 @@ class FetcherBase { '--no-progress', '--no-save', '--no-audit', + // override any omit settings from the environment + '--include=dev', + '--include=peer', + '--include=optional', + // we need the actual things, not just the lockfile + '--no-package-lock-only', + '--no-dry-run', ] } @@ -430,6 +437,7 @@ class FetcherBase { return { cwd, noChmod: true, + noMtime: true, filter: (name, entry) => { if (/Link$/.test(entry.type)) return false diff --git a/deps/npm/node_modules/pacote/lib/git.js b/deps/npm/node_modules/pacote/lib/git.js index 973e13ea9be..18f42547bb3 100644 --- a/deps/npm/node_modules/pacote/lib/git.js +++ b/deps/npm/node_modules/pacote/lib/git.js @@ -85,6 +85,9 @@ class GitFetcher extends Fetcher { [_resolvedFromHosted] (hosted) { return this[_resolvedFromRepo](hosted.https && hosted.https()) .catch(er => { + // Throw early since we know pathspec errors will fail again if retried + if (er instanceof git.errors.GitPathspecError) + throw er const ssh = hosted.sshurl && hosted.sshurl() // no fallthrough if we can't fall through or have https auth if (!ssh || hosted.auth) @@ -260,9 +263,11 @@ class GitFetcher extends Fetcher { // is present, otherwise ssh if the hosted type provides it [_cloneHosted] (ref, tmp) { const hosted = this.spec.hosted - const https = hosted.https() return this[_cloneRepo](hosted.https({ noCommittish: true }), ref, tmp) .catch(er => { + // Throw early since we know pathspec errors will fail again if retried + if (er instanceof git.errors.GitPathspecError) + throw er const ssh = hosted.sshurl && hosted.sshurl({ noCommittish: true }) // no fallthrough if we can't fall through or have https auth if (!ssh || hosted.auth) diff --git a/deps/npm/node_modules/pacote/package.json b/deps/npm/node_modules/pacote/package.json index 7472c6eeab0..437bb8f79e1 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.4", + "version": "11.3.5", "description": "JavaScript package downloader", "author": "Isaac Z. Schlueter <i@izs.me> (https://izs.me)", "bin": { @@ -33,7 +33,7 @@ "git" ], "dependencies": { - "@npmcli/git": "^2.0.1", + "@npmcli/git": "^2.1.0", "@npmcli/installed-package-contents": "^1.0.6", "@npmcli/promise-spawn": "^1.2.0", "@npmcli/run-script": "^1.8.2", diff --git a/deps/npm/node_modules/socks/typings/common/receivebuffer.d.ts b/deps/npm/node_modules/socks/typings/common/receivebuffer.d.ts new file mode 100644 index 00000000000..756e98b5893 --- /dev/null +++ b/deps/npm/node_modules/socks/typings/common/receivebuffer.d.ts @@ -0,0 +1,12 @@ +/// <reference types="node" /> +declare class ReceiveBuffer { + private buffer; + private offset; + private originalSize; + constructor(size?: number); + get length(): number; + append(data: Buffer): number; + peek(length: number): Buffer; + get(length: number): Buffer; +} +export { ReceiveBuffer }; diff --git a/deps/npm/package.json b/deps/npm/package.json index 73b03991026..f0b9642905c 100644 --- a/deps/npm/package.json +++ b/deps/npm/package.json @@ -1,5 +1,5 @@ { - "version": "7.19.1", + "version": "7.20.0", "name": "npm", "description": "a package manager for JavaScript", "workspaces": [ @@ -53,7 +53,7 @@ "./package.json": "./package.json" }, "dependencies": { - "@npmcli/arborist": "^2.6.4", + "@npmcli/arborist": "^2.7.1", "@npmcli/ci-detect": "^1.2.0", "@npmcli/config": "^2.2.0", "@npmcli/package-json": "^1.0.1", @@ -88,7 +88,7 @@ "libnpmsearch": "^3.1.1", "libnpmteam": "^2.0.3", "libnpmversion": "^1.2.1", - "make-fetch-happen": "^9.0.3", + "make-fetch-happen": "^9.0.4", "minipass": "^3.1.3", "minipass-pipeline": "^1.2.4", "mkdirp": "^1.0.4", @@ -104,7 +104,7 @@ "npm-user-validate": "^1.0.1", "npmlog": "~4.1.2", "opener": "^1.5.2", - "pacote": "^11.3.3", + "pacote": "^11.3.5", "parse-conflict-json": "^1.1.1", "qrcode-terminal": "^0.12.0", "read": "~1.0.7", @@ -193,7 +193,7 @@ "write-file-atomic" ], "devDependencies": { - "eslint": "^7.26.0", + "eslint": "^7.30.0", "eslint-plugin-import": "^2.23.4", "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^5.1.0", diff --git a/deps/npm/tap-snapshots/smoke-tests/index.js.test.cjs b/deps/npm/tap-snapshots/smoke-tests/index.js.test.cjs index 89c0cb20b5e..0a79e38cdfa 100644 --- a/deps/npm/tap-snapshots/smoke-tests/index.js.test.cjs +++ b/deps/npm/tap-snapshots/smoke-tests/index.js.test.cjs @@ -26,10 +26,10 @@ All commands: 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 + pkg, 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: {CWD}/smoke-tests/tap-testdir-index/.npmrc @@ -482,6 +482,89 @@ abbrev 1.0.4 1.1.1 1.1.1 node_modules/abbrev project ` +exports[`smoke-tests/index.js TAP npm pkg > should have expected npm pkg delete modified package.json result 1`] = ` +{ + "name": "project", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo /"Error: no test specified/" && exit 1", + "hello": "echo Hello" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "abbrev": "^1.0.4" + } +} + +` + +exports[`smoke-tests/index.js TAP npm pkg > should have expected npm pkg set modified package.json result 1`] = ` +{ + "name": "project", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo /"Error: no test specified/" && exit 1", + "hello": "echo Hello" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "abbrev": "^1.0.4" + }, + "tap": { + "test-env": [ + "LC_ALL=sk" + ] + } +} + +` + +exports[`smoke-tests/index.js TAP npm pkg > should have expected pkg delete output 1`] = ` + +` + +exports[`smoke-tests/index.js TAP npm pkg > should have expected pkg get output 1`] = ` +"ISC" + +` + +exports[`smoke-tests/index.js TAP npm pkg > should have expected pkg set output 1`] = ` + +` + +exports[`smoke-tests/index.js TAP npm pkg > should print package.json contents 1`] = ` +{ + "name": "project", + "version": "1.0.0", + "description": "", + "ma", + "scripts": { + "test": "echo /"Error: no test specified/" && exit 1", + "hello": "echo Hello" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "abbrev": "^1.0.4" + }, + "tap": { + "test-env": [ + "LC_ALL=sk" + ] + } +} + +` + exports[`smoke-tests/index.js TAP npm prefix > should have expected prefix output 1`] = ` {CWD}/smoke-tests/tap-testdir-index/project diff --git a/deps/npm/tap-snapshots/test/lib/config.js.test.cjs b/deps/npm/tap-snapshots/test/lib/config.js.test.cjs index 84418ec2e81..a094bd32d56 100644 --- a/deps/npm/tap-snapshots/test/lib/config.js.test.cjs +++ b/deps/npm/tap-snapshots/test/lib/config.js.test.cjs @@ -5,7 +5,7 @@ * Make sure to inspect the output below. Do not ignore changes! */ 'use strict' -exports[`test/lib/config.js TAP config edit --global > should write global config file 1`] = ` +exports[`test/lib/config.js TAP config edit --location=global > should write global config file 1`] = ` ;;;; ; npm globalconfig file: /etc/npmrc ; this is a simple ini-formatted file @@ -92,8 +92,8 @@ cat = true chai = true dog = true editor = "vi" -global = false json = false +location = "user" long = false ; node bin location = /path/to/node @@ -116,8 +116,8 @@ cat = true chai = true dog = true editor = "vi" -global = false json = false +location = "user" long = true ` @@ -128,8 +128,8 @@ cat = true chai = true dog = true editor = "vi" -global = false json = false +location = "user" long = false ; node bin location = /path/to/node @@ -145,9 +145,9 @@ cat = true chai = true dog = true editor = "vi" -global = false init.author.name = "Bar" json = false +location = "user" long = false ; "user" config from ~/.npmrc diff --git a/deps/npm/tap-snapshots/test/lib/load-all-commands.js.test.cjs b/deps/npm/tap-snapshots/test/lib/load-all-commands.js.test.cjs index 3575783a644..8cf2e2837e2 100644 --- a/deps/npm/tap-snapshots/test/lib/load-all-commands.js.test.cjs +++ b/deps/npm/tap-snapshots/test/lib/load-all-commands.js.test.cjs @@ -84,7 +84,7 @@ Usage: npm bugs [<pkgname>] Options: -[--browser|--browser <browser>] [--registry <registry>] +[--no-browser|--browser <browser>] [--registry <registry>] alias: issues @@ -120,7 +120,7 @@ Usage: npm ci Options: -[--ignore-scripts] [--script-shell <script-shell>] +[--no-audit] [--ignore-scripts] [--script-shell <script-shell>] aliases: clean-install, ic, install-clean, isntall-clean @@ -151,7 +151,8 @@ npm config list [--json] npm config edit Options: -[--json] [-g|--global] [--editor <editor>] [-l|--long] +[--json] [-g|--global] [--editor <editor>] [-L|--location <global|user|project>] +[-l|--long] alias: c @@ -167,9 +168,9 @@ Usage: npm dedupe Options: -[--global-style] [--legacy-bundling] [--strict-peer-deps] [--package-lock] +[--global-style] [--legacy-bundling] [--strict-peer-deps] [--no-package-lock] [--omit <dev|optional|peer> [--omit <dev|optional|peer> ...]] [--ignore-scripts] -[--audit] [--bin-links] [--fund] [--dry-run] +[--no-audit] [--no-bin-links] [--no-fund] [--dry-run] [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces] @@ -239,7 +240,7 @@ Usage: npm docs [<pkgname> [<pkgname> ...]] Options: -[--browser|--browser <browser>] [--registry <registry>] +[--no-browser|--browser <browser>] [--registry <registry>] [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces] @@ -337,9 +338,9 @@ Usage: npm find-dupes Options: -[--global-style] [--legacy-bundling] [--strict-peer-deps] [--package-lock] +[--global-style] [--legacy-bundling] [--strict-peer-deps] [--no-package-lock] [--omit <dev|optional|peer> [--omit <dev|optional|peer> ...]] [--ignore-scripts] -[--audit] [--bin-links] [--fund] +[--no-audit] [--no-bin-links] [--no-fund] [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces] @@ -355,7 +356,7 @@ Usage: npm fund [[<@scope>/]<pkg>] Options: -[--json] [--browser|--browser <browser>] [--unicode] +[--json] [--no-browser|--browser <browser>] [--unicode] [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [--which <fundingSourceNumber>] @@ -446,9 +447,9 @@ npm install <github username>/<github project> Options: [-S|--save|--no-save|--save-prod|--save-dev|--save-optional|--save-peer] [-E|--save-exact] [-g|--global] [--global-style] [--legacy-bundling] -[--strict-peer-deps] [--package-lock] +[--strict-peer-deps] [--no-package-lock] [--omit <dev|optional|peer> [--omit <dev|optional|peer> ...]] [--ignore-scripts] -[--audit] [--bin-links] [--fund] [--dry-run] +[--no-audit] [--no-bin-links] [--no-fund] [--dry-run] [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces] @@ -466,7 +467,7 @@ Usage: npm install-ci-test Options: -[--ignore-scripts] [--script-shell <script-shell>] +[--no-audit] [--ignore-scripts] [--script-shell <script-shell>] alias: cit @@ -493,9 +494,9 @@ npm install-test <github username>/<github project> Options: [-S|--save|--no-save|--save-prod|--save-dev|--save-optional|--save-peer] [-E|--save-exact] [-g|--global] [--global-style] [--legacy-bundling] -[--strict-peer-deps] [--package-lock] +[--strict-peer-deps] [--no-package-lock] [--omit <dev|optional|peer> [--omit <dev|optional|peer> ...]] [--ignore-scripts] -[--audit] [--bin-links] [--fund] [--dry-run] +[--no-audit] [--no-bin-links] [--no-fund] [--dry-run] [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces] @@ -516,9 +517,9 @@ npm link [<@scope>/]<pkg>[@<version>] Options: [-S|--save|--no-save|--save-prod|--save-dev|--save-optional|--save-peer] [-E|--save-exact] [-g|--global] [--global-style] [--legacy-bundling] -[--strict-peer-deps] [--package-lock] +[--strict-peer-deps] [--no-package-lock] [--omit <dev|optional|peer> [--omit <dev|optional|peer> ...]] [--ignore-scripts] -[--audit] [--bin-links] [--fund] [--dry-run] +[--no-audit] [--no-bin-links] [--no-fund] [--dry-run] [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces] @@ -678,6 +679,24 @@ Options: Run "npm help ping" for more info ` +exports[`test/lib/load-all-commands.js TAP load each command pkg > must match snapshot 1`] = ` +npm pkg + +Manages your package.json + +Usage: +npm pkg set <key>=<value> [<key>=<value> ...] +npm pkg get [<key> [<key> ...]] +npm pkg delete <key> [<key> ...] + +Options: +[-f|--force] [--json] +[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] +[-ws|--workspaces] + +Run "npm help pkg" for more info +` + exports[`test/lib/load-all-commands.js TAP load each command prefix > must match snapshot 1`] = ` npm prefix @@ -750,7 +769,7 @@ Usage: npm rebuild [[<@scope>/]<name>[@<version>] ...] Options: -[-g|--global] [--bin-links] [--ignore-scripts] +[-g|--global] [--no-bin-links] [--ignore-scripts] [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces] @@ -768,7 +787,7 @@ Usage: npm repo [<pkgname> [<pkgname> ...]] Options: -[--browser|--browser <browser>] +[--no-browser|--browser <browser>] [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces] @@ -830,7 +849,7 @@ Usage: npm search [search terms ...] Options: -[-l|--long] [--json] [--color|--color <always>] [-p|--parseable] +[-l|--long] [--json] [--color|--no-color|--color always] [-p|--parseable] [--no-description] [--searchopts <searchopts>] [--searchexclude <searchexclude>] [--registry <registry>] [--prefer-online] [--prefer-offline] [--offline] @@ -1041,8 +1060,8 @@ npm update [<pkg>...] Options: [-g|--global] [--global-style] [--legacy-bundling] [--strict-peer-deps] -[--package-lock] [--omit <dev|optional|peer> [--omit <dev|optional|peer> ...]] -[--ignore-scripts] [--audit] [--bin-links] [--fund] [--dry-run] +[--no-package-lock] [--omit <dev|optional|peer> [--omit <dev|optional|peer> ...]] +[--ignore-scripts] [--no-audit] [--no-bin-links] [--no-fund] [--dry-run] [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces] @@ -1060,7 +1079,7 @@ Usage: npm version [<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease | from-git] Options: -[--allow-same-version] [--commit-hooks] [--git-tag-version] [--json] +[--allow-same-version] [--no-commit-hooks] [--no-git-tag-version] [--json] [--preid prerelease-id] [--sign-git-tag] [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces] diff --git a/deps/npm/tap-snapshots/test/lib/utils/cmd-list.js.test.cjs b/deps/npm/tap-snapshots/test/lib/utils/cmd-list.js.test.cjs index 832f8560125..97158079204 100644 --- a/deps/npm/tap-snapshots/test/lib/utils/cmd-list.js.test.cjs +++ b/deps/npm/tap-snapshots/test/lib/utils/cmd-list.js.test.cjs @@ -158,6 +158,7 @@ Object { "diff", "dist-tag", "ping", + "pkg", "test", "stop", "start", diff --git a/deps/npm/tap-snapshots/test/lib/utils/config/definitions.js.test.cjs b/deps/npm/tap-snapshots/test/lib/utils/config/definitions.js.test.cjs index 12df9ec89f6..01b137b8af5 100644 --- a/deps/npm/tap-snapshots/test/lib/utils/config/definitions.js.test.cjs +++ b/deps/npm/tap-snapshots/test/lib/utils/config/definitions.js.test.cjs @@ -81,6 +81,7 @@ Array [ "legacy-peer-deps", "link", "local-address", + "location", "loglevel", "logs-max", "long", @@ -218,9 +219,10 @@ exports[`test/lib/utils/config/definitions.js TAP > config description for 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. +When "true" submit audit reports alongside the current npm command 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. ` exports[`test/lib/utils/config/definitions.js TAP > config description for audit-level 1`] = ` @@ -648,6 +650,7 @@ mistakes, unnecessary performance degradation, and malicious input. * Allow unpublishing all versions of a published package. * Allow conflicting peerDependencies to be installed in the root project. * Implicitly set \`--yes\` during \`npm init\`. +* Allow clobbering existing values in \`npm pkg\` 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! @@ -949,6 +952,9 @@ exports[`test/lib/utils/config/definitions.js TAP > config description for json Whether or not to output JSON data, rather than the normal output. +* In \`npm pkg set\` it enables parsing set values with JSON.parse() before + saving them to your \`package.json\`. + Not supported by all npm commands. ` @@ -1019,6 +1025,16 @@ 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. ` +exports[`test/lib/utils/config/definitions.js TAP > config description for location 1`] = ` +#### \`location\` + +* Default: "user" unless \`--global\` is passed, which will also set this value + to "global" +* Type: "global", "user", or "project" + +When passed to \`npm config\` this refers to which config file to use. +` + exports[`test/lib/utils/config/definitions.js TAP > config description for loglevel 1`] = ` #### \`loglevel\` diff --git a/deps/npm/tap-snapshots/test/lib/utils/config/describe-all.js.test.cjs b/deps/npm/tap-snapshots/test/lib/utils/config/describe-all.js.test.cjs index daa071b642e..8487b45174c 100644 --- a/deps/npm/tap-snapshots/test/lib/utils/config/describe-all.js.test.cjs +++ b/deps/npm/tap-snapshots/test/lib/utils/config/describe-all.js.test.cjs @@ -49,9 +49,10 @@ to the same value as the current version. * 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. +When "true" submit audit reports alongside the current npm command 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\` @@ -374,6 +375,7 @@ mistakes, unnecessary performance degradation, and malicious input. * Allow unpublishing all versions of a published package. * Allow conflicting peerDependencies to be installed in the root project. * Implicitly set \`--yes\` during \`npm init\`. +* Allow clobbering existing values in \`npm pkg\` 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! @@ -573,6 +575,9 @@ number, if not already set in package.json. Whether or not to output JSON data, rather than the normal output. +* In \`npm pkg set\` it enables parsing set values with JSON.parse() before + saving them to your \`package.json\`. + Not supported by all npm commands. #### \`key\` @@ -632,6 +637,14 @@ Used with \`npm ls\`, limiting output to only those packages that are linked. 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. +#### \`location\` + +* Default: "user" unless \`--global\` is passed, which will also set this value + to "global" +* Type: "global", "user", or "project" + +When passed to \`npm config\` this refers to which config file to use. + #### \`loglevel\` * Default: "notice" diff --git a/deps/npm/tap-snapshots/test/lib/utils/config/index.js.test.cjs b/deps/npm/tap-snapshots/test/lib/utils/config/index.js.test.cjs index 1e5ca232452..f1cba9264ee 100644 --- a/deps/npm/tap-snapshots/test/lib/utils/config/index.js.test.cjs +++ b/deps/npm/tap-snapshots/test/lib/utils/config/index.js.test.cjs @@ -64,6 +64,9 @@ Object { "l": Array [ "--long", ], + "L": Array [ + "--location", + ], "local": Array [ "--no-global", ], diff --git a/deps/npm/tap-snapshots/test/lib/utils/error-message.js.test.cjs b/deps/npm/tap-snapshots/test/lib/utils/error-message.js.test.cjs index 7b02dbd9aaa..8adb33c395d 100644 --- a/deps/npm/tap-snapshots/test/lib/utils/error-message.js.test.cjs +++ b/deps/npm/tap-snapshots/test/lib/utils/error-message.js.test.cjs @@ -1289,6 +1289,29 @@ Object { } ` +exports[`test/lib/utils/error-message.js TAP just simple messages > must match snapshot 23`] = ` +Object { + "detail": Array [ + Array [ + "network", + String( + This is a problem related to network connectivity. + In most cases you are behind a proxy or have bad network settings. + + If you are behind a proxy, please make sure that the + 'proxy' config is set properly. See: 'npm help config' + ), + ], + ], + "summary": Array [ + Array [ + "network", + "foo", + ], + ], +} +` + exports[`test/lib/utils/error-message.js TAP just simple messages > must match snapshot 3`] = ` Object { "detail": Array [ diff --git a/deps/npm/tap-snapshots/test/lib/utils/exit-handler.js.test.cjs b/deps/npm/tap-snapshots/test/lib/utils/exit-handler.js.test.cjs index 8cea8ee17e5..eb383c104a6 100644 --- a/deps/npm/tap-snapshots/test/lib/utils/exit-handler.js.test.cjs +++ b/deps/npm/tap-snapshots/test/lib/utils/exit-handler.js.test.cjs @@ -6,15 +6,15 @@ */ 'use strict' exports[`test/lib/utils/exit-handler.js TAP handles unknown error > should have expected log contents for unknown error 1`] = ` -0 verbose stack Error: ERROR -1 verbose cwd {CWD} -2 verbose Foo 1.0.0 -3 verbose argv "/node" "{CWD}/test/lib/utils/exit-handler.js" -4 verbose node v1.0.0 -5 verbose npm v1.0.0 -6 error foo code ERROR -7 error foo ERR ERROR -8 error foo ERR ERROR -9 verbose exit 1 +24 verbose stack Error: ERROR +25 verbose cwd {CWD} +26 verbose Foo 1.0.0 +27 verbose argv "/node" "{CWD}/test/lib/utils/exit-handler.js" +28 verbose node v1.0.0 +29 verbose npm v1.0.0 +30 error code ERROR +31 error ERR ERROR +32 error ERR ERROR +33 verbose exit 1 ` diff --git a/deps/npm/tap-snapshots/test/lib/utils/npm-usage.js.test.cjs b/deps/npm/tap-snapshots/test/lib/utils/npm-usage.js.test.cjs index 3987f6a732d..17df1aa1f58 100644 --- a/deps/npm/tap-snapshots/test/lib/utils/npm-usage.js.test.cjs +++ b/deps/npm/tap-snapshots/test/lib/utils/npm-usage.js.test.cjs @@ -26,10 +26,10 @@ All commands: 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 + pkg, 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 @@ -62,10 +62,10 @@ All commands: 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 + pkg, 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 @@ -98,10 +98,10 @@ All commands: 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 + pkg, 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 @@ -134,10 +134,10 @@ All commands: 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 + pkg, 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 @@ -235,7 +235,7 @@ All commands: npm bugs [<pkgname>] Options: - [--browser|--browser <browser>] [--registry <registry>] + [--no-browser|--browser <browser>] [--registry <registry>] alias: issues @@ -267,7 +267,7 @@ All commands: npm ci Options: - [--ignore-scripts] [--script-shell <script-shell>] + [--no-audit] [--ignore-scripts] [--script-shell <script-shell>] aliases: clean-install, ic, install-clean, isntall-clean @@ -294,7 +294,8 @@ All commands: npm config edit Options: - [--json] [-g|--global] [--editor <editor>] [-l|--long] + [--json] [-g|--global] [--editor <editor>] [-L|--location <global|user|project>] + [-l|--long] alias: c @@ -308,9 +309,9 @@ All commands: npm dedupe Options: - [--global-style] [--legacy-bundling] [--strict-peer-deps] [--package-lock] + [--global-style] [--legacy-bundling] [--strict-peer-deps] [--no-package-lock] [--omit <dev|optional|peer> [--omit <dev|optional|peer> ...]] [--ignore-scripts] - [--audit] [--bin-links] [--fund] [--dry-run] + [--no-audit] [--no-bin-links] [--no-fund] [--dry-run] [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces] @@ -372,7 +373,7 @@ All commands: npm docs [<pkgname> [<pkgname> ...]] Options: - [--browser|--browser <browser>] [--registry <registry>] + [--no-browser|--browser <browser>] [--registry <registry>] [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces] @@ -458,9 +459,9 @@ All commands: npm find-dupes Options: - [--global-style] [--legacy-bundling] [--strict-peer-deps] [--package-lock] + [--global-style] [--legacy-bundling] [--strict-peer-deps] [--no-package-lock] [--omit <dev|optional|peer> [--omit <dev|optional|peer> ...]] [--ignore-scripts] - [--audit] [--bin-links] [--fund] + [--no-audit] [--no-bin-links] [--no-fund] [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces] @@ -474,7 +475,7 @@ All commands: npm fund [[<@scope>/]<pkg>] Options: - [--json] [--browser|--browser <browser>] [--unicode] + [--json] [--no-browser|--browser <browser>] [--unicode] [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [--which <fundingSourceNumber>] @@ -555,9 +556,9 @@ All commands: Options: [-S|--save|--no-save|--save-prod|--save-dev|--save-optional|--save-peer] [-E|--save-exact] [-g|--global] [--global-style] [--legacy-bundling] - [--strict-peer-deps] [--package-lock] + [--strict-peer-deps] [--no-package-lock] [--omit <dev|optional|peer> [--omit <dev|optional|peer> ...]] [--ignore-scripts] - [--audit] [--bin-links] [--fund] [--dry-run] + [--no-audit] [--no-bin-links] [--no-fund] [--dry-run] [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces] @@ -573,7 +574,7 @@ All commands: npm install-ci-test Options: - [--ignore-scripts] [--script-shell <script-shell>] + [--no-audit] [--ignore-scripts] [--script-shell <script-shell>] alias: cit @@ -598,9 +599,9 @@ All commands: Options: [-S|--save|--no-save|--save-prod|--save-dev|--save-optional|--save-peer] [-E|--save-exact] [-g|--global] [--global-style] [--legacy-bundling] - [--strict-peer-deps] [--package-lock] + [--strict-peer-deps] [--no-package-lock] [--omit <dev|optional|peer> [--omit <dev|optional|peer> ...]] [--ignore-scripts] - [--audit] [--bin-links] [--fund] [--dry-run] + [--no-audit] [--no-bin-links] [--no-fund] [--dry-run] [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces] @@ -619,9 +620,9 @@ All commands: Options: [-S|--save|--no-save|--save-prod|--save-dev|--save-optional|--save-peer] [-E|--save-exact] [-g|--global] [--global-style] [--legacy-bundling] - [--strict-peer-deps] [--package-lock] + [--strict-peer-deps] [--no-package-lock] [--omit <dev|optional|peer> [--omit <dev|optional|peer> ...]] [--ignore-scripts] - [--audit] [--bin-links] [--fund] [--dry-run] + [--no-audit] [--no-bin-links] [--no-fund] [--dry-run] [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces] @@ -762,6 +763,22 @@ All commands: Run "npm help ping" for more info + pkg npm pkg + + Manages your package.json + + Usage: + npm pkg set <key>=<value> [<key>=<value> ...] + npm pkg get [<key> [<key> ...]] + npm pkg delete <key> [<key> ...] + + Options: + [-f|--force] [--json] + [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] + [-ws|--workspaces] + + Run "npm help pkg" for more info + prefix npm prefix Display prefix @@ -825,7 +842,7 @@ All commands: npm rebuild [[<@scope>/]<name>[@<version>] ...] Options: - [-g|--global] [--bin-links] [--ignore-scripts] + [-g|--global] [--no-bin-links] [--ignore-scripts] [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces] @@ -841,7 +858,7 @@ All commands: npm repo [<pkgname> [<pkgname> ...]] Options: - [--browser|--browser <browser>] + [--no-browser|--browser <browser>] [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces] @@ -895,7 +912,7 @@ All commands: npm search [search terms ...] Options: - [-l|--long] [--json] [--color|--color <always>] [-p|--parseable] + [-l|--long] [--json] [--color|--no-color|--color always] [-p|--parseable] [--no-description] [--searchopts <searchopts>] [--searchexclude <searchexclude>] [--registry <registry>] [--prefer-online] [--prefer-offline] [--offline] @@ -1078,8 +1095,8 @@ All commands: Options: [-g|--global] [--global-style] [--legacy-bundling] [--strict-peer-deps] - [--package-lock] [--omit <dev|optional|peer> [--omit <dev|optional|peer> ...]] - [--ignore-scripts] [--audit] [--bin-links] [--fund] [--dry-run] + [--no-package-lock] [--omit <dev|optional|peer> [--omit <dev|optional|peer> ...]] + [--ignore-scripts] [--no-audit] [--no-bin-links] [--no-fund] [--dry-run] [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces] @@ -1095,7 +1112,7 @@ All commands: npm version [<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease | from-git] Options: - [--allow-same-version] [--commit-hooks] [--git-tag-version] [--json] + [--allow-same-version] [--no-commit-hooks] [--no-git-tag-version] [--json] [--preid prerelease-id] [--sign-git-tag] [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces] diff --git a/deps/npm/tap-snapshots/test/lib/utils/update-notifier.js.test.cjs b/deps/npm/tap-snapshots/test/lib/utils/update-notifier.js.test.cjs index 91228650d47..157390997d7 100644 --- a/deps/npm/tap-snapshots/test/lib/utils/update-notifier.js.test.cjs +++ b/deps/npm/tap-snapshots/test/lib/utils/update-notifier.js.test.cjs @@ -6,11 +6,11 @@ */ 'use strict' exports[`test/lib/utils/update-notifier.js TAP notification situations major to current > color 1`] = ` -[40m[37m[39m[49m -[40m[37mNew [31mmajor[39m[37m version of npm available! [31m122.420.69[39m[37m -> [32m123.420.69[39m[37m[39m[49m -[40m[37mChangelog: [36mhttps://github.com/npm/cli/releases/tag/v123.420.69[39m[37m[39m[49m -[40m[37mRun [32mnpm install -g npm@123.420.69[39m[37m to update![39m[49m -[40m[37m[39m[49m + +New [31mmajor[39m version of npm available! [31m122.420.69[39m -> [32m123.420.69[39m +Changelog: [36mhttps://github.com/npm/cli/releases/tag/v123.420.69[39m +Run [32mnpm install -g npm@123.420.69[39m to update! + ` exports[`test/lib/utils/update-notifier.js TAP notification situations major to current > no color 1`] = ` @@ -22,11 +22,11 @@ Run \`npm install -g npm@123.420.69\` to update! ` exports[`test/lib/utils/update-notifier.js TAP notification situations minor to current > color 1`] = ` -[40m[37m[39m[49m -[40m[37mNew [33mminor[39m[37m version of npm available! [31m123.419.69[39m[37m -> [32m123.420.69[39m[37m[39m[49m -[40m[37mChangelog: [36mhttps://github.com/npm/cli/releases/tag/v123.420.69[39m[37m[39m[49m -[40m[37mRun [32mnpm install -g npm@123.420.69[39m[37m to update![39m[49m -[40m[37m[39m[49m + +New [33mminor[39m version of npm available! [31m123.419.69[39m -> [32m123.420.69[39m +Changelog: [36mhttps://github.com/npm/cli/releases/tag/v123.420.69[39m +Run [32mnpm install -g npm@123.420.69[39m to update! + ` exports[`test/lib/utils/update-notifier.js TAP notification situations minor to current > no color 1`] = ` @@ -38,11 +38,11 @@ Run \`npm install -g npm@123.420.69\` to update! ` exports[`test/lib/utils/update-notifier.js TAP notification situations minor to next version > color 1`] = ` -[40m[37m[39m[49m -[40m[37mNew [33mminor[39m[37m version of npm available! [31m123.420.70[39m[37m -> [32m123.421.70[39m[37m[39m[49m -[40m[37mChangelog: [36mhttps://github.com/npm/cli/releases/tag/v123.421.70[39m[37m[39m[49m -[40m[37mRun [32mnpm install -g npm@123.421.70[39m[37m to update![39m[49m -[40m[37m[39m[49m + +New [33mminor[39m version of npm available! [31m123.420.70[39m -> [32m123.421.70[39m +Changelog: [36mhttps://github.com/npm/cli/releases/tag/v123.421.70[39m +Run [32mnpm install -g npm@123.421.70[39m to update! + ` exports[`test/lib/utils/update-notifier.js TAP notification situations minor to next version > no color 1`] = ` @@ -54,11 +54,11 @@ Run \`npm install -g npm@123.421.70\` to update! ` exports[`test/lib/utils/update-notifier.js TAP notification situations new beta available > color 1`] = ` -[40m[37m[39m[49m -[40m[37mNew [32mprerelease[39m[37m version of npm available! [31m124.0.0-beta.0[39m[37m -> [32m124.0.0-beta.99999[39m[37m[39m[49m -[40m[37mChangelog: [36mhttps://github.com/npm/cli/releases/tag/v124.0.0-beta.99999[39m[37m[39m[49m -[40m[37mRun [32mnpm install -g npm@124.0.0-beta.99999[39m[37m to update![39m[49m -[40m[37m[39m[49m + +New [32mprerelease[39m version of npm available! [31m124.0.0-beta.0[39m -> [32m124.0.0-beta.99999[39m +Changelog: [36mhttps://github.com/npm/cli/releases/tag/v124.0.0-beta.99999[39m +Run [32mnpm install -g npm@124.0.0-beta.99999[39m to update! + ` exports[`test/lib/utils/update-notifier.js TAP notification situations new beta available > no color 1`] = ` @@ -70,11 +70,11 @@ Run \`npm install -g npm@124.0.0-beta.99999\` to update! ` exports[`test/lib/utils/update-notifier.js TAP notification situations patch to current > color 1`] = ` -[40m[37m[39m[49m -[40m[37mNew [32mpatch[39m[37m version of npm available! [31m123.420.68[39m[37m -> [32m123.420.69[39m[37m[39m[49m -[40m[37mChangelog: [36mhttps://github.com/npm/cli/releases/tag/v123.420.69[39m[37m[39m[49m -[40m[37mRun [32mnpm install -g npm@123.420.69[39m[37m to update![39m[49m -[40m[37m[39m[49m + +New [32mpatch[39m version of npm available! [31m123.420.68[39m -> [32m123.420.69[39m +Changelog: [36mhttps://github.com/npm/cli/releases/tag/v123.420.69[39m +Run [32mnpm install -g npm@123.420.69[39m to update! + ` exports[`test/lib/utils/update-notifier.js TAP notification situations patch to current > no color 1`] = ` @@ -86,11 +86,11 @@ Run \`npm install -g npm@123.420.69\` to update! ` exports[`test/lib/utils/update-notifier.js TAP notification situations patch to next version > color 1`] = ` -[40m[37m[39m[49m -[40m[37mNew [32mpatch[39m[37m version of npm available! [31m123.421.69[39m[37m -> [32m123.421.70[39m[37m[39m[49m -[40m[37mChangelog: [36mhttps://github.com/npm/cli/releases/tag/v123.421.70[39m[37m[39m[49m -[40m[37mRun [32mnpm install -g npm@123.421.70[39m[37m to update![39m[49m -[40m[37m[39m[49m + +New [32mpatch[39m version of npm available! [31m123.421.69[39m -> [32m123.421.70[39m +Changelog: [36mhttps://github.com/npm/cli/releases/tag/v123.421.70[39m +Run [32mnpm install -g npm@123.421.70[39m to update! + ` exports[`test/lib/utils/update-notifier.js TAP notification situations patch to next version > no color 1`] = ` diff --git a/deps/npm/test/fixtures/mock-npm.js b/deps/npm/test/fixtures/mock-npm.js index 1de080eb10b..e3be10b4b9a 100644 --- a/deps/npm/test/fixtures/mock-npm.js +++ b/deps/npm/test/fixtures/mock-npm.js @@ -1,20 +1,19 @@ const npmlog = require('npmlog') -const perf = require('../../lib/utils/perf.js') -perf.reset() const procLog = require('../../lib/utils/proc-log-listener.js') procLog.reset() const realLog = {} -for (const level of ['silly', 'verbose', 'timing', 'notice', 'warn', 'error']) +for (const level in npmlog.levels) realLog[level] = npmlog[level] const { title, execPath } = process const RealMockNpm = (t, otherMocks = {}) => { t.teardown(() => { - for (const level of ['silly', 'verbose', 'timing', 'notice', 'warn', 'error']) + npm.perfStop() + npmlog.record.length = 0 + for (const level in npmlog.levels) npmlog[level] = realLog[level] - perf.reset() procLog.reset() process.title = title process.execPath = execPath @@ -33,9 +32,14 @@ const RealMockNpm = (t, otherMocks = {}) => { }) }) } - for (const level of ['silly', 'verbose', 'timing', 'notice', 'warn', 'error']) { + for (const level in npmlog.levels) { npmlog[level] = (...msg) => { logs.push([level, ...msg]) + + const l = npmlog.level + npmlog.level = 'silent' + realLog[level](...msg) + npmlog.level = l } } npm.output = (...msg) => outputs.push(msg) diff --git a/deps/npm/test/lib/config.js b/deps/npm/test/lib/config.js index 6c04293137a..8a1e7d85e09 100644 --- a/deps/npm/test/lib/config.js +++ b/deps/npm/test/lib/config.js @@ -47,8 +47,8 @@ const defaults = { const cliConfig = { editor: 'vi', json: false, + location: 'user', long: false, - global: false, cat: true, chai: true, dog: true, @@ -198,8 +198,8 @@ t.test('config list --json', t => { { editor: 'vi', json: true, + location: 'user', long: false, - global: false, cat: true, chai: true, dog: true, @@ -265,7 +265,7 @@ t.test('config delete multiple key', t => { }) }) -t.test('config delete key --global', t => { +t.test('config delete key --location=global', t => { t.plan(4) npm.config.delete = (key, where) => { @@ -277,13 +277,13 @@ t.test('config delete key --global', t => { t.equal(where, 'global', 'should save global config post-delete') } - cliConfig.global = true + cliConfig.location = 'global' config.exec(['delete', 'foo'], (err) => { - t.error(err, 'npm config delete key --global') + t.error(err, 'npm config delete key --location=global') }) t.teardown(() => { - cliConfig.global = false + cliConfig.location = 'user' delete npm.config.delete delete npm.config.save }) @@ -419,7 +419,7 @@ t.test('config set invalid key', t => { }) }) -t.test('config set key --global', t => { +t.test('config set key --location=global', t => { t.plan(5) npm.config.set = (key, val, where) => { @@ -432,13 +432,13 @@ t.test('config set key --global', t => { t.equal(where, 'global', 'should save global config') } - cliConfig.global = true + cliConfig.location = 'global' config.exec(['set', 'foo', 'bar'], (err) => { - t.error(err, 'npm config set key --global') + t.error(err, 'npm config set key --location=global') }) t.teardown(() => { - cliConfig.global = false + cliConfig.location = 'user' delete npm.config.set delete npm.config.save }) @@ -583,10 +583,10 @@ sign-git-commit=true` }) }) -t.test('config edit --global', t => { +t.test('config edit --location=global', t => { t.plan(6) - cliConfig.global = true + cliConfig.location = 'global' const npmrc = 'init.author.name=Foo' npm.config.data.set('global', { source: '/etc/npmrc', @@ -626,7 +626,7 @@ t.test('config edit --global', t => { }) t.teardown(() => { - cliConfig.global = false + cliConfig.location = 'user' npm.config.data.delete('user') delete npm.config.save }) diff --git a/deps/npm/test/lib/link.js b/deps/npm/test/lib/link.js index 736d18cab99..96f689892ff 100644 --- a/deps/npm/test/lib/link.js +++ b/deps/npm/test/lib/link.js @@ -30,7 +30,7 @@ const printLinks = async (opts) => { const linkedItems = [...tree.inventory.values()] .sort((a, b) => a.pkgid.localeCompare(b.pkgid, 'en')) for (const item of linkedItems) { - if (item.target) + if (item.isLink) res += `${item.path} -> ${item.target.path}\n` } return res diff --git a/deps/npm/test/lib/npm.js b/deps/npm/test/lib/npm.js index 291a58955ce..03bb46d8d84 100644 --- a/deps/npm/test/lib/npm.js +++ b/deps/npm/test/lib/npm.js @@ -476,3 +476,28 @@ t.test('set process.title', t => { t.end() }) + +t.test('timings', t => { + const { npm, logs } = mockNpm(t) + process.emit('time', 'foo') + process.emit('time', 'bar') + t.match(npm.timers.get('foo'), Number, 'foo timer is a number') + t.match(npm.timers.get('bar'), Number, 'foo timer is a number') + process.emit('timeEnd', 'foo') + process.emit('timeEnd', 'bar') + process.emit('timeEnd', 'baz') + t.match(logs, [ + ['timing', 'foo', /Completed in [0-9]+ms/], + ['timing', 'bar', /Completed in [0-9]+ms/], + [ + 'silly', + 'timing', + "Tried to end timer that doesn't exist:", + 'baz', + ], + ]) + t.notOk(npm.timers.has('foo'), 'foo timer is gone') + t.notOk(npm.timers.has('bar'), 'bar timer is gone') + t.match(npm.timings, { foo: Number, bar: Number }) + t.end() +}) diff --git a/deps/npm/test/lib/pkg.js b/deps/npm/test/lib/pkg.js new file mode 100644 index 00000000000..688df685905 --- /dev/null +++ b/deps/npm/test/lib/pkg.js @@ -0,0 +1,737 @@ +const { resolve } = require('path') +const { readFileSync } = require('fs') +const t = require('tap') +const { fake: mockNpm } = require('../fixtures/mock-npm') + +const redactCwd = (path) => { + const normalizePath = p => p + .replace(/\\+/g, '/') + .replace(/\r\n/g, '\n') + return normalizePath(path) + .replace(new RegExp(normalizePath(process.cwd()), 'g'), '{CWD}') +} + +t.cleanSnapshot = (str) => redactCwd(str) + +let OUTPUT = '' +const config = { + global: false, + force: false, + 'pkg-cast': 'string', +} +const npm = mockNpm({ + localPrefix: t.testdirName, + config, + output: (str) => { + OUTPUT += str + }, +}) + +const Pkg = require('../../lib/pkg.js') +const pkg = new Pkg(npm) + +const readPackageJson = (path) => { + path = path || npm.localPrefix + return JSON.parse(readFileSync(resolve(path, 'package.json'), 'utf8')) +} + +t.afterEach(() => { + config.global = false + config.json = false + npm.localPrefix = t.testdirName + OUTPUT = '' +}) + +t.test('no args', t => { + pkg.exec([], err => { + t.match( + err, + { code: 'EUSAGE' }, + 'should throw usage error' + ) + t.end() + }) +}) + +t.test('no global mode', t => { + config.global = true + pkg.exec(['get', 'foo'], err => { + t.match( + err, + { code: 'EPKGGLOBAL' }, + 'should throw no global mode error' + ) + t.end() + }) +}) + +t.test('get no args', t => { + npm.localPrefix = t.testdir({ + 'package.json': JSON.stringify({ + name: 'foo', + version: '1.1.1', + }), + }) + + pkg.exec(['get'], err => { + if (err) + throw err + + t.strictSame( + JSON.parse(OUTPUT), + { + name: 'foo', + version: '1.1.1', + }, + 'should print package.json content' + ) + t.end() + }) +}) + +t.test('get single arg', t => { + npm.localPrefix = t.testdir({ + 'package.json': JSON.stringify({ + name: 'foo', + version: '1.1.1', + }), + }) + + pkg.exec(['get', 'version'], err => { + if (err) + throw err + + t.strictSame( + JSON.parse(OUTPUT), + '1.1.1', + 'should print retrieved package.json field' + ) + t.end() + }) +}) + +t.test('get nested arg', t => { + npm.localPrefix = t.testdir({ + 'package.json': JSON.stringify({ + name: 'foo', + version: '1.1.1', + scripts: { + test: 'node test.js', + }, + }), + }) + + pkg.exec(['get', 'scripts.test'], err => { + if (err) + throw err + + t.strictSame( + JSON.parse(OUTPUT), + 'node test.js', + 'should print retrieved nested field' + ) + t.end() + }) +}) + +t.test('get array field', t => { + const files = [ + 'index.js', + 'cli.js', + ] + npm.localPrefix = t.testdir({ + 'package.json': JSON.stringify({ + name: 'foo', + version: '1.1.1', + files, + }), + }) + + pkg.exec(['get', 'files'], err => { + if (err) + throw err + + t.strictSame( + JSON.parse(OUTPUT), + files, + 'should print retrieved array field' + ) + t.end() + }) +}) + +t.test('get array item', t => { + const files = [ + 'index.js', + 'cli.js', + ] + npm.localPrefix = t.testdir({ + 'package.json': JSON.stringify({ + name: 'foo', + version: '1.1.1', + files, + }), + }) + + pkg.exec(['get', 'files[0]'], err => { + if (err) + throw err + + t.strictSame( + JSON.parse(OUTPUT), + 'index.js', + 'should print retrieved array field' + ) + t.end() + }) +}) + +t.test('get array nested items notation', t => { + const contributors = [ + { + name: 'Ruy', + url: 'http://example.com/ruy', + }, + { + name: 'Gar', + url: 'http://example.com/gar', + }, + ] + npm.localPrefix = t.testdir({ + 'package.json': JSON.stringify({ + name: 'foo', + version: '1.1.1', + contributors, + }), + }) + + pkg.exec(['get', 'contributors.name'], err => { + if (err) + throw err + + t.strictSame( + JSON.parse(OUTPUT), + { + 'contributors[0].name': 'Ruy', + 'contributors[1].name': 'Gar', + }, + 'should print json result containing matching results' + ) + t.end() + }) +}) + +t.test('set no args', t => { + npm.localPrefix = t.testdir({ + 'package.json': JSON.stringify({ name: 'foo' }), + }) + pkg.exec(['set'], err => { + t.match( + err, + { code: 'EPKGSET' }, + 'should throw an error if no args' + ) + + t.end() + }) +}) + +t.test('set missing value', t => { + npm.localPrefix = t.testdir({ + 'package.json': JSON.stringify({ name: 'foo' }), + }) + pkg.exec(['set', 'key='], err => { + t.match( + err, + { code: 'EPKGSET' }, + 'should throw an error if missing value' + ) + + t.end() + }) +}) + +t.test('set missing key', t => { + npm.localPrefix = t.testdir({ + 'package.json': JSON.stringify({ name: 'foo' }), + }) + pkg.exec(['set', '=value'], err => { + t.match( + err, + { code: 'EPKGSET' }, + 'should throw an error if missing key' + ) + + t.end() + }) +}) + +t.test('set single field', t => { + const json = { + name: 'foo', + version: '1.1.1', + } + npm.localPrefix = t.testdir({ + 'package.json': JSON.stringify(json), + }) + + pkg.exec(['set', 'description=Awesome stuff'], err => { + if (err) + throw err + + t.strictSame( + readPackageJson(), + { + ...json, + description: 'Awesome stuff', + }, + 'should add single field to package.json' + ) + t.end() + }) +}) + +t.test('push to array syntax', t => { + const json = { + name: 'foo', + version: '1.1.1', + keywords: [ + 'foo', + ], + } + npm.localPrefix = t.testdir({ + 'package.json': JSON.stringify(json), + }) + + pkg.exec(['set', 'keywords[]=bar', 'keywords[]=baz'], err => { + if (err) + throw err + + t.strictSame( + readPackageJson(), + { + ...json, + keywords: [ + 'foo', + 'bar', + 'baz', + ], + }, + 'should append to arrays using empty bracket syntax' + ) + t.end() + }) +}) + +t.test('set multiple fields', t => { + const json = { + name: 'foo', + version: '1.1.1', + } + npm.localPrefix = t.testdir({ + 'package.json': JSON.stringify(json), + }) + + pkg.exec(['set', 'bin.foo=foo.js', 'scripts.test=node test.js'], err => { + if (err) + throw err + + t.strictSame( + readPackageJson(), + { + ...json, + bin: { + foo: 'foo.js', + }, + scripts: { + test: 'node test.js', + }, + }, + 'should add single field to package.json' + ) + t.end() + }) +}) + +t.test('set = separate value', t => { + const json = { + name: 'foo', + version: '1.1.1', + } + npm.localPrefix = t.testdir({ + 'package.json': JSON.stringify(json), + }) + + pkg.exec(['set', 'tap[test-env][0]=LC_ALL=sk'], err => { + if (err) + throw err + + t.strictSame( + readPackageJson(), + { + ...json, + tap: { + 'test-env': [ + 'LC_ALL=sk', + ], + }, + }, + 'should add single field to package.json' + ) + t.end() + }) +}) + +t.test('set --json', async t => { + config.json = true + npm.localPrefix = t.testdir({ + 'package.json': JSON.stringify({ + name: 'foo', + version: '1.1.1', + }), + }) + + await new Promise((res, rej) => { + pkg.exec(['set', 'private=true'], err => { + if (err) + rej(err) + + t.strictSame( + readPackageJson(), + { + name: 'foo', + version: '1.1.1', + private: true, + }, + 'should add boolean field to package.json' + ) + res() + }) + }) + + await new Promise((res, rej) => { + pkg.exec(['set', 'tap.timeout=60'], err => { + if (err) + rej(err) + + t.strictSame( + readPackageJson(), + { + name: 'foo', + version: '1.1.1', + private: true, + tap: { + timeout: 60, + }, + }, + 'should add number field to package.json' + ) + res() + }) + }) + + await new Promise((res, rej) => { + pkg.exec(['set', 'foo={ "bar": { "baz": "BAZ" } }'], err => { + if (err) + rej(err) + + t.strictSame( + readPackageJson(), + { + name: 'foo', + version: '1.1.1', + private: true, + tap: { + timeout: 60, + }, + foo: { + bar: { + baz: 'BAZ', + }, + }, + }, + 'should add object field to package.json' + ) + res() + }) + }) + + await new Promise((res, rej) => { + pkg.exec(['set', 'workspaces=["packages/*"]'], err => { + if (err) + rej(err) + + t.strictSame( + readPackageJson(), + { + name: 'foo', + version: '1.1.1', + private: true, + workspaces: [ + 'packages/*', + ], + tap: { + timeout: 60, + }, + foo: { + bar: { + baz: 'BAZ', + }, + }, + }, + 'should add object field to package.json' + ) + res() + }) + }) + + await new Promise((res, rej) => { + pkg.exec(['set', 'description="awesome"'], err => { + if (err) + rej(err) + + t.strictSame( + readPackageJson(), + { + name: 'foo', + version: '1.1.1', + description: 'awesome', + private: true, + workspaces: [ + 'packages/*', + ], + tap: { + timeout: 60, + }, + foo: { + bar: { + baz: 'BAZ', + }, + }, + }, + 'should add object field to package.json' + ) + res() + }) + }) +}) + +t.test('delete no args', t => { + npm.localPrefix = t.testdir({ + 'package.json': JSON.stringify({ name: 'foo' }), + }) + pkg.exec(['delete'], err => { + t.match( + err, + { code: 'EPKGDELETE' }, + 'should throw an error if deleting no args' + ) + + t.end() + }) +}) + +t.test('delete invalid key', t => { + npm.localPrefix = t.testdir({ + 'package.json': JSON.stringify({ name: 'foo' }), + }) + pkg.exec(['delete', ''], err => { + t.match( + err, + { code: 'EPKGDELETE' }, + 'should throw an error if deleting invalid args' + ) + + t.end() + }) +}) + +t.test('delete single field', t => { + npm.localPrefix = t.testdir({ + 'package.json': JSON.stringify({ + name: 'foo', + version: '1.0.0', + }), + }) + pkg.exec(['delete', 'version'], err => { + if (err) + throw err + + t.strictSame( + readPackageJson(), + { + name: 'foo', + }, + 'should delete single field from package.json' + ) + + t.end() + }) +}) + +t.test('delete multiple field', t => { + npm.localPrefix = t.testdir({ + 'package.json': JSON.stringify({ + name: 'foo', + version: '1.0.0', + description: 'awesome', + }), + }) + pkg.exec(['delete', 'version', 'description'], err => { + if (err) + throw err + + t.strictSame( + readPackageJson(), + { + name: 'foo', + }, + 'should delete multiple fields from package.json' + ) + + t.end() + }) +}) + +t.test('delete nested field', t => { + npm.localPrefix = t.testdir({ + 'package.json': JSON.stringify({ + name: 'foo', + version: '1.0.0', + info: { + foo: { + bar: [ + { + baz: 'deleteme', + }, + ], + }, + }, + }), + }) + pkg.exec(['delete', 'info.foo.bar[0].baz'], err => { + if (err) + throw err + + t.strictSame( + readPackageJson(), + { + name: 'foo', + version: '1.0.0', + info: { + foo: { + bar: [ + {}, + ], + }, + }, + }, + 'should delete nested fields from package.json' + ) + + t.end() + }) +}) + +t.test('workspaces', async t => { + npm.localPrefix = t.testdir({ + 'package.json': JSON.stringify({ + name: 'root', + version: '1.0.0', + workspaces: [ + 'packages/*', + ], + }), + packages: { + a: { + 'package.json': JSON.stringify({ + name: 'a', + version: '1.0.0', + }), + }, + b: { + 'package.json': JSON.stringify({ + name: 'b', + version: '1.2.3', + }), + }, + }, + }) + + await new Promise((res, rej) => { + pkg.execWorkspaces(['get', 'name', 'version'], [], err => { + if (err) + rej(err) + + t.strictSame( + JSON.parse(OUTPUT), + { + a: { + name: 'a', + version: '1.0.0', + }, + b: { + name: 'b', + version: '1.2.3', + }, + }, + 'should return expected result for configured workspaces' + ) + res() + }) + }) + + await new Promise((res, rej) => { + pkg.execWorkspaces(['set', 'funding=http://example.com'], [], err => { + if (err) + rej(err) + + t.strictSame( + readPackageJson(resolve(npm.localPrefix, 'packages/a')), + { + name: 'a', + version: '1.0.0', + funding: 'http://example.com', + }, + 'should add field to workspace a' + ) + + t.strictSame( + readPackageJson(resolve(npm.localPrefix, 'packages/b')), + { + name: 'b', + version: '1.2.3', + funding: 'http://example.com', + }, + 'should add field to workspace b' + ) + res() + }) + }) + + await new Promise((res, rej) => { + pkg.execWorkspaces(['delete', 'version'], [], err => { + if (err) + rej(err) + + t.strictSame( + readPackageJson(resolve(npm.localPrefix, 'packages/a')), + { + name: 'a', + funding: 'http://example.com', + }, + 'should delete version field from workspace a' + ) + + t.strictSame( + readPackageJson(resolve(npm.localPrefix, 'packages/b')), + { + name: 'b', + funding: 'http://example.com', + }, + 'should delete version field from workspace b' + ) + res() + }) + }) +}) diff --git a/deps/npm/test/lib/publish.js b/deps/npm/test/lib/publish.js index 56590478fc1..4aa3e559275 100644 --- a/deps/npm/test/lib/publish.js +++ b/deps/npm/test/lib/publish.js @@ -762,3 +762,103 @@ t.test('private workspaces', (t) => { t.end() }) + +t.test('runs correct lifecycle scripts', t => { + const testDir = t.testdir({ + 'package.json': JSON.stringify({ + name: 'my-cool-pkg', + version: '1.0.0', + scripts: { + prepublishOnly: 'echo test prepublishOnly', + prepublish: 'echo test prepublish', // should NOT run this one + publish: 'echo test publish', + postpublish: 'echo test postpublish', + }, + }, null, 2), + }) + + const scripts = [] + const Publish = t.mock('../../lib/publish.js', { + '@npmcli/run-script': (args) => { + scripts.push(args) + }, + '../../lib/utils/tar.js': { + getContents: () => ({ + id: 'someid', + }), + logTar: () => { + t.pass('logTar is called') + }, + }, + libnpmpublish: { + publish: () => { + t.pass('publish called') + }, + }, + }) + const npm = mockNpm({ + output: () => { + t.pass('output is called') + }, + }) + npm.config.getCredentialsByURI = (uri) => { + t.same(uri, npm.config.get('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.same( + scripts.map(s => s.event), + ['prepublishOnly', 'publish', 'postpublish'], + 'runs only expected scripts, in order' + ) + t.end() + }) +}) + +t.test('does not run scripts on --ignore-scripts', t => { + const testDir = t.testdir({ + 'package.json': JSON.stringify({ + name: 'my-cool-pkg', + version: '1.0.0', + }, null, 2), + }) + + const Publish = t.mock('../../lib/publish.js', { + '@npmcli/run-script': () => { + t.fail('should not call run-script') + }, + '../../lib/utils/tar.js': { + getContents: () => ({ + id: 'someid', + }), + logTar: () => { + t.pass('logTar is called') + }, + }, + libnpmpublish: { + publish: () => { + t.pass('publish called') + }, + }, + }) + const npm = mockNpm({ + config: { 'ignore-scripts': true }, + output: () => { + t.pass('output is called') + }, + }) + npm.config.getCredentialsByURI = (uri) => { + t.same(uri, npm.config.get('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() + }) +}) diff --git a/deps/npm/test/lib/utils/config/definition.js b/deps/npm/test/lib/utils/config/definition.js index 45f4c977a77..a17a1a09a22 100644 --- a/deps/npm/test/lib/utils/config/definition.js +++ b/deps/npm/test/lib/utils/config/definition.js @@ -95,6 +95,13 @@ t.test('basic definition', async t => { description: 'test description', }) t.equal(hasShort.usage, '-t|--key <key>') + const multiHasShort = new Definition('key', { + default: 'test default', + short: 't', + type: [null, String], + description: 'test description', + }) + t.equal(multiHasShort.usage, '-t|--key <key>') const hardCodedTypes = new Definition('key', { default: 'test default', type: ['string1', 'string2'], diff --git a/deps/npm/test/lib/utils/config/definitions.js b/deps/npm/test/lib/utils/config/definitions.js index 8724f0e3bd3..63d9bbd195a 100644 --- a/deps/npm/test/lib/utils/config/definitions.js +++ b/deps/npm/test/lib/utils/config/definitions.js @@ -463,7 +463,7 @@ t.test('search options', t => { t.end() }) -t.test('noProxy', t => { +t.test('noProxy - array', t => { const obj = { noproxy: ['1.2.3.4,2.3.4.5', '3.4.5.6'] } const flat = {} definitions.noproxy.flatten('noproxy', obj, flat) @@ -471,6 +471,14 @@ t.test('noProxy', t => { t.end() }) +t.test('noProxy - string', 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 = {} @@ -797,3 +805,26 @@ t.test('save-exact', t => { t.strictSame(flat, { savePrefix: '~1.2.3' }) t.end() }) + +t.test('location', t => { + const obj = { + global: true, + location: 'user', + } + const flat = {} + definitions.location.flatten('location', obj, flat) + // global = true sets location in both places to global + t.strictSame(flat, { location: 'global' }) + t.strictSame(obj, { global: true, location: 'global' }) + + obj.global = false + obj.location = 'user' + delete flat.global + delete flat.location + + definitions.location.flatten('location', obj, flat) + // global = false leaves location unaltered + t.strictSame(flat, { location: 'user' }) + t.strictSame(obj, { global: false, location: 'user' }) + t.end() +}) diff --git a/deps/npm/test/lib/utils/error-message.js b/deps/npm/test/lib/utils/error-message.js index 4f94645a454..3fdfb8cc250 100644 --- a/deps/npm/test/lib/utils/error-message.js +++ b/deps/npm/test/lib/utils/error-message.js @@ -97,6 +97,7 @@ t.test('just simple messages', t => { 'ETOOMANYARGS', 'ETARGET', 'E403', + 'ERR_SOCKET_TIMEOUT', ] t.plan(codes.length) codes.forEach(code => { diff --git a/deps/npm/test/lib/utils/exit-handler.js b/deps/npm/test/lib/utils/exit-handler.js index 06014b67a97..981ac9a32b6 100644 --- a/deps/npm/test/lib/utils/exit-handler.js +++ b/deps/npm/test/lib/utils/exit-handler.js @@ -1,13 +1,12 @@ /* eslint-disable no-extend-native */ /* eslint-disable no-global-assign */ -const EventEmitter = require('events') -const writeFileAtomic = require('write-file-atomic') const t = require('tap') +const EventEmitter = require('events') +const os = require('os') +const fs = require('fs') +const path = require('path') -// NOTE: Although these unit tests may look like the rest on the surface, -// they are in fact very special due to the amount of things hooking directly -// to global process and variables defined in the module scope. That makes -// for tests that are very interdependent and their order are important. +const { real: mockNpm } = require('../../fixtures/mock-npm') // generic error to be used in tests const err = Object.assign(new Error('ERROR'), { code: 'ERROR' }) @@ -23,69 +22,23 @@ const redactCwd = (path) => { t.cleanSnapshot = (str) => redactCwd(str) -// internal modules mocks const cacheFolder = t.testdir({}) -const config = { - values: { - cache: cacheFolder, - timing: true, - }, - loaded: true, - updateNotification: null, - get (key) { - return this.values[key] - }, -} - -const npm = { - version: '1.0.0', - config, - shelloutCommands: ['exec', 'run-script'], -} +const logFile = path.resolve(cacheFolder, '_logs', 'expecteddate-debug.log') +const timingFile = path.resolve(cacheFolder, '_timing.json') -const npmlog = { - disableProgress: () => null, - log (level, ...args) { - this.record.push({ - id: this.record.length, - level, - message: args.reduce((res, i) => `${res} ${i.message ? i.message : i}`, ''), - prefix: level !== 'verbose' ? 'foo' : '', - }) - }, - error (...args) { - this.log('error', ...args) - }, - info (...args) { - this.log('info', ...args) - }, - level: 'silly', - levels: { - silly: 0, - verbose: 1, - info: 2, - error: 3, - silent: 4, - }, - notice (...args) { - this.log('notice', ...args) - }, - record: [], - verbose (...args) { - this.log('verbose', ...args) - }, -} +const { npm } = mockNpm(t) -// overrides OS type/release for cross platform snapshots -const os = require('os') -os.type = () => 'Foo' -os.release = () => '1.0.0' +t.before(async () => { + npm.version = '1.0.0' + await npm.load() + npm.config.set('cache', cacheFolder) +}) -// bootstrap tap before cutting off process ref -t.test('ok', (t) => { +t.test('bootstrap tap before cutting off process ref', (t) => { t.ok('ok') t.end() }) + // cut off process from script so that it won't quit the test runner // while trying to run through the myriad of cases const _process = process @@ -95,9 +48,11 @@ process = Object.assign( argv: ['/node', ..._process.argv.slice(1)], cwd: _process.cwd, env: _process.env, - exit () {}, - exitCode: 0, version: 'v1.0.0', + exit: (code) => { + process.exitCode = code || process.exitCode || 0 + process.emit('exit', process.exitCode) + }, stdout: { write (_, cb) { cb() } }, @@ -105,19 +60,40 @@ process = Object.assign( hrtime: _process.hrtime, } ) -// needs to put process back in its place -// in order for tap to exit properly + +const osType = os.type +const osRelease = os.release +// overrides OS type/release for cross platform snapshots +os.type = () => 'Foo' +os.release = () => '1.0.0' + +// generates logfile name with mocked date +const _toISOString = Date.prototype.toISOString +Date.prototype.toISOString = () => 'expecteddate' + +const consoleError = console.error +const errors = [] +console.error = (err) => { + errors.push(err) +} t.teardown(() => { + os.type = osType + os.release = osRelease + // needs to put process back in its place in order for tap to exit properly process = _process + Date.prototype.toISOString = _toISOString + console.error = consoleError }) t.afterEach(() => { + errors.length = 0 + npm.log.level = 'silent' // clear out the 'A complete log' message - npmlog.record.length = 0 + npm.log.record.length = 0 + delete process.exitCode }) const mocks = { - npmlog, '../../../lib/utils/error-message.js': (err) => ({ ...err, summary: [['ERR', err.message]], @@ -125,102 +101,57 @@ const mocks = { }), } -let exitHandler = t.mock('../../../lib/utils/exit-handler.js', mocks) +const exitHandler = t.mock('../../../lib/utils/exit-handler.js', mocks) exitHandler.setNpm(npm) -t.test('default exit code', (t) => { - t.plan(1) - - // manually simulate timing handlers - process.emit('timing', 'foo', 1) - process.emit('timing', 'foo', 2) - - // generates logfile name with mocked date - const _toISOString = Date.prototype.toISOString - Date.prototype.toISOString = () => 'expecteddate' - - npmlog.level = 'silent' - const _exit = process.exit - process.exit = (code) => { - t.equal(code, 1, 'should default to error code 1') - } - - // skip console.error logs - const _error = console.error - console.error = () => null - +t.test('exit handler never called - loglevel silent', (t) => { + npm.log.level = 'silent' process.emit('exit', 1) + const logData = fs.readFileSync(logFile, 'utf8') + t.match(logData, 'Exit handler never called!') + t.match(errors, [''], 'logs one empty string to console.error') + t.end() +}) - t.teardown(() => { - npmlog.level = 'silly' - process.exit = _exit - console.error = _error - Date.prototype.toISOString = _toISOString - }) +t.test('exit handler never called - loglevel notice', (t) => { + npm.log.level = 'notice' + process.emit('exit', 1) + const logData = fs.readFileSync(logFile, 'utf8') + t.match(logData, 'Exit handler never called!') + t.match(errors, ['', ''], 'logs two empty strings to console.error') + t.end() }) t.test('handles unknown error', (t) => { t.plan(2) - const _toISOString = Date.prototype.toISOString - Date.prototype.toISOString = () => 'expecteddate' - - const sync = writeFileAtomic.sync - writeFileAtomic.sync = (filename, content) => { - t.equal( - redactCwd(filename), - '{CWD}/test/lib/utils/tap-testdir-exit-handler/_logs/expecteddate-debug.log', - 'should use expected log filename' - ) - t.matchSnapshot( - content, - 'should have expected log contents for unknown error' - ) - } - - exitHandler(err) + npm.log.level = 'notice' - t.teardown(() => { - writeFileAtomic.sync = sync - Date.prototype.toISOString = _toISOString + process.once('timeEnd', (msg) => { + t.equal(msg, 'npm', 'should trigger timeEnd for npm') }) + + exitHandler(err) + const logData = fs.readFileSync(logFile, 'utf8') + t.matchSnapshot( + logData, + 'should have expected log contents for unknown error' + ) t.end() }) -t.test('npm.config not ready', (t) => { +t.test('fail to write logfile', (t) => { t.plan(1) - config.loaded = false - - const _error = console.error - console.error = (msg) => { - t.match( - msg, - /Error: Exit prior to config file resolving./, - 'should exit with config error msg' - ) - } - - exitHandler() - t.teardown(() => { - console.error = _error - config.loaded = true + npm.config.set('cache', cacheFolder) }) -}) - -t.test('fail to write logfile', (t) => { - t.plan(1) const badDir = t.testdir({ _logs: 'is a file', }) - config.values.cache = badDir - - t.teardown(() => { - config.values.cache = cacheFolder - }) + npm.config.set('cache', badDir) t.doesNotThrow( () => exitHandler(err), @@ -231,241 +162,166 @@ t.test('fail to write logfile', (t) => { t.test('console.log output using --json', (t) => { t.plan(1) - config.values.json = true - - const _error = console.error - console.error = (jsonOutput) => { - t.same( - JSON.parse(jsonOutput), - { - error: { - code: 'EBADTHING', // should default error code to E[A-Z]+ - summary: 'Error: EBADTHING Something happened', - detail: 'Error: EBADTHING Something happened', - }, - }, - 'should output expected json output' - ) - } - - exitHandler(new Error('Error: EBADTHING Something happened')) - + npm.config.set('json', true) t.teardown(() => { - console.error = _error - delete config.values.json + npm.config.set('json', false) }) + + exitHandler(new Error('Error: EBADTHING Something happened')) + t.same( + JSON.parse(errors[0]), + { + error: { + code: 'EBADTHING', // should default error code to E[A-Z]+ + summary: 'Error: EBADTHING Something happened', + detail: 'Error: EBADTHING Something happened', + }, + }, + 'should output expected json output' + ) }) t.test('throw a non-error obj', (t) => { - t.plan(3) + t.plan(2) const weirdError = { code: 'ESOMETHING', message: 'foo bar', } - const _logError = npmlog.error - npmlog.error = (title, err) => { - t.equal(title, 'weird error', 'should name it a weird error') - t.same(err, weirdError, 'should log given weird error') - } - - const _exit = process.exit - process.exit = (code) => { - t.equal(code, 1, 'should exit with code 1') - } - - exitHandler(weirdError) - - t.teardown(() => { - process.exit = _exit - npmlog.error = _logError + process.once('exit', code => { + t.equal(code, 1, 'exits with exitCode 1') }) + exitHandler(weirdError) + t.match( + npm.log.record.find(r => r.level === 'error'), + { message: 'foo bar' } + ) }) t.test('throw a string error', (t) => { - t.plan(3) - + t.plan(2) const error = 'foo bar' - const _logError = npmlog.error - npmlog.error = (title, err) => { - t.equal(title, '', 'should have an empty name ref') - t.same(err, 'foo bar', 'should log string error') - } - - const _exit = process.exit - process.exit = (code) => { - t.equal(code, 1, 'should exit with code 1') - } - - exitHandler(error) - - t.teardown(() => { - process.exit = _exit - npmlog.error = _logError + process.once('exit', code => { + t.equal(code, 1, 'exits with exitCode 1') }) + exitHandler(error) + t.match( + npm.log.record.find(r => r.level === 'error'), + { message: 'foo bar' } + ) }) t.test('update notification', (t) => { - t.plan(2) - const updateMsg = 'you should update npm!' npm.updateNotification = updateMsg - - const _notice = npmlog.notice - npmlog.notice = (prefix, msg) => { - t.equal(prefix, '', 'should have no prefix') - t.equal(msg, updateMsg, 'should show update message') - } - - exitHandler(err) + npm.log.level = 'silent' t.teardown(() => { - npmlog.notice = _notice delete npm.updateNotification }) + + exitHandler() + t.match( + npm.log.record.find(r => r.level === 'notice'), + { message: 'you should update npm!' } + ) + t.end() }) -t.test('on exit handler', (t) => { - t.plan(2) +t.test('npm.config not ready', (t) => { + t.plan(1) - const _exit = process.exit - process.exit = (code) => { - t.equal(code, 1, 'should default to error code 1') - } + const { npm: unloaded } = mockNpm(t) - process.once('timeEnd', (msg) => { - t.equal(msg, 'npm', 'should trigger timeEnd for npm') + t.teardown(() => { + exitHandler.setNpm(npm) }) - // skip console.error logs - const _error = console.error - console.error = () => null + exitHandler.setNpm(unloaded) - process.emit('exit', 1) - - t.teardown(() => { - console.error = _error - process.exit = _exit - }) + exitHandler() + t.match( + errors[0], + /Error: Exit prior to config file resolving./, + 'should exit with config error msg' + ) + t.end() }) -t.test('it worked', (t) => { - t.plan(2) +t.test('timing', (t) => { + npm.config.set('timing', true) - config.values.timing = false - - const _exit = process.exit - process.exit = (code) => { - process.exit = _exit - t.notOk(code, 'should exit with no code') + t.teardown(() => { + fs.unlinkSync(timingFile) + npm.config.set('timing', false) + }) - const _info = npmlog.info - npmlog.info = (msg) => { - npmlog.info = _info - t.equal(msg, 'ok', 'should log ok if "it worked"') - } + exitHandler() + const timingData = JSON.parse(fs.readFileSync(timingFile, 'utf8')) + t.match(timingData, { version: '1.0.0', 'config:load:defaults': Number }) + t.end() +}) - process.emit('exit', 0) - } +t.test('timing - with error', (t) => { + npm.config.set('timing', true) t.teardown(() => { - process.exit = _exit - config.values.timing = true + fs.unlinkSync(timingFile) + npm.config.set('timing', false) }) - exitHandler() + exitHandler(err) + const timingData = JSON.parse(fs.readFileSync(timingFile, 'utf8')) + t.match(timingData, { version: '1.0.0', 'config:load:defaults': Number }) + t.end() }) t.test('uses code from errno', (t) => { t.plan(1) - exitHandler = t.mock('../../../lib/utils/exit-handler.js', mocks) - exitHandler.setNpm(npm) - - npmlog.level = 'silent' - const _exit = process.exit - process.exit = (code) => { - t.equal(code, 127, 'should use set errno') - } - + process.once('exit', code => { + t.equal(code, 127, 'should set exitCode from errno') + }) exitHandler(Object.assign( new Error('Error with errno'), { errno: 127, } )) - - t.teardown(() => { - npmlog.level = 'silly' - process.exit = _exit - }) }) -t.test('uses exitCode as code if using a number', (t) => { +t.test('uses code from number', (t) => { t.plan(1) - exitHandler = t.mock('../../../lib/utils/exit-handler.js', mocks) - exitHandler.setNpm(npm) - - npmlog.level = 'silent' - const _exit = process.exit - process.exit = (code) => { - t.equal(code, 404, 'should use code if a number') - } - + process.once('exit', code => { + t.equal(code, 404, 'should set exitCode from a number') + }) exitHandler(Object.assign( new Error('Error with code type number'), { code: 404, } )) - - t.teardown(() => { - npmlog.level = 'silly' - process.exit = _exit - }) }) t.test('call exitHandler with no error', (t) => { t.plan(1) - - exitHandler = t.mock('../../../lib/utils/exit-handler.js', mocks) - exitHandler.setNpm(npm) - - const _exit = process.exit - process.exit = (code) => { - t.equal(code, undefined, 'should exit with code undefined') - } - - t.teardown(() => { - process.exit = _exit + process.once('exit', code => { + t.equal(code, 0, 'should end up with exitCode 0 (default)') }) - - exitHandler() -}) - -t.test('exit handler called twice', (t) => { - t.plan(2) - - const _verbose = npmlog.verbose - npmlog.verbose = (key, value) => { - t.equal(key, 'stack', 'should log stack in verbose level') - t.match( - value, - /Error: Exit handler called more than once./, - 'should have expected error msg' - ) - npmlog.verbose = _verbose - } - exitHandler() }) t.test('defaults to log error msg if stack is missing', (t) => { - t.plan(1) + const { npm: unloaded } = mockNpm(t) + t.teardown(() => { + exitHandler.setNpm(npm) + }) + + exitHandler.setNpm(unloaded) const noStackErr = Object.assign( new Error('Error with no stack'), { @@ -475,89 +331,63 @@ t.test('defaults to log error msg if stack is missing', (t) => { ) delete noStackErr.stack - npm.config.loaded = false - - const _error = console.error - console.error = (msg) => { - console.error = _error - npm.config.loaded = true - t.equal(msg, 'Error with no stack', 'should use error msg') - } - exitHandler(noStackErr) + t.equal(errors[0], 'Error with no stack', 'should use error msg') + t.end() }) t.test('exits cleanly when emitting exit event', (t) => { t.plan(1) - npmlog.level = 'silent' - const _exit = process.exit - process.exit = (code) => { - process.exit = _exit - t.same(code, null, 'should exit with code null') - } - - t.teardown(() => { - process.exit = _exit - npmlog.level = 'silly' - }) - + npm.log.level = 'silent' process.emit('exit') + t.match( + npm.log.record.find(r => r.level === 'info'), + { prefix: 'ok', message: '' } + ) + t.end() }) t.test('do no fancy handling for shellouts', t => { - const { exit } = process const { command } = npm - const { log } = npmlog const LOG_RECORD = [] + npm.command = 'exec' + t.teardown(() => { - npmlog.log = log - process.exit = exit npm.command = command }) - - npmlog.log = function (level, ...args) { - log.call(this, level, ...args) - LOG_RECORD.push(npmlog.record[npmlog.record.length - 1]) - } - - npm.command = 'exec' - - let EXPECT_EXIT = 0 - process.exit = code => { - t.equal(code, EXPECT_EXIT, 'got expected exit code') - EXPECT_EXIT = 0 - } t.beforeEach(() => LOG_RECORD.length = 0) - const loudNoises = () => LOG_RECORD + const loudNoises = () => npm.log.record .filter(({ level }) => ['warn', 'error'].includes(level)) t.test('shellout with a numeric error code', t => { - EXPECT_EXIT = 5 + t.plan(2) + process.once('exit', code => { + t.equal(code, 5, 'got expected exit code') + }) exitHandler(Object.assign(new Error(), { code: 5 })) - t.equal(EXPECT_EXIT, 0, 'called process.exit') - // should log no warnings or errors, verbose/silly is fine. t.strictSame(loudNoises(), [], 'no noisy warnings') - t.end() }) t.test('shellout without a numeric error code (something in npm)', t => { - EXPECT_EXIT = 1 + t.plan(2) + process.once('exit', code => { + t.equal(code, 1, 'got expected exit code') + }) exitHandler(Object.assign(new Error(), { code: 'banana stand' })) - t.equal(EXPECT_EXIT, 0, 'called process.exit') // should log some warnings and errors, because something weird happened t.strictNotSame(loudNoises(), [], 'bring the noise') t.end() }) t.test('shellout with code=0 (extra weird?)', t => { - EXPECT_EXIT = 1 + t.plan(2) + process.once('exit', code => { + t.equal(code, 1, 'got expected exit code') + }) exitHandler(Object.assign(new Error(), { code: 0 })) - t.equal(EXPECT_EXIT, 0, 'called process.exit') - // should log some warnings and errors, because something weird happened t.strictNotSame(loudNoises(), [], 'bring the noise') - t.end() }) t.end() diff --git a/deps/npm/test/lib/utils/perf.js b/deps/npm/test/lib/utils/perf.js deleted file mode 100644 index 840dcb6e323..00000000000 --- a/deps/npm/test/lib/utils/perf.js +++ /dev/null @@ -1,38 +0,0 @@ -const t = require('tap') -const logs = [] -const npmlog = require('npmlog') -npmlog.silly = (...msg) => logs.push(['silly', ...msg]) -npmlog.timing = (...msg) => logs.push(['timing', ...msg]) - -t.test('time some stuff', t => { - const timings = {} - process.on('timing', (name, value) => { - timings[name] = (timings[name] || 0) + value - }) - require('../../../lib/utils/perf.js') - process.emit('time', 'foo') - process.emit('time', 'bar') - setTimeout(() => { - process.emit('timeEnd', 'foo') - process.emit('timeEnd', 'bar') - process.emit('time', 'foo') - setTimeout(() => { - process.emit('timeEnd', 'foo') - process.emit('timeEnd', 'baz') - t.match(logs, [ - ['timing', 'foo', /Completed in [0-9]+ms/], - ['timing', 'bar', /Completed in [0-9]+ms/], - ['timing', 'foo', /Completed in [0-9]+ms/], - [ - 'silly', - 'timing', - "Tried to end timer that doesn't exist:", - 'baz', - ], - ]) - t.match(timings, { foo: Number, bar: Number }) - t.equal(timings.foo > timings.bar, true, 'foo should be > bar') - t.end() - }, 100) - }, 100) -}) diff --git a/deps/npm/test/lib/utils/queryable.js b/deps/npm/test/lib/utils/queryable.js new file mode 100644 index 00000000000..bde3ea66238 --- /dev/null +++ b/deps/npm/test/lib/utils/queryable.js @@ -0,0 +1,965 @@ +const { inspect } = require('util') +const t = require('tap') +const Queryable = require('../../../lib/utils/queryable.js') + +t.test('retrieve single nested property', async t => { + const fixture = { + foo: { + bar: 'bar', + baz: 'baz', + }, + lorem: { + ipsum: 'ipsum', + }, + } + const q = new Queryable(fixture) + const query = 'foo.bar' + t.strictSame(q.query(query), { [query]: 'bar' }, + 'should retrieve property value when querying for dot-sep name') +}) + +t.test('query', async t => { + const fixture = { + o: 'o', + single: [ + 'item', + ], + w: [ + 'a', + 'b', + 'c', + ], + list: [ + { + name: 'first', + }, + { + name: 'second', + }, + ], + foo: { + bar: 'bar', + baz: 'baz', + }, + lorem: { + ipsum: 'ipsum', + dolor: [ + 'a', + 'b', + 'c', + { + sit: [ + 'amet', + ], + }, + ], + }, + a: [ + [ + [ + { + b: [ + [ + { + c: 'd', + }, + ], + ], + }, + ], + ], + ], + } + const q = new Queryable(fixture) + t.strictSame( + q.query(['foo.baz', 'lorem.dolor[0]']), + { + 'foo.baz': 'baz', + 'lorem.dolor[0]': 'a', + }, + 'should retrieve property values when querying for multiple dot-sep names') + t.strictSame( + q.query('lorem.dolor[3].sit[0]'), + { + 'lorem.dolor[3].sit[0]': 'amet', + }, + 'should retrieve property from nested array items') + t.strictSame( + q.query('a[0][0][0].b[0][0].c'), + { + 'a[0][0][0].b[0][0].c': 'd', + }, + 'should retrieve property from deep nested array items') + t.strictSame( + q.query('o'), + { + o: 'o', + }, + 'should retrieve single level property value') + t.strictSame( + q.query('list.name'), + { + 'list[0].name': 'first', + 'list[1].name': 'second', + }, + 'should automatically expand arrays') + t.strictSame( + q.query(['list.name']), + { + 'list[0].name': 'first', + 'list[1].name': 'second', + }, + 'should automatically expand multiple arrays') + t.strictSame( + q.query('w'), + { + w: ['a', 'b', 'c'], + }, + 'should return arrays') + t.strictSame( + q.query('single'), + { + single: 'item', + }, + 'should return single item') + t.strictSame( + q.query('missing'), + undefined, + 'should return undefined') + t.strictSame( + q.query('missing[bar]'), + undefined, + 'should return undefined also') + t.throws(() => q.query('lorem.dolor[]'), + { code: 'EINVALIDSYNTAX' }, + 'should throw if using empty brackets notation' + ) + t.throws(() => q.query('lorem.dolor[].sit[0]'), + { code: 'EINVALIDSYNTAX' }, + 'should throw if using nested empty brackets notation' + ) + + const qq = new Queryable({ + foo: { + bar: 'bar', + }, + }) + t.strictSame( + qq.query(''), + { + '': { + foo: { + bar: 'bar', + }, + }, + }, + 'should return an object with results in an empty key' + ) +}) + +t.test('missing key', async t => { + const fixture = { + foo: { + bar: 'bar', + }, + } + const q = new Queryable(fixture) + const query = 'foo.missing' + t.equal(q.query(query), undefined, + 'should retrieve no results') +}) + +t.test('no data object', async t => { + t.throws( + () => new Queryable(), + { code: 'ENOQUERYABLEOBJ' }, + 'should throw ENOQUERYABLEOBJ error' + ) + t.throws( + () => new Queryable(1), + { code: 'ENOQUERYABLEOBJ' }, + 'should throw ENOQUERYABLEOBJ error' + ) +}) + +t.test('get values', async t => { + const q = new Queryable({ + foo: { + bar: 'bar', + }, + }) + t.equal(q.get('foo.bar'), 'bar', 'should retrieve value') + t.equal(q.get('missing'), undefined, 'should return undefined') +}) + +t.test('set property values', async t => { + const fixture = { + foo: { + bar: 'bar', + }, + } + const q = new Queryable(fixture) + q.set('foo.baz', 'baz') + t.strictSame( + q.toJSON(), + { + foo: { + bar: 'bar', + baz: 'baz', + }, + }, + 'should add new property and its assigned value' + ) + q.set('foo[lorem.ipsum]', 'LOREM IPSUM') + t.strictSame( + q.toJSON(), + { + foo: { + bar: 'bar', + baz: 'baz', + 'lorem.ipsum': 'LOREM IPSUM', + }, + }, + 'should be able to set square brackets props' + ) + q.set('a.b[c.d]', 'omg') + t.strictSame( + q.toJSON(), + { + foo: { + bar: 'bar', + baz: 'baz', + 'lorem.ipsum': 'LOREM IPSUM', + }, + a: { + b: { + 'c.d': 'omg', + }, + }, + }, + 'should be able to nest square brackets props' + ) + q.set('a.b[e][f.g][1.0.0]', 'multiple') + t.strictSame( + q.toJSON(), + { + foo: { + bar: 'bar', + baz: 'baz', + 'lorem.ipsum': 'LOREM IPSUM', + }, + a: { + b: { + 'c.d': 'omg', + e: { + 'f.g': { + '1.0.0': 'multiple', + }, + }, + }, + }, + }, + 'should be able to nest multiple square brackets props' + ) + q.set('a.b[e][f.g][2.0.0].author.name', 'Ruy Adorno') + t.strictSame( + q.toJSON(), + { + foo: { + bar: 'bar', + baz: 'baz', + 'lorem.ipsum': 'LOREM IPSUM', + }, + a: { + b: { + 'c.d': 'omg', + e: { + 'f.g': { + '1.0.0': 'multiple', + '2.0.0': { + author: { + name: 'Ruy Adorno', + }, + }, + }, + }, + }, + }, + }, + 'should be able to use dot-sep notation after square bracket props' + ) + q.set('a.b[e][f.g][2.0.0].author[url]', 'https://npmjs.com') + t.strictSame( + q.toJSON(), + { + foo: { + bar: 'bar', + baz: 'baz', + 'lorem.ipsum': 'LOREM IPSUM', + }, + a: { + b: { + 'c.d': 'omg', + e: { + 'f.g': { + '1.0.0': 'multiple', + '2.0.0': { + author: { + name: 'Ruy Adorno', + url: 'https://npmjs.com', + }, + }, + }, + }, + }, + }, + }, + 'should be able to have multiple, separated, square brackets props' + ) + q.set('a.b[e][f.g][2.0.0].author[foo][bar].lorem.ipsum[dolor][sit][amet].omg', 'O_O') + t.strictSame( + q.toJSON(), + { + foo: { + bar: 'bar', + baz: 'baz', + 'lorem.ipsum': 'LOREM IPSUM', + }, + a: { + b: { + 'c.d': 'omg', + e: { + 'f.g': { + '1.0.0': 'multiple', + '2.0.0': { + author: { + name: 'Ruy Adorno', + url: 'https://npmjs.com', + foo: { + bar: { + lorem: { + ipsum: { + dolor: { + sit: { + amet: { + omg: 'O_O', + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + 'many many times...' + ) + t.throws( + () => q.set('foo.bar.nest', 'should throw'), + { code: 'EOVERRIDEVALUE' }, + 'should throw if trying to override a literal value with an object' + ) + q.set('foo.bar.nest', 'use the force!', { force: true }) + t.strictSame( + q.toJSON().foo, + { + bar: { + nest: 'use the force!', + }, + baz: 'baz', + 'lorem.ipsum': 'LOREM IPSUM', + }, + 'should allow overriding literal values when using force option' + ) + + const qq = new Queryable({}) + qq.set('foo.bar.baz', 'BAZ') + t.strictSame( + qq.toJSON(), + { + foo: { + bar: { + baz: 'BAZ', + }, + }, + }, + 'should add new props to qq object' + ) + qq.set('foo.bar.bario', 'bario') + t.strictSame( + qq.toJSON(), + { + foo: { + bar: { + baz: 'BAZ', + bario: 'bario', + }, + }, + }, + 'should add new props to a previously existing object' + ) + qq.set('lorem', 'lorem') + t.strictSame( + qq.toJSON(), + { + foo: { + bar: { + baz: 'BAZ', + bario: 'bario', + }, + }, + lorem: 'lorem', + }, + 'should append new props added to object later' + ) + qq.set('foo.bar[foo.bar]', 'foo.bar.with.dots') + t.strictSame( + qq.toJSON(), + { + foo: { + bar: { + 'foo.bar': 'foo.bar.with.dots', + baz: 'BAZ', + bario: 'bario', + }, + }, + lorem: 'lorem', + }, + 'should append new props added to object later' + ) +}) + +t.test('set arrays', async t => { + const q = new Queryable({}) + + q.set('foo[1]', 'b') + t.strictSame( + q.toJSON(), + { + foo: [ + undefined, + 'b', + ], + }, + 'should be able to set items in an array using index references' + ) + + q.set('foo[0]', 'a') + t.strictSame( + q.toJSON(), + { + foo: [ + 'a', + 'b', + ], + }, + 'should be able to set a previously missing item to an array' + ) + + q.set('foo[2]', 'c') + t.strictSame( + q.toJSON(), + { + foo: [ + 'a', + 'b', + 'c', + ], + }, + 'should be able to append more items to an array' + ) + + q.set('foo[2]', 'C') + t.strictSame( + q.toJSON(), + { + foo: [ + 'a', + 'b', + 'C', + ], + }, + 'should be able to override array items' + ) + + t.throws( + () => q.set('foo[2].bar', 'bar'), + { code: 'EOVERRIDEVALUE' }, + 'should throw if trying to override an array literal item with an obj' + ) + + q.set('foo[2].bar', 'bar', { force: true }) + t.strictSame( + q.toJSON(), + { + foo: [ + 'a', + 'b', + { bar: 'bar' }, + ], + }, + 'should be able to override an array string item with an obj' + ) + + q.set('foo[3].foo', 'surprise surprise, another foo') + t.strictSame( + q.toJSON(), + { + foo: [ + 'a', + 'b', + { bar: 'bar' }, + { + foo: 'surprise surprise, another foo', + }, + ], + }, + 'should be able to append more items to an array' + ) + + q.set('foo[3].foo', 'FOO') + t.strictSame( + q.toJSON(), + { + foo: [ + 'a', + 'b', + { bar: 'bar' }, + { + foo: 'FOO', + }, + ], + }, + 'should be able to override property of an obj inside an array' + ) + + const qq = new Queryable({}) + qq.set('foo[0].bar[1].baz.bario[0][0][0]', 'something') + t.strictSame( + qq.toJSON(), + { + foo: [ + { + bar: [ + undefined, + { + baz: { + bario: [[['something']]], + }, + }, + ], + }, + ], + }, + 'should append as many arrays as necessary' + ) + qq.set('foo[0].bar[1].baz.bario[0][1][0]', 'something else') + t.strictSame( + qq.toJSON(), + { + foo: [ + { + bar: [ + undefined, + { + baz: { + bario: [[ + ['something'], + ['something else'], + ]], + }, + }, + ], + }, + ], + }, + 'should append as many arrays as necessary' + ) + qq.set('foo', null) + t.strictSame( + qq.toJSON(), + { + foo: null, + }, + 'should be able to set a value to null' + ) + qq.set('foo.bar', 'bar') + t.strictSame( + qq.toJSON(), + { + foo: { + bar: 'bar', + }, + }, + 'should be able to replace a null value with properties' + ) + + const qqq = new Queryable({ + arr: [ + 'a', + 'b', + ], + }) + + qqq.set('arr[]', 'c') + t.strictSame( + qqq.toJSON(), + { + arr: [ + 'a', + 'b', + 'c', + ], + }, + 'should be able to append to array using empty bracket notation' + ) + + qqq.set('arr[].foo', 'foo') + t.strictSame( + qqq.toJSON(), + { + arr: [ + 'a', + 'b', + 'c', + { + foo: 'foo', + }, + ], + }, + 'should be able to append objects to array using empty bracket notation' + ) + + qqq.set('arr[].bar.name', 'BAR') + t.strictSame( + qqq.toJSON(), + { + arr: [ + 'a', + 'b', + 'c', + { + foo: 'foo', + }, + { + bar: { + name: 'BAR', + }, + }, + ], + }, + 'should be able to append more objects to array using empty brackets' + ) + + qqq.set('foo.bar.baz[].lorem.ipsum', 'something') + t.strictSame( + qqq.toJSON(), + { + arr: [ + 'a', + 'b', + 'c', + { + foo: 'foo', + }, + { + bar: { + name: 'BAR', + }, + }, + ], + foo: { + bar: { + baz: [ + { + lorem: { + ipsum: 'something', + }, + }, + ], + }, + }, + }, + 'should be able to append to array using empty brackets in nested objs' + ) + + qqq.set('foo.bar.baz[].lorem.array[]', 'new item') + t.strictSame( + qqq.toJSON(), + { + arr: [ + 'a', + 'b', + 'c', + { + foo: 'foo', + }, + { + bar: { + name: 'BAR', + }, + }, + ], + foo: { + bar: { + baz: [ + { + lorem: { + ipsum: 'something', + }, + }, + { + lorem: { + array: [ + 'new item', + ], + }, + }, + ], + }, + }, + }, + 'should be able to append to array using empty brackets in nested objs' + ) + + const qqqq = new Queryable({ + arr: [ + 'a', + 'b', + ], + }) + t.throws( + () => qqqq.set('arr.foo', 'foo'), + { code: 'ENOADDPROP' }, + 'should throw an override error' + ) + + qqqq.set('arr.foo', 'foo', { force: true }) + t.strictSame( + qqqq.toJSON(), + { + arr: { + 0: 'a', + 1: 'b', + foo: 'foo', + }, + }, + 'should be able to override arrays with objects when using force=true' + ) + + qqqq.set('bar[]', 'item', { force: true }) + t.strictSame( + qqqq.toJSON(), + { + arr: { + 0: 'a', + 1: 'b', + foo: 'foo', + }, + bar: [ + 'item', + ], + }, + 'should be able to create new array with item when using force=true' + ) + + qqqq.set('bar[]', 'something else', { force: true }) + t.strictSame( + qqqq.toJSON(), + { + arr: { + 0: 'a', + 1: 'b', + foo: 'foo', + }, + bar: [ + 'item', + 'something else', + ], + }, + 'should be able to append items to arrays when using force=true' + ) + + const qqqqq = new Queryable({ + arr: [ + null, + ], + }) + qqqqq.set('arr[]', 'b') + t.strictSame( + qqqqq.toJSON(), + { + arr: [ + null, + 'b', + ], + }, + 'should be able to append items with empty items' + ) + qqqqq.set('arr[0]', 'a') + t.strictSame( + qqqqq.toJSON(), + { + arr: [ + 'a', + 'b', + ], + }, + 'should be able to replace empty items in an array' + ) + qqqqq.set('lorem.ipsum', 3) + t.strictSame( + qqqqq.toJSON(), + { + arr: [ + 'a', + 'b', + ], + lorem: { + ipsum: 3, + }, + }, + 'should be able to replace empty items in an array' + ) + t.throws( + () => qqqqq.set('lorem[]', 4), + { code: 'ENOAPPEND' }, + 'should throw error if using empty square bracket in an non-array item' + ) + qqqqq.set('lorem[0]', 3) + t.strictSame( + qqqqq.toJSON(), + { + arr: [ + 'a', + 'b', + ], + lorem: { + 0: 3, + ipsum: 3, + }, + }, + 'should be able add indexes as props when finding an object' + ) + qqqqq.set('lorem.1', 3) + t.strictSame( + qqqqq.toJSON(), + { + arr: [ + 'a', + 'b', + ], + lorem: { + 0: 3, + 1: 3, + ipsum: 3, + }, + }, + 'should be able add numeric props to an obj' + ) +}) + +t.test('delete values', async t => { + const q = new Queryable({ + foo: { + bar: { + lorem: 'lorem', + }, + }, + }) + q.delete('foo.bar.lorem') + t.strictSame( + q.toJSON(), + { + foo: { + bar: {}, + }, + }, + 'should delete queried item' + ) + q.delete('foo') + t.strictSame( + q.toJSON(), + {}, + 'should delete nested items' + ) + q.set('foo.a.b.c[0]', 'value') + q.delete('foo.a.b.c[0]') + t.strictSame( + q.toJSON(), + { + foo: { + a: { + b: { + c: [], + }, + }, + }, + }, + 'should delete array item' + ) + // creates an array that has an implicit empty first item + q.set('foo.a.b.c[1][0].foo.bar[0][0]', 'value') + q.delete('foo.a.b.c[1]') + t.strictSame( + q.toJSON(), + { + foo: { + a: { + b: { + c: [null], + }, + }, + }, + }, + 'should delete array item' + ) +}) + +t.test('logger', async t => { + const q = new Queryable({}) + q.set('foo.bar[0].baz', 'baz') + t.strictSame( + inspect(q, { depth: 10 }), + inspect({ + foo: { + bar: [ + { + baz: 'baz', + }, + ], + }, + }, { depth: 10 }), + 'should retrieve expected data' + ) +}) + +t.test('bracket lovers', async t => { + const q = new Queryable({}) + q.set('[iLoveBrackets]', 'seriously?') + t.strictSame( + q.toJSON(), + { + '[iLoveBrackets]': 'seriously?', + }, + 'should be able to set top-level props using square brackets notation' + ) + + t.equal(q.get('[iLoveBrackets]'), 'seriously?', + 'should bypass square bracket in top-level properties') + + q.set('[0]', '-.-') + t.strictSame( + q.toJSON(), + { + '[iLoveBrackets]': 'seriously?', + '[0]': '-.-', + }, + 'any top-level item can not be parsed with square bracket notation' + ) +}) |