deps: upgrade npm to 7.3.0

PR-URL: https://github.com/nodejs/node/pull/36572
Reviewed-By: Myles Borins <myles.borins@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
This commit is contained in:
Ruy Adorno 2020-12-18 15:39:05 -05:00 committed by Michaël Zasso
parent eefb424c60
commit ffc11c6015
No known key found for this signature in database
GPG Key ID: 770F7A9A5AE15600
71 changed files with 2486 additions and 698 deletions

View File

@ -67,6 +67,13 @@
"key-spacing": ["error", { "beforeColon": false, "afterColon": true }],
"keyword-spacing": ["error", { "before": true, "after": true }],
"lines-between-class-members": ["error", "always", { "exceptAfterSingleLine": true }],
"max-len": ["error", 80, {
"ignoreUrls": true,
"ignoreComments": false,
"ignoreRegExpLiterals": true,
"ignoreStrings": true,
"ignoreTemplateLiterals": true
}],
"new-cap": ["error", { "newIsCap": true, "capIsNew": false, "properties": true }],
"new-parens": "error",
"no-array-constructor": "error",

2
deps/npm/AUTHORS vendored
View File

@ -739,3 +739,5 @@ kai zhu <kaizhu256@gmail.com>
Alex Woollam <alexjhwoollam@gmail.com>
Daniel Fischer <daniel@d-fischer.dev>
Yash-Singh1 <saiansh2525@gmail.com>
Edu93Jer <mailing_93@hotmail.com>
Tieg Zaharia <tieg@tidelift.com>

74
deps/npm/CHANGELOG.md vendored
View File

@ -1,3 +1,75 @@
## 7.3.0 (2020-12-18)
### FEATURES
* [`a9b8bf263`](https://github.com/npm/cli/commit/a9b8bf2634c627fbb16ca3a6bb2c2f1058c3e586)
[#2362](https://github.com/npm/cli/issues/2362)
Support multiple set/get/deletes in npm config
([@isaacs](https://github.com/isaacs))
### BUG FIXES
* [`9eef63849`](https://github.com/npm/cli/commit/9eef638499c88689acb00d812c10f0407cb95c08)
Pass full set of options to login helper functions.
This fixes `npm login --no-strict-ssl`, as well as a host of other
options that one might want to set while logging in.
Reported by: [@toddself](https://github.com/toddself)
([@isaacs](https://github.com/isaacs))
* [`628a554bc`](https://github.com/npm/cli/commit/628a554bc113e4e115d34778bfe8a77cfad1d933)
[#2358](https://github.com/npm/cli/issues/2358)
fix doctor test to work correctly for node pre-release versions
([@nlf](https://github.com/nlf))
* [`be4a0900b`](https://github.com/npm/cli/commit/be4a0900b14b2c6315bf62bed8f5affb648215ae)
[#2360](https://github.com/npm/cli/issues/2360)
raise an error early if publishing without login, registry
([@isaacs](https://github.com/isaacs))
* [`44d433105`](https://github.com/npm/cli/commit/44d4331058c53909ada62470b23b2185102b2128)
[#2366](https://github.com/npm/cli/issues/2366)
Include prerelease versions when deprecating
([@tiegz](https://github.com/tiegz))
* [`cba3341da`](https://github.com/npm/cli/commit/cba3341dae4c92541049dc976e82e2ba19566e95)
[#2373](https://github.com/npm/cli/issues/2373)
npm profile refactor
([@ruyadorno](https://github.com/ruyadorno))
* [`7539504e3`](https://github.com/npm/cli/commit/7539504e3abdec28039a7798e5ccb745b536cb6e)
[#2382](https://github.com/npm/cli/issues/2382)
remove the metrics sender
([@nlf](https://github.com/nlf))
### DOCS
* [`b98569a8c`](https://github.com/npm/cli/commit/b98569a8ca28dbd611fe84492aee996e2e567b55)
add note about `INIT_CWD` to run-script doc
* [`292929279`](https://github.com/npm/cli/commit/292929279854a06ca60ff737b574cbd6503ec5db)
[#2368](https://github.com/npm/cli/issues/2368)
Revert bug-reporting links to GH.
Re: <https://blog.npmjs.org/post/188841555980/updates-to-community-docs-more>
([@tiegz](https://github.com/tiegz))
* [`f4560626f`](https://github.com/npm/cli/commit/f4560626f09dba4889d752f7f739aa5a5f3da741)
update `ISSUE_TEMPLATE` with modern links
([@isaacs](https://github.com/isaacs))
* [`bc1c567ed`](https://github.com/npm/cli/commit/bc1c567ed3d853ed4f01d33a800eb453956de6ef)
update npm command doc feature request links
([@isaacs](https://github.com/isaacs))
* [`0ad958fe1`](https://github.com/npm/cli/commit/0ad958fe1cb811699caca235f361c8328baac8c4)
[#2381](https://github.com/npm/cli/issues/2381)
(docs,test): assorted typo fixes
([@XhmikosR](https://github.com/XhmikosR))
### TESTING
* [`a92d310b7`](https://github.com/npm/cli/commit/a92d310b7e9e4c48b08f52785c2e3a6d52a82ad7)
[#2361](https://github.com/npm/cli/issues/2361)
Add max-len to lint rules
([@Edu93Jer](https://github.com/Edu93Jer))
### DEPENDENCIES
* [`4fc2f3e05`](https://github.com/npm/cli/commit/4fc2f3e05b600aa64fe5eb6b8b77bc070e5a9403)
[#2300](https://github.com/npm/cli/issues/2300)
`@npmcli/config@1.2.8`:
* Support setting email without username/password
## 7.2.0 (2020-12-15)
### FEATURES
@ -977,7 +1049,7 @@
* fix package.json dependencies order
* [`49b2bf5a7`](https://github.com/npm/cli/commit/49b2bf5a798b49d52166744088a80b8a39ccaeb6)
`@npmcli/config@1.1.8`
* fix unkown envs to be passed through
* fix unknown envs to be passed through
* fix setting correct globalPrefix on load
* [`f9aac351d`](https://github.com/npm/cli/commit/f9aac351dd36a19d14e1f951a2e8e20b41545822)
`libnpmversion@1.0.5`

4
deps/npm/Makefile vendored
View File

@ -88,13 +88,13 @@ prune:
@[[ "$(shell git status -s)" != "" ]] && echo "ERR: found unpruned files" && exit 1 || echo "git status is clean"
publish: gitclean ls-ok link test docs-clean docs prune
publish: gitclean ls-ok link test docs prune
@git push origin :v$(shell node bin/npm-cli.js --no-timing -v) 2>&1 || true
git push origin $(BRANCH) &&\
git push origin --tags &&\
node bin/npm-cli.js publish --tag=$(PUBLISHTAG)
release: gitclean ls-ok docs-clean docs prune
release: gitclean ls-ok docs prune
@bash scripts/release.sh
.PHONY: all latest install dev link docs clean uninstall test man docs-clean docsclean release ls-ok dev-deps prune

2
deps/npm/README.md vendored
View File

@ -150,6 +150,8 @@ you should [read this](https://docs.npmjs.com/misc/developers).
When you find issues, please report them:
* web:
<https://github.com/npm/npm/issues>
* archived web:
<https://npm.community/c/bugs>
Be sure to include *all* of the output from the npm command that didn't work

View File

@ -7,15 +7,15 @@ description: Manage the npm configuration files
### Synopsis
```bash
npm config set <key> <value> [-g|--global]
npm config get <key>
npm config delete <key>
npm config list [-l] [--json]
npm config set <key>=<value> [<key>=<value> ...]
npm config get [<key> [<key> ...]]
npm config delete <key> [<key> ...]
npm config list [--json]
npm config edit
npm get <key>
npm set <key> <value> [-g|--global]
npm set <key>=<value> [<key>=<value> ...]
npm get [<key> [<key> ...]]
aliases: c
alias: c
```
### Description
@ -39,20 +39,31 @@ Config supports the following sub-commands:
#### set
```bash
npm config set key value
npm config set key=value [key=value...]
npm set key=value [key=value...]
```
Sets the config key to the value.
Sets each of the config keys to the value provided.
If value is omitted, then it sets it to "true".
If value is omitted, then it sets it to an empty string.
Note: for backwards compatibility, `npm config set key value` is supported
as an alias for `npm config set key=value`.
#### get
```bash
npm config get key
npm config get [key ...]
npm get [key ...]
```
Echo the config value to stdout.
Echo the config value(s) to stdout.
If multiple keys are provided, then the values will be prefixed with the
key names.
If no keys are provided, then this command behaves the same as `npm config
list`.
#### list
@ -66,10 +77,10 @@ to show the settings in json format.
#### delete
```bash
npm config delete key
npm config delete key [key ...]
```
Deletes the key from all configuration files.
Deletes the specified keys from all configuration files.
#### edit

View File

@ -7,7 +7,7 @@ description: Deprecate a version of a package
### Synopsis
```bash
npm deprecate <pkg>[@<version>] <message>
npm deprecate <pkg>[@<version range>] <message>
```
### Description
@ -22,8 +22,17 @@ versions, so you can do something like this:
npm deprecate my-thing@"< 0.2.3" "critical bug fixed in v0.2.3"
```
Note that you must be the package owner to deprecate something. See the
`owner` and `adduser` help topics.
SemVer ranges passed to this command are interpreted such that they *do*
include prerelease versions. For example:
```bash
npm deprecate my-thing@1.x "1.x is no longer supported"
```
In this case, a version `my-thing@1.0.0-beta.0` will also be deprecated.
You must be the package owner to deprecate something. See the `owner` and
`adduser` help topics.
To un-deprecate a package, specify an empty string (`""`) for the `message`
argument. Note that you must use double quotes with no space between them to

View File

@ -60,18 +60,18 @@ on Unix-like systems it is the `/bin/sh` command, on Windows it is the `cmd.exe`
The actual shell referred to by `/bin/sh` also depends on the system.
You can customize the shell with the `script-shell` configuration.
Scripts are run from the root of the module, regardless of what the current
working directory is when `npm run` is called. If you want your script to
use different behavior based on what subdirectory you're in, you can use the
`INIT_CWD` environment variable, which holds the full path you were in when
you ran `npm run`.
Scripts are run from the root of the package folder, regardless of what the
current working directory is when `npm run` is called. If you want your
script to use different behavior based on what subdirectory you're in, you
can use the `INIT_CWD` environment variable, which holds the full path you
were in when you ran `npm run`.
`npm run` sets the `NODE` environment variable to the `node` executable with
which `npm` is executed. Also, if the `--scripts-prepend-node-path` is passed,
the directory within which `node` resides is added to the
`PATH`. If `--scripts-prepend-node-path=auto` is passed (which has been the
default in `npm` v3), this is only performed when that `node` executable is
not found in the `PATH`.
`npm run` sets the `NODE` environment variable to the `node` executable
with which `npm` is executed. Also, if the `--scripts-prepend-node-path` is
passed, the directory within which `node` resides is added to the `PATH`.
If `--scripts-prepend-node-path=auto` is passed (which has been the default
in `npm` v3), this is only performed when that `node` executable is not
found in the `PATH`.
If you try to run a script without having a `node_modules` directory and it fails,
you will be given a warning to run `npm install`, just in case you've forgotten.

View File

@ -143,12 +143,21 @@ the contributing guidelines and check the issues list.
When you find issues, please report them:
* web:
<https://github.com/npm/npm/issues>
* archived web:
<https://npm.community/c/bugs>
Be sure to follow the template and bug reporting guidelines. You can also ask
for help in the [support forum](https://npm.community/c/support) if you're
unsure if it's actually a bug or are having trouble coming up with a detailed
reproduction to report.
Be sure to follow the template and bug reporting guidelines.
### Feature Requests
Discuss new feature ideas on our discussion forum:
* <https://github.com/npm/feedback>
Or suggest formal RFC proposals:
* <https://github.com/npm/rfcs>
### Author

View File

@ -744,13 +744,6 @@ Commit message which is used by `npm version` when creating version commit.
Any "%s" in the message will be replaced with the version number.
#### metrics-registry
* Default: The value of `registry` (which defaults to "https://registry.npmjs.org/")
* Type: String
The registry you want to send cli metrics to if `send-metrics` is true.
#### node-options
* Default: null
@ -1089,16 +1082,6 @@ searches.
The age of the cache, in seconds, before another registry request is made if
using legacy search endpoint.
#### send-metrics
* Default: false
* Type: Boolean
If true, success/failure metrics will be reported to the registry stored in
`metrics-registry`. These requests contain the number of successful and
failing runs of the npm CLI and the time period over which those counts were
gathered. No identifying information is included in these requests.
#### shell
* Default: SHELL environment variable, or "bash" on Posix, or "cmd" on

View File

@ -24,7 +24,7 @@ To create "pre" or "post" scripts for any scripts defined in the `"scripts"` sec
### Life Cycle Scripts
There are some special life cycle scripts that happen only in certain situations. These scripts happen in addtion to the "pre" and "post" script.
There are some special life cycle scripts that happen only in certain situations. These scripts happen in addition to the "pre" and "post" script.
* `prepare`, `prepublish`, `prepublishOnly`, `prepack`, `postpack`
**prepare** (since `npm@4.0.0`)

View File

@ -145,15 +145,15 @@ npm command-line interface
</section>
<div id="_content"><h3 id="synopsis">Synopsis</h3>
<pre lang="bash"><code>npm config set &lt;key&gt; &lt;value&gt; [-g|--global]
npm config get &lt;key&gt;
npm config delete &lt;key&gt;
npm config list [-l] [--json]
<pre lang="bash"><code>npm config set &lt;key&gt;=&lt;value&gt; [&lt;key&gt;=&lt;value&gt; ...]
npm config get [&lt;key&gt; [&lt;key&gt; ...]]
npm config delete &lt;key&gt; [&lt;key&gt; ...]
npm config list [--json]
npm config edit
npm get &lt;key&gt;
npm set &lt;key&gt; &lt;value&gt; [-g|--global]
npm set &lt;key&gt;=&lt;value&gt; [&lt;key&gt;=&lt;value&gt; ...]
npm get [&lt;key&gt; [&lt;key&gt; ...]]
aliases: c
alias: c
</code></pre>
<h3 id="description">Description</h3>
<p>npm gets its config settings from the command line, environment
@ -167,23 +167,30 @@ of the user and global npmrc files.</p>
<h3 id="sub-commands">Sub-commands</h3>
<p>Config supports the following sub-commands:</p>
<h4 id="set">set</h4>
<pre lang="bash"><code>npm config set key value
<pre lang="bash"><code>npm config set key=value [key=value...]
npm set key=value [key=value...]
</code></pre>
<p>Sets the config key to the value.</p>
<p>If value is omitted, then it sets it to “true”.</p>
<p>Sets each of the config keys to the value provided.</p>
<p>If value is omitted, then it sets it to an empty string.</p>
<p>Note: for backwards compatibility, <code>npm config set key value</code> is supported
as an alias for <code>npm config set key=value</code>.</p>
<h4 id="get">get</h4>
<pre lang="bash"><code>npm config get key
<pre lang="bash"><code>npm config get [key ...]
npm get [key ...]
</code></pre>
<p>Echo the config value to stdout.</p>
<p>Echo the config value(s) to stdout.</p>
<p>If multiple keys are provided, then the values will be prefixed with the
key names.</p>
<p>If no keys are provided, then this command behaves the same as <code>npm config list</code>.</p>
<h4 id="list">list</h4>
<pre lang="bash"><code>npm config list
</code></pre>
<p>Show all the config settings. Use <code>-l</code> to also show defaults. Use <code>--json</code>
to show the settings in json format.</p>
<h4 id="delete">delete</h4>
<pre lang="bash"><code>npm config delete key
<pre lang="bash"><code>npm config delete key [key ...]
</code></pre>
<p>Deletes the key from all configuration files.</p>
<p>Deletes the specified keys from all configuration files.</p>
<h4 id="edit2">edit</h4>
<pre lang="bash"><code>npm config edit
</code></pre>

View File

@ -145,7 +145,7 @@ npm command-line interface
</section>
<div id="_content"><h3 id="synopsis">Synopsis</h3>
<pre lang="bash"><code>npm deprecate &lt;pkg&gt;[@&lt;version&gt;] &lt;message&gt;
<pre lang="bash"><code>npm deprecate &lt;pkg&gt;[@&lt;version range&gt;] &lt;message&gt;
</code></pre>
<h3 id="description">Description</h3>
<p>This command will update the npm registry entry for a package, providing a
@ -154,8 +154,13 @@ deprecation warning to all who attempt to install it.</p>
versions, so you can do something like this:</p>
<pre lang="bash"><code>npm deprecate my-thing@"&lt; 0.2.3" "critical bug fixed in v0.2.3"
</code></pre>
<p>Note that you must be the package owner to deprecate something. See the
<code>owner</code> and <code>adduser</code> help topics.</p>
<p>SemVer ranges passed to this command are interpreted such that they <em>do</em>
include prerelease versions. For example:</p>
<pre lang="bash"><code>npm deprecate my-thing@1.x "1.x is no longer supported"
</code></pre>
<p>In this case, a version <code>my-thing@1.0.0-beta.0</code> will also be deprecated.</p>
<p>You must be the package owner to deprecate something. See the <code>owner</code> and
<code>adduser</code> help topics.</p>
<p>To un-deprecate a package, specify an empty string (<code>""</code>) for the <code>message</code>
argument. Note that you must use double quotes with no space between them to
format an empty string.</p>

View File

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

View File

@ -181,17 +181,17 @@ provided by locally-installed dependencies can be used without the
on Unix-like systems it is the <code>/bin/sh</code> command, on Windows it is the <code>cmd.exe</code>.
The actual shell referred to by <code>/bin/sh</code> also depends on the system.
You can customize the shell with the <code>script-shell</code> configuration.</p>
<p>Scripts are run from the root of the module, regardless of what the current
working directory is when <code>npm run</code> is called. If you want your script to
use different behavior based on what subdirectory youre in, you can use the
<code>INIT_CWD</code> environment variable, which holds the full path you were in when
you ran <code>npm run</code>.</p>
<p><code>npm run</code> sets the <code>NODE</code> environment variable to the <code>node</code> executable with
which <code>npm</code> is executed. Also, if the <code>--scripts-prepend-node-path</code> is passed,
the directory within which <code>node</code> resides is added to the
<code>PATH</code>. If <code>--scripts-prepend-node-path=auto</code> is passed (which has been the
default in <code>npm</code> v3), this is only performed when that <code>node</code> executable is
not found in the <code>PATH</code>.</p>
<p>Scripts are run from the root of the package folder, regardless of what the
current working directory is when <code>npm run</code> is called. If you want your
script to use different behavior based on what subdirectory youre in, you
can use the <code>INIT_CWD</code> environment variable, which holds the full path you
were in when you ran <code>npm run</code>.</p>
<p><code>npm run</code> sets the <code>NODE</code> environment variable to the <code>node</code> executable
with which <code>npm</code> is executed. Also, if the <code>--scripts-prepend-node-path</code> is
passed, the directory within which <code>node</code> resides is added to the <code>PATH</code>.
If <code>--scripts-prepend-node-path=auto</code> is passed (which has been the default
in <code>npm</code> v3), this is only performed when that <code>node</code> executable is not
found in the <code>PATH</code>.</p>
<p>If you try to run a script without having a <code>node_modules</code> directory and it fails,
you will be given a warning to run <code>npm install</code>, just in case youve forgotten.</p>
<p>You can use the <code>--silent</code> flag to prevent showing <code>npm ERR!</code> output on error.</p>

View File

@ -141,14 +141,14 @@ 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="#version">Version</a></li><li><a href="#description">Description</a></li><li><a href="#important">Important</a></li><li><a href="#introduction">Introduction</a></li><li><a href="#dependencies">Dependencies</a></li><li><a href="#directories">Directories</a></li><li><a href="#developer-usage">Developer Usage</a></li><ul><li><a href="#configuration">Configuration</a></li></ul><li><a href="#contributions">Contributions</a></li><li><a href="#bugs">Bugs</a></li><li><a href="#author">Author</a></li><li><a href="#see-also">See Also</a></li></ul></div>
<div id="_table_of_contents"><ul><li><a href="#synopsis">Synopsis</a></li><li><a href="#version">Version</a></li><li><a href="#description">Description</a></li><li><a href="#important">Important</a></li><li><a href="#introduction">Introduction</a></li><li><a href="#dependencies">Dependencies</a></li><li><a href="#directories">Directories</a></li><li><a href="#developer-usage">Developer Usage</a></li><ul><li><a href="#configuration">Configuration</a></li></ul><li><a href="#contributions">Contributions</a></li><li><a href="#bugs">Bugs</a></li><li><a href="#feature-requests">Feature Requests</a></li><li><a href="#author">Author</a></li><li><a href="#see-also">See Also</a></li></ul></div>
</section>
<div id="_content"><h3 id="synopsis">Synopsis</h3>
<pre lang="bash"><code>npm &lt;command&gt; [args]
</code></pre>
<h3 id="version">Version</h3>
<p>7.2.0</p>
<p>7.3.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
@ -255,12 +255,20 @@ the contributing guidelines and check the issues list.</p>
<p>When you find issues, please report them:</p>
<ul>
<li>web:
<a href="https://github.com/npm/npm/issues">https://github.com/npm/npm/issues</a></li>
<li>archived web:
<a href="https://npm.community/c/bugs">https://npm.community/c/bugs</a></li>
</ul>
<p>Be sure to follow the template and bug reporting guidelines. You can also ask
for help in the <a href="https://npm.community/c/support">support forum</a> if youre
unsure if its actually a bug or are having trouble coming up with a detailed
reproduction to report.</p>
<p>Be sure to follow the template and bug reporting guidelines.</p>
<h3 id="feature-requests">Feature Requests</h3>
<p>Discuss new feature ideas on our discussion forum:</p>
<ul>
<li><a href="https://github.com/npm/feedback">https://github.com/npm/feedback</a></li>
</ul>
<p>Or suggest formal RFC proposals:</p>
<ul>
<li><a href="https://github.com/npm/rfcs">https://github.com/npm/rfcs</a></li>
</ul>
<h3 id="author">Author</h3>
<p><a href="http://blog.izs.me/">Isaac Z. Schlueter</a> ::
<a href="https://github.com/isaacs/">isaacs</a> ::

File diff suppressed because one or more lines are too long

View File

@ -157,7 +157,7 @@ npm command-line interface
}
</code></pre>
<h3 id="life-cycle-scripts">Life Cycle Scripts</h3>
<p>There are some special life cycle scripts that happen only in certain situations. These scripts happen in addtion to the “pre” and “post” script.</p>
<p>There are some special life cycle scripts that happen only in certain situations. These scripts happen in addition to the “pre” and “post” script.</p>
<ul>
<li><code>prepare</code>, <code>prepublish</code>, <code>prepublishOnly</code>, <code>prepack</code>, <code>postpack</code></li>
</ul>

View File

@ -59,6 +59,7 @@ const adduser = async (args) => {
log.notice('', `Log in on ${replaceInfo(registry)}`)
const { message, newCreds } = await auth({
...npm.flatOptions,
creds,
registry,
scope,

View File

@ -15,13 +15,13 @@ const ini = require('ini')
const usage = usageUtil(
'config',
'npm config set <key> <value>' +
'\nnpm config get [<key>]' +
'\nnpm config delete <key>' +
'npm config set <key>=<value> [<key>=<value> ...]' +
'\nnpm config get [<key> [<key> ...]]' +
'\nnpm config delete <key> [<key> ...]' +
'\nnpm config list [--json]' +
'\nnpm config edit' +
'\nnpm set <key> <value>' +
'\nnpm get [<key>]'
'\nnpm set <key>=<value> [<key>=<value> ...]' +
'\nnpm get [<key> [<key> ...]]'
)
const cmd = (args, cb) => config(args).then(() => cb()).catch(cb)
@ -63,20 +63,20 @@ const completion = (opts, cb) => {
const UsageError = () =>
Object.assign(new Error(usage), { code: 'EUSAGE' })
const config = async ([action, key, val]) => {
const config = async ([action, ...args]) => {
npm.log.disableProgress()
try {
switch (action) {
case 'set':
await set(key, val)
await set(args)
break
case 'get':
await get(key)
await get(args)
break
case 'delete':
case 'rm':
case 'del':
await del(key)
await del(args)
break
case 'list':
case 'ls':
@ -93,46 +93,58 @@ const config = async ([action, key, val]) => {
}
}
const set = async (key, val) => {
if (key === undefined)
// take an array of `[key, value, k2=v2, k3, v3, ...]` and turn into
// { key: value, k2: v2, k3: v3 }
const keyValues = args => {
const kv = {}
for (let i = 0; i < args.length; i++) {
const arg = args[i].split('=')
const key = arg.shift()
const val = arg.length ? arg.join('=')
: i < args.length - 1 ? args[++i]
: ''
kv[key.trim()] = val.trim()
}
return kv
}
const set = async (args) => {
if (!args.length)
throw UsageError()
if (val === undefined) {
if (key.indexOf('=') !== -1) {
const k = key.split('=')
key = k.shift()
val = k.join('=')
} else
val = ''
}
key = key.trim()
val = val.trim()
npm.log.info('config', 'set %j %j', key, val)
const where = npm.flatOptions.global ? 'global' : 'user'
npm.config.set(key, val, where)
if (!npm.config.validate(where))
npm.log.warn('config', 'omitting invalid config values')
for (const [key, val] of Object.entries(keyValues(args))) {
npm.log.info('config', 'set %j %j', key, val)
npm.config.set(key, val || '', where)
if (!npm.config.validate(where))
npm.log.warn('config', 'omitting invalid config values')
}
await npm.config.save(where)
}
const get = async key => {
if (!key)
const get = async keys => {
if (!keys.length)
return list()
if (!publicVar(key))
throw `The ${key} option is protected, and cannot be retrieved in this way`
const out = []
for (const key of keys) {
if (!publicVar(key))
throw `The ${key} option is protected, and cannot be retrieved in this way`
output(npm.config.get(key))
const pref = keys.length > 1 ? `${key}=` : ''
out.push(pref + npm.config.get(key))
}
output(out.join('\n'))
}
const del = async key => {
if (!key)
const del = async keys => {
if (!keys.length)
throw UsageError()
const where = npm.flatOptions.global ? 'global' : 'user'
npm.config.delete(key, where)
for (const key of keys)
npm.config.delete(key, where)
await npm.config.save(where)
}

View File

@ -25,7 +25,8 @@ const completion = (opts, cb) => {
return libaccess.lsPackages(username, npm.flatOptions).then((packages) => {
return Object.keys(packages)
.filter((name) => packages[name] === 'write' &&
(opts.conf.argv.remain.length === 0 || name.startsWith(opts.conf.argv.remain[0]))
(opts.conf.argv.remain.length === 0 ||
name.startsWith(opts.conf.argv.remain[0]))
)
})
}).then((list) => cb(null, list), (err) => cb(err))
@ -57,7 +58,7 @@ const deprecate = async ([pkg, msg]) => {
})
Object.keys(packument.versions)
.filter(v => semver.satisfies(v, spec))
.filter(v => semver.satisfies(v, spec, { includePrerelease: true }))
.forEach(v => {
packument.versions[v].deprecated = msg
})

View File

@ -59,7 +59,8 @@ const getLatestNodejsVersion = async () => {
if (lts && semver.gt(version, maxLTS))
maxLTS = version
if (semver.satisfies(version, currentRange) && semver.gt(version, maxCurrent))
if (semver.satisfies(version, currentRange) &&
semver.gt(version, maxCurrent))
maxCurrent = version
}
const recommended = semver.gt(maxCurrent, maxLTS) ? maxCurrent : maxLTS
@ -175,7 +176,12 @@ const verifyCachedFiles = async () => {
tracker.info('verifyCachedFiles', 'Verifying the npm cache')
try {
const stats = await cacache.verify(npm.flatOptions.cache)
const { badContentCount, reclaimedCount, missingContent, reclaimedSize } = stats
const {
badContentCount,
reclaimedCount,
missingContent,
reclaimedSize,
} = stats
if (badContentCount || reclaimedCount || missingContent) {
if (badContentCount)
tracker.warn('verifyCachedFiles', `Corrupted content removed: ${badContentCount}`)

2
deps/npm/lib/get.js vendored
View File

@ -3,7 +3,7 @@ const usageUtil = require('./utils/usage.js')
const usage = usageUtil(
'get',
'npm get <key> <value> (See `npm config`)'
'npm get [<key> ...] (See `npm config`)'
)
const completion = npm.commands.config.completion

View File

@ -41,8 +41,9 @@ const init = async args => {
}
}
npm.config.set('package', [])
const newArgs = [packageName, ...args.slice(1)]
return new Promise((res, rej) => {
npm.commands.exec([packageName, ...args.slice(1)], er => er ? rej(er) : res())
npm.commands.exec(newArgs, er => er ? rej(er) : res())
})
}

6
deps/npm/lib/npm.js vendored
View File

@ -13,7 +13,8 @@ require('graceful-fs').gracefulify(require('fs'))
const procLogListener = require('./utils/proc-log-listener.js')
const hasOwnProperty = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key)
const hasOwnProperty = (obj, key) =>
Object.prototype.hasOwnProperty.call(obj, key)
// the first time `npm.commands.xyz` is loaded, it gets added
// to the cmds object, so we don't have to load it again.
@ -206,8 +207,6 @@ const npm = module.exports = new class extends EventEmitter {
this.projectScope = this.config.get('scope') ||
getProjectScope(this.prefix)
startMetrics()
}
get flatOptions () {
@ -296,7 +295,6 @@ const npm = module.exports = new class extends EventEmitter {
const log = require('npmlog')
const { promisify } = require('util')
const startMetrics = require('./utils/metrics.js').start
const which = promisify(require('which'))

View File

@ -167,7 +167,7 @@ async function outdated_ (tree, deps, opts) {
}
} catch (err) {
// silently catch and ignore ETARGET, E403 &
// E404 errors, deps are just skipped
// E404 errors, deps are just skipped {
if (!(
err.code === 'ETARGET' ||
err.code === 'E403' ||
@ -234,7 +234,16 @@ function makePretty (dep, opts) {
// <fullpath>:<name@wanted>:<name@installed>:<name@latest>:<dependedby>
function makeParseable (list, opts) {
return list.map(dep => {
const { name, current, wanted, latest, path, dependent, type, homepage } = dep
const {
name,
current,
wanted,
latest,
path,
dependent,
type,
homepage,
} = dep
const out = [
path,
name + '@' + wanted,
@ -252,7 +261,16 @@ function makeParseable (list, opts) {
function makeJSON (list, opts) {
const out = {}
list.forEach(dep => {
const { name, current, wanted, latest, path, type, dependent, homepage } = dep
const {
name,
current,
wanted,
latest,
path,
type,
dependent,
homepage,
} = dep
out[name] = {
current,
wanted,

View File

@ -1,35 +1,36 @@
const ansistyles = require('ansistyles')
const inspect = require('util').inspect
const { URL } = require('url')
const ansistyles = require('ansistyles')
const log = require('npmlog')
const npmProfile = require('npm-profile')
const qrcodeTerminal = require('qrcode-terminal')
const Table = require('cli-table3')
const npm = require('./npm.js')
const otplease = require('./utils/otplease.js')
const output = require('./utils/output.js')
const profile = require('npm-profile')
const pulseTillDone = require('./utils/pulse-till-done.js')
const qrcodeTerminal = require('qrcode-terminal')
const readUserInfo = require('./utils/read-user-info.js')
const Table = require('cli-table3')
const { URL } = require('url')
const usageUtil = require('./utils/usage.js')
module.exports = profileCmd
profileCmd.usage =
'npm profile enable-2fa [auth-only|auth-and-writes]\n' +
'npm profile disable-2fa\n' +
'npm profile get [<key>]\n' +
const usage = usageUtil(
'npm profile enable-2fa [auth-only|auth-and-writes]\n',
'npm profile disable-2fa\n',
'npm profile get [<key>]\n',
'npm profile set <key> <value>'
)
profileCmd.subcommands = ['enable-2fa', 'disable-2fa', 'get', 'set']
profileCmd.completion = function (opts, cb) {
const completion = (opts, cb) => {
var argv = opts.conf.argv.remain
const subcommands = ['enable-2fa', 'disable-2fa', 'get', 'set']
if (!argv[2])
return cb(null, subcommands)
switch (argv[2]) {
case 'enable-2fa':
case 'enable-tfa':
if (argv.length === 3)
return cb(null, ['auth-and-writes', 'auth-only'])
else
return cb(null, [])
return cb(null, ['auth-and-writes', 'auth-only'])
case 'disable-2fa':
case 'disable-tfa':
@ -41,35 +42,33 @@ profileCmd.completion = function (opts, cb) {
}
}
function withCb (prom, cb) {
prom.then((value) => cb(null, value), cb)
}
const cmd = (args, cb) => profile(args).then(() => cb()).catch(cb)
function profileCmd (args, cb) {
const profile = async (args) => {
if (args.length === 0)
return cb(new Error(profileCmd.usage))
throw new Error(usage)
log.gauge.show('profile')
switch (args[0]) {
const [subcmd, ...opts] = args
switch (subcmd) {
case 'enable-2fa':
case 'enable-tfa':
case 'enable2fa':
case 'enabletfa':
withCb(enable2fa(args.slice(1)), cb)
break
return enable2fa(opts)
case 'disable-2fa':
case 'disable-tfa':
case 'disable2fa':
case 'disabletfa':
withCb(disable2fa(), cb)
break
return disable2fa()
case 'get':
withCb(get(args.slice(1)), cb)
break
return get(opts)
case 'set':
withCb(set(args.slice(1)), cb)
break
return set(opts)
default:
cb(new Error('Unknown profile command: ' + args[0]))
throw new Error('Unknown profile command: ' + subcmd)
}
}
@ -86,52 +85,62 @@ const knownProfileKeys = [
'updated',
]
function get (args) {
const get = async args => {
const tfa = 'two-factor auth'
const conf = npm.flatOptions
return pulseTillDone.withPromise(profile.get(conf)).then((info) => {
if (!info.cidr_whitelist)
delete info.cidr_whitelist
if (conf.json) {
output(JSON.stringify(info, null, 2))
return
}
const cleaned = {}
knownProfileKeys.forEach((k) => {
cleaned[k] = info[k] || ''
})
Object.keys(info).filter((k) => !(k in cleaned)).forEach((k) => {
cleaned[k] = info[k] || ''
})
delete cleaned.tfa
delete cleaned.email_verified
cleaned.email += info.email_verified ? ' (verified)' : '(unverified)'
if (info.tfa && !info.tfa.pending)
cleaned[tfa] = info.tfa.mode
else
cleaned[tfa] = 'disabled'
const conf = { ...npm.flatOptions }
if (args.length) {
const values = args // comma or space separated ↓
.join(',').split(/,/).map((arg) => arg.trim()).filter((arg) => arg !== '')
.map((arg) => cleaned[arg])
.join('\t')
output(values)
} else {
if (conf.parseable) {
Object.keys(info).forEach((key) => {
if (key === 'tfa')
output(`${key}\t${cleaned[tfa]}`)
else
output(`${key}\t${info[key]}`)
})
} else {
const table = new Table()
Object.keys(cleaned).forEach((k) => table.push({ [ansistyles.bright(k)]: cleaned[k] }))
output(table.toString())
const info = await pulseTillDone.withPromise(npmProfile.get(conf))
if (!info.cidr_whitelist)
delete info.cidr_whitelist
if (conf.json) {
output(JSON.stringify(info, null, 2))
return
}
// clean up and format key/values for output
const cleaned = {}
for (const key of knownProfileKeys)
cleaned[key] = info[key] || ''
const unknownProfileKeys = Object.keys(info).filter((k) => !(k in cleaned))
for (const key of unknownProfileKeys)
cleaned[key] = info[key] || ''
delete cleaned.tfa
delete cleaned.email_verified
cleaned.email += info.email_verified ? ' (verified)' : '(unverified)'
if (info.tfa && !info.tfa.pending)
cleaned[tfa] = info.tfa.mode
else
cleaned[tfa] = 'disabled'
if (args.length) {
const values = args // comma or space separated
.join(',')
.split(/,/)
.filter((arg) => arg.trim() !== '')
.map((arg) => cleaned[arg])
.join('\t')
output(values)
} else {
if (conf.parseable) {
for (const key of Object.keys(info)) {
if (key === 'tfa')
output(`${key}\t${cleaned[tfa]}`)
else
output(`${key}\t${info[key]}`)
}
} else {
const table = new Table()
for (const key of Object.keys(cleaned))
table.push({ [ansistyles.bright(key)]: cleaned[key] })
output(table.toString())
}
})
}
}
const writableProfileKeys = [
@ -144,83 +153,87 @@ const writableProfileKeys = [
'github',
]
function set (args) {
const conf = npm.flatOptions
const set = async (args) => {
const conf = { ...npm.flatOptions }
const prop = (args[0] || '').toLowerCase().trim()
let value = args.length > 1 ? args.slice(1).join(' ') : null
const readPasswords = async () => {
const newpassword = await readUserInfo.password('New password: ')
const confirmedpassword = await readUserInfo.password(' Again: ')
if (newpassword !== confirmedpassword) {
log.warn('profile', 'Passwords do not match, please try again.')
return readPasswords()
}
return newpassword
}
if (prop !== 'password' && value === null)
return Promise.reject(Error('npm profile set <prop> <value>'))
throw new Error('npm profile set <prop> <value>')
if (prop === 'password' && value !== null) {
return Promise.reject(Error(
throw new Error(
'npm profile set password\n' +
'Do not include your current or new passwords on the command line.'))
'Do not include your current or new passwords on the command line.')
}
if (writableProfileKeys.indexOf(prop) === -1)
return Promise.reject(Error(`"${prop}" is not a property we can set. Valid properties are: ` + writableProfileKeys.join(', ')))
return Promise.resolve().then(() => {
if (prop === 'password') {
return readUserInfo.password('Current password: ').then((current) => {
return readPasswords().then((newpassword) => {
value = { old: current, new: newpassword }
})
})
} else if (prop === 'email') {
return readUserInfo.password('Password: ').then((current) => {
return { password: current, email: value }
})
}
function readPasswords () {
return readUserInfo.password('New password: ').then((password1) => {
return readUserInfo.password(' Again: ').then((password2) => {
if (password1 !== password2) {
log.warn('profile', 'Passwords do not match, please try again.')
return readPasswords()
}
return password1
})
})
}
}).then(() => {
// FIXME: Work around to not clear everything other than what we're setting
return pulseTillDone.withPromise(profile.get(conf).then((user) => {
const newUser = {}
writableProfileKeys.forEach((k) => {
newUser[k] = user[k]
})
newUser[prop] = value
return otplease(conf, conf => profile.set(newUser, conf))
.then((result) => {
if (conf.json)
output(JSON.stringify({ [prop]: result[prop] }, null, 2))
else if (conf.parseable)
output(prop + '\t' + result[prop])
else if (result[prop] != null)
output('Set', prop, 'to', result[prop])
else
output('Set', prop)
})
}))
})
if (writableProfileKeys.indexOf(prop) === -1) {
throw new Error(`"${prop}" is not a property we can set. ` +
`Valid properties are: ` + writableProfileKeys.join(', '))
}
if (prop === 'password') {
const current = await readUserInfo.password('Current password: ')
const newpassword = await readPasswords()
value = { old: current, new: newpassword }
}
// FIXME: Work around to not clear everything other than what we're setting
const user = await pulseTillDone.withPromise(npmProfile.get(conf))
const newUser = {}
for (const key of writableProfileKeys)
newUser[key] = user[key]
newUser[prop] = value
const result = await otplease(conf, conf => npmProfile.set(newUser, conf))
if (conf.json)
output(JSON.stringify({ [prop]: result[prop] }, null, 2))
else if (conf.parseable)
output(prop + '\t' + result[prop])
else if (result[prop] != null)
output('Set', prop, 'to', result[prop])
else
output('Set', prop)
}
function enable2fa (args) {
const enable2fa = async (args) => {
if (args.length > 1)
return Promise.reject(new Error('npm profile enable-2fa [auth-and-writes|auth-only]'))
throw new Error('npm profile enable-2fa [auth-and-writes|auth-only]')
const mode = args[0] || 'auth-and-writes'
if (mode !== 'auth-only' && mode !== 'auth-and-writes') {
return Promise.reject(new Error(`Invalid two-factor authentication mode "${mode}".\n` +
throw new Error(
`Invalid two-factor authentication mode "${mode}".\n` +
'Valid modes are:\n' +
' auth-only - Require two-factor authentication only when logging in\n' +
' auth-and-writes - Require two-factor authentication when logging in AND when publishing'))
' auth-and-writes - Require two-factor authentication when logging in ' +
'AND when publishing'
)
}
const conf = npm.flatOptions
const conf = { ...npm.flatOptions }
if (conf.json || conf.parseable) {
return Promise.reject(new Error(
throw new Error(
'Enabling two-factor authentication is an interactive operation and ' +
(conf.json ? 'JSON' : 'parseable') + ' output mode is not available'))
(conf.json ? 'JSON' : 'parseable') + ' output mode is not available'
)
}
const info = {
@ -229,119 +242,153 @@ function enable2fa (args) {
},
}
return Promise.resolve().then(() => {
// if they're using legacy auth currently then we have to update them to a
// bearer token before continuing.
const auth = getAuth(conf)
if (auth.basic) {
log.info('profile', 'Updating authentication to bearer token')
return profile.createToken(
auth.basic.password, false, [], conf
).then((result) => {
if (!result.token) {
throw new Error(`Your registry ${conf.registry} does not seem to ` +
'support bearer tokens. Bearer tokens are required for ' +
'two-factor authentication')
}
npm.config.setCredentialsByURI(conf.registry, { token: result.token })
return npm.config.save('user')
})
}
}).then(() => {
log.notice('profile', 'Enabling two factor authentication for ' + mode)
return readUserInfo.password()
}).then((password) => {
info.tfa.password = password
log.info('profile', 'Determine if tfa is pending')
return pulseTillDone.withPromise(profile.get(conf)).then((info) => {
if (!info.tfa)
return
if (info.tfa.pending) {
log.info('profile', 'Resetting two-factor authentication')
return pulseTillDone.withPromise(profile.set({ tfa: { password, mode: 'disable' } }, conf))
} else {
if (conf.auth.otp)
return
return readUserInfo.otp('Enter one-time password from your authenticator app: ').then((otp) => {
conf.auth.otp = otp
})
}
})
}).then(() => {
log.info('profile', 'Setting two-factor authentication to ' + mode)
return pulseTillDone.withPromise(profile.set(info, conf))
}).then((challenge) => {
if (challenge.tfa === null) {
output('Two factor authentication mode changed to: ' + mode)
return
}
if (typeof challenge.tfa !== 'string' || !/^otpauth:[/][/]/.test(challenge.tfa))
throw new Error('Unknown error enabling two-factor authentication. Expected otpauth URL, got: ' + inspect(challenge.tfa))
// if they're using legacy auth currently then we have to
// update them to a bearer token before continuing.
const auth = getAuth(conf)
const otpauth = new URL(challenge.tfa)
const secret = otpauth.searchParams.get('secret')
return qrcode(challenge.tfa).then((code) => {
output('Scan into your authenticator app:\n' + code + '\n Or enter code:', secret)
}).then((code) => {
return readUserInfo.otp('And an OTP code from your authenticator: ')
}).then((otp1) => {
log.info('profile', 'Finalizing two-factor authentication')
return profile.set({ tfa: [otp1] }, conf)
}).then((result) => {
output('2FA successfully enabled. Below are your recovery codes, please print these out.')
output('You will need these to recover access to your account if you lose your authentication device.')
result.tfa.forEach((c) => output('\t' + c))
})
})
if (!auth.basic && !auth.token) {
throw new Error(
'You need to be logged in to registry ' +
`${conf.registry} in order to enable 2fa`
)
}
if (auth.basic) {
log.info('profile', 'Updating authentication to bearer token')
const result = await npmProfile.createToken(
auth.basic.password, false, [], conf
)
if (!result.token) {
throw new Error(
`Your registry ${conf.registry} does not seem to ` +
'support bearer tokens. Bearer tokens are required for ' +
'two-factor authentication'
)
}
npm.config.setCredentialsByURI(conf.registry, { token: result.token })
await npm.config.save('user')
}
log.notice('profile', 'Enabling two factor authentication for ' + mode)
const password = await readUserInfo.password()
info.tfa.password = password
log.info('profile', 'Determine if tfa is pending')
const userInfo = await pulseTillDone.withPromise(npmProfile.get(conf))
if (userInfo && userInfo.tfa && userInfo.tfa.pending) {
log.info('profile', 'Resetting two-factor authentication')
await pulseTillDone.withPromise(
npmProfile.set({ tfa: { password, mode: 'disable' } }, conf)
)
} else if (userInfo && userInfo.tfa) {
if (conf.otp)
conf.otp = conf.otp
else {
const otp = await readUserInfo.otp(
'Enter one-time password from your authenticator app: '
)
conf.otp = otp
}
}
log.info('profile', 'Setting two-factor authentication to ' + mode)
const challenge = await pulseTillDone.withPromise(npmProfile.set(info, conf))
if (challenge.tfa === null) {
output('Two factor authentication mode changed to: ' + mode)
return
}
const badResponse = typeof challenge.tfa !== 'string'
|| !/^otpauth:[/][/]/.test(challenge.tfa)
if (badResponse) {
throw new Error(
'Unknown error enabling two-factor authentication. Expected otpauth URL' +
', got: ' + inspect(challenge.tfa)
)
}
const otpauth = new URL(challenge.tfa)
const secret = otpauth.searchParams.get('secret')
const code = await qrcode(challenge.tfa)
output(
'Scan into your authenticator app:\n' + code + '\n Or enter code:', secret
)
const interactiveOTP =
await readUserInfo.otp('And an OTP code from your authenticator: ')
log.info('profile', 'Finalizing two-factor authentication')
const result = await npmProfile.set({ tfa: [interactiveOTP] }, conf)
output(
'2FA successfully enabled. Below are your recovery codes, ' +
'please print these out.'
)
output(
'You will need these to recover access to your account ' +
'if you lose your authentication device.'
)
for (const tfaCode of result.tfa)
output('\t' + tfaCode)
}
function getAuth (conf) {
const getAuth = conf => {
const creds = npm.config.getCredentialsByURI(conf.registry)
let auth
const auth = {}
if (creds.token)
auth = { token: creds.token }
auth.token = creds.token
else if (creds.username)
auth = { basic: { username: creds.username, password: creds.password } }
auth.basic = { username: creds.username, password: creds.password }
else if (creds.auth) {
const basic = Buffer.from(creds.auth, 'base64').toString().split(':', 2)
auth = { basic: { username: basic[0], password: basic[1] } }
} else
auth = {}
auth.basic = { username: basic[0], password: basic[1] }
}
if (conf.otp)
auth.otp = conf.otp
return auth
}
function disable2fa (args) {
let conf = npm.flatOptions
return pulseTillDone.withPromise(profile.get(conf)).then((info) => {
if (!info.tfa || info.tfa.pending) {
output('Two factor authentication not enabled.')
return
}
return readUserInfo.password().then((password) => {
return Promise.resolve().then(() => {
if (conf.otp)
return
return readUserInfo.otp('Enter one-time password from your authenticator: ').then((otp) => {
conf = { ...conf, otp }
})
}).then(() => {
log.info('profile', 'disabling tfa')
return pulseTillDone.withPromise(profile.set({ tfa: { password: password, mode: 'disable' } }, conf)).then(() => {
if (conf.json)
output(JSON.stringify({ tfa: false }, null, 2))
else if (conf.parseable)
output('tfa\tfalse')
else
output('Two factor authentication disabled.')
})
})
})
})
const disable2fa = async args => {
const conf = { ...npm.flatOptions }
const info = await pulseTillDone.withPromise(npmProfile.get(conf))
if (!info.tfa || info.tfa.pending) {
output('Two factor authentication not enabled.')
return
}
const password = await readUserInfo.password()
if (!conf.otp) {
const msg = 'Enter one-time password from your authenticator app: '
conf.otp = await readUserInfo.otp(msg)
}
log.info('profile', 'disabling tfa')
await pulseTillDone.withPromise(npmProfile.set({
tfa: { password: password, mode: 'disable' },
}, conf))
if (conf.json)
output(JSON.stringify({ tfa: false }, null, 2))
else if (conf.parseable)
output('tfa\tfalse')
else
output('Two factor authentication disabled.')
}
function qrcode (url) {
return new Promise((resolve) => qrcodeTerminal.generate(url, resolve))
}
const qrcode = url =>
new Promise((resolve) => qrcodeTerminal.generate(url, resolve))
module.exports = Object.assign(cmd, { usage, completion })

View File

@ -35,7 +35,21 @@ const publish = async args => {
log.verbose('publish', args)
const opts = { ...npm.flatOptions }
const { json, defaultTag } = opts
const { json, defaultTag, registry } = opts
if (!registry) {
throw Object.assign(new Error('No registry specified.'), {
code: 'ENOREGISTRY',
})
}
const creds = npm.config.getCredentialsByURI(registry)
if (!creds.token && !creds.username) {
throw Object.assign(new Error('This command requires you to be logged in.'), {
code: 'ENEEDAUTH',
})
}
if (semver.validRange(defaultTag))
throw new Error('Tag name must not be a valid SemVer range: ' + defaultTag.trim())

View File

@ -36,7 +36,8 @@ const getRepo = async pkg => {
}
const info = hostedFromMani(mani)
const url = info ? info.browse(mani.repository.directory) : unknownHostedUrl(rurl)
const url = info ?
info.browse(mani.repository.directory) : unknownHostedUrl(rurl)
if (!url) {
throw Object.assign(new Error('no repository: could not get url'), {

2
deps/npm/lib/set.js vendored
View File

@ -1,7 +1,7 @@
module.exports = set
set.usage = 'npm set <key> <value> (See `npm config`)'
set.usage = 'npm set <key>=<value> [<key>=<value> ...] (See `npm config`)'
var npm = require('./npm.js')

19
deps/npm/lib/token.js vendored
View File

@ -74,16 +74,19 @@ function token (args, cb) {
function generateTokenIds (tokens, minLength) {
const byId = {}
tokens.forEach((token) => {
for (const token of tokens) {
token.id = token.key
for (let ii = minLength; ii < token.key.length; ++ii) {
if (!tokens.some((ot) => ot !== token && ot.key.slice(0, ii) === token.key.slice(0, ii))) {
const match = tokens.some(ot =>
ot !== token &&
ot.key.slice(0, ii) === token.key.slice(0, ii))
if (!match) {
token.id = token.key.slice(0, ii)
break
}
}
byId[token.id] = token
})
}
return byId
}
@ -136,7 +139,8 @@ function list (args) {
return
}
generateTokenIds(tokens, 6)
const idWidth = tokens.reduce((acc, token) => Math.max(acc, token.id.length), 0)
const idWidth = tokens.reduce((acc, token) =>
Math.max(acc, token.id.length), 0)
const table = new Table({
head: ['id', 'token', 'created', 'readonly', 'CIDR whitelist'],
colWidths: [Math.max(idWidth, 2) + 2, 9, 12, 10],
@ -170,8 +174,8 @@ function rm (args) {
else if (matches.length > 1)
throw new Error(`Token ID "${id}" was ambiguous, a new token may have been created since you last ran \`npm token list\`.`)
else {
const tokenMatches = tokens.filter((token) => id.indexOf(token.token) === 0)
if (tokenMatches.length === 0)
const tokenMatches = tokens.some(t => id.indexOf(t.token) === 0)
if (!tokenMatches)
throw new Error(`Unknown token id or value "${id}".`)
toRemove.push(id)
@ -212,7 +216,8 @@ function create (args) {
Object.keys(result).forEach((k) => output(k + '\t' + result[k]))
else {
const table = new Table()
Object.keys(result).forEach((k) => table.push({ [ansistyles.bright(k)]: String(result[k]) }))
for (const k of Object.keys(result))
table.push({ [ansistyles.bright(k)]: String(result[k]) })
output(table.toString())
}
})

View File

@ -93,8 +93,8 @@ async function unpublish (args) {
const { name, version, publishConfig } = manifest
const pkgJsonSpec = npa.resolve(name, version)
res = await otplease(opts, opts => libunpub(pkgJsonSpec, { ...opts, publishConfig }))
const optsWithPub = { ...opts, publishConfig }
res = await otplease(opts, opts => libunpub(pkgJsonSpec, optsWithPub))
pkgName = name
pkgVersion = version ? `@${version}` : ''
} else {

View File

@ -120,7 +120,6 @@ const defaults = {
long: false,
maxsockets: 50,
message: '%s',
'metrics-registry': null,
'node-options': null,
'node-version': process.version,
noproxy: null,
@ -159,7 +158,6 @@ const defaults = {
searchlimit: 20,
searchopts: '',
searchstaleness: 15 * 60,
'send-metrics': false,
shell,
shrinkwrap: true,
'sign-git-commit': false,
@ -273,7 +271,6 @@ const types = {
long: Boolean,
maxsockets: Number,
message: String,
'metrics-registry': [null, String],
'node-options': [null, String],
'node-version': [null, semver],
noproxy: [null, String, Array],
@ -312,7 +309,6 @@ const types = {
searchlimit: Number,
searchopts: String,
searchstaleness: Number,
'send-metrics': Boolean,
shell: String,
shrinkwrap: Boolean,
'sign-git-commit': Boolean,

View File

@ -7,7 +7,6 @@ let wroteLogFile = false
let exitCode = 0
const errorMessage = require('./error-message.js')
const replaceInfo = require('./replace-info.js')
const stopMetrics = require('./metrics.js').stop
const cacheFile = require('./cache-file.js')
@ -43,9 +42,6 @@ process.on('exit', code => {
}
}
// kill any outstanding stats reporter if it hasn't finished yet
stopMetrics()
if (code)
itWorked = false
if (itWorked)

View File

@ -193,10 +193,14 @@ module.exports = (er) => {
else {
detail.push(['404', 'This package name is not valid, because', ''])
const errorsArray = (valResult.errors || []).concat(valResult.warnings || [])
errorsArray.forEach(function (item, idx) {
detail.push(['404', ' ' + (idx + 1) + '. ' + item])
})
const errorsArray = [
...(valResult.errors || []),
...(valResult.warnings || []),
]
errorsArray.forEach((item, idx) => detail.push([
'404',
' ' + (idx + 1) + '. ' + item,
]))
}
detail.push(['404', '\nNote that you can also install from a'])

View File

@ -3,6 +3,8 @@ const util = require('util')
const stat = util.promisify(fs.stat)
const fileExists = (file) => stat(file).then((stat) => stat.isFile()).catch(() => false)
const fileExists = (file) => stat(file)
.then((stat) => stat.isFile())
.catch(() => false)
module.exports = fileExists

View File

@ -50,8 +50,6 @@ const flatten = obj => ({
cache: join(obj.cache, '_cacache'),
global: obj.global,
metricsRegistry: obj['metrics-registry'] || obj.registry,
sendMetrics: obj['send-metrics'],
registry: obj.registry,
scope: obj.scope,
access: obj.access,

View File

@ -1,43 +0,0 @@
/* eslint-disable camelcase */
module.exports = launchSendMetrics
var fs = require('graceful-fs')
var child_process = require('child_process')
if (require.main === module)
main()
function launchSendMetrics () {
var path = require('path')
var npm = require('../npm.js')
try {
if (!npm.config.get('send-metrics'))
return
var cliMetrics = path.join(npm.config.get('cache'), 'anonymous-cli-metrics.json')
var targetRegistry = npm.config.get('metrics-registry')
fs.statSync(cliMetrics)
return runInBackground(__filename, [cliMetrics, targetRegistry])
} catch (ex) {
// if the metrics file doesn't exist, don't run
}
}
function runInBackground (js, args, opts) {
if (!args)
args = []
args.unshift(js)
if (!opts)
opts = {}
opts.stdio = 'ignore'
opts.detached = true
var child = child_process.spawn(process.execPath, args, opts)
child.unref()
return child
}
function main () {
var sendMetrics = require('./metrics.js').send
var metricsFile = process.argv[2]
var metricsRegistry = process.argv[3]
sendMetrics(metricsFile, metricsRegistry)
}

View File

@ -1,80 +0,0 @@
exports.start = startMetrics
exports.stop = stopMetrics
exports.save = saveMetrics
exports.send = sendMetrics
const fs = require('fs')
const path = require('path')
const npm = require('../npm.js')
const regFetch = require('npm-registry-fetch')
const { v4: uuidv4 } = require('uuid')
const cacheFile = require('./cache-file.js')
let inMetrics = false
function startMetrics () {
if (inMetrics)
return
// loaded on demand to avoid any recursive deps when `./metrics-launch` requires us.
var metricsLaunch = require('./metrics-launch.js')
npm.metricsProcess = metricsLaunch()
}
function stopMetrics () {
if (inMetrics)
return
if (npm.metricsProcess)
npm.metricsProcess.kill('SIGKILL')
}
function saveMetrics (itWorked) {
if (inMetrics)
return
// If the metrics reporter hasn't managed to PUT yet then kill it so that it doesn't
// step on our updating the anonymous-cli-metrics json
stopMetrics()
var metricsFile = path.join(npm.config.get('cache'), 'anonymous-cli-metrics.json')
var metrics
try {
metrics = JSON.parse(fs.readFileSync(metricsFile))
metrics.metrics.to = new Date().toISOString()
if (itWorked)
++metrics.metrics.successfulInstalls
else
++metrics.metrics.failedInstalls
} catch (ex) {
metrics = {
metricId: uuidv4(),
metrics: {
from: new Date().toISOString(),
to: new Date().toISOString(),
successfulInstalls: itWorked ? 1 : 0,
failedInstalls: itWorked ? 0 : 1,
},
}
}
try {
cacheFile.write(metricsFile, JSON.stringify(metrics))
} catch (ex) {
// we couldn't write and/or chown the error metrics file, oh well.
}
}
function sendMetrics (metricsFile, metricsRegistry) {
inMetrics = true
var cliMetrics = JSON.parse(fs.readFileSync(metricsFile))
regFetch(
`/-/npm/anon-metrics/v1/${encodeURIComponent(cliMetrics.metricId)}`,
// NOTE: skip npmConfig() to prevent auth
{
registry: metricsRegistry,
method: 'PUT',
body: cliMetrics.metrics,
retry: false,
}
).then(() => {
fs.unlinkSync(metricsFile)
}, err => {
cacheFile.write(path.join(path.dirname(metricsFile), 'last-send-metrics-error.txt'), err.stack)
})
}

View File

@ -1,7 +1,7 @@
// pass in an arborist object, and it'll output the data about what
// was done, what was audited, etc.
//
// added 351 packages, removed 132 packages, and audited 13388 packages in 19.157s
// added ## packages, removed ## packages, and audited ## packages in 19.157s
//
// 1 package is looking for funding
// run `npm fund` for details

13
deps/npm/lib/view.js vendored
View File

@ -196,7 +196,8 @@ const prettyView = async (packument, manifest, opts) => {
name: color.yellow(manifest._npmUser.name),
email: color.cyan(manifest._npmUser.email),
}),
modified: packument.time ? color.yellow(relativeDate(packument.time[packument.version])) : undefined,
modified: !packument.time ? undefined
: color.yellow(relativeDate(packument.time[packument.version])),
maintainers: (packument.maintainers || []).map((u) => unparsePerson({
name: color.yellow(u.name),
email: color.cyan(u.email),
@ -387,8 +388,14 @@ async function printData (data, name, opts) {
if (includeVersions || includeFields || typeof d !== 'string') {
if (opts.json)
msgJson[msgJson.length - 1][f] = d
else
d = inspect(d, { showHidden: false, depth: 5, colors: npm.color, maxArrayLength: null })
else {
d = inspect(d, {
showHidden: false,
depth: 5,
colors: npm.color,
maxArrayLength: null,
})
}
} else if (typeof d === 'string' && opts.json)
d = JSON.stringify(d)

View File

@ -5,15 +5,15 @@
.P
.RS 2
.nf
npm config set <key> <value> [\-g|\-\-global]
npm config get <key>
npm config delete <key>
npm config list [\-l] [\-\-json]
npm config set <key>=<value> [<key>=<value> \.\.\.]
npm config get [<key> [<key> \.\.\.]]
npm config delete <key> [<key> \.\.\.]
npm config list [\-\-json]
npm config edit
npm get <key>
npm set <key> <value> [\-g|\-\-global]
npm set <key>=<value> [<key>=<value> \.\.\.]
npm get [<key> [<key> \.\.\.]]
aliases: c
alias: c
.fi
.RE
.SS Description
@ -36,22 +36,33 @@ Config supports the following sub\-commands:
.P
.RS 2
.nf
npm config set key value
npm config set key=value [key=value\.\.\.]
npm set key=value [key=value\.\.\.]
.fi
.RE
.P
Sets the config key to the value\.
Sets each of the config keys to the value provided\.
.P
If value is omitted, then it sets it to "true"\.
If value is omitted, then it sets it to an empty string\.
.P
Note: for backwards compatibility, \fBnpm config set key value\fP is supported
as an alias for \fBnpm config set key=value\fP\|\.
.SS get
.P
.RS 2
.nf
npm config get key
npm config get [key \.\.\.]
npm get [key \.\.\.]
.fi
.RE
.P
Echo the config value to stdout\.
Echo the config value(s) to stdout\.
.P
If multiple keys are provided, then the values will be prefixed with the
key names\.
.P
If no keys are provided, then this command behaves the same as \fBnpm config
list\fP\|\.
.SS list
.P
.RS 2
@ -66,11 +77,11 @@ to show the settings in json format\.
.P
.RS 2
.nf
npm config delete key
npm config delete key [key \.\.\.]
.fi
.RE
.P
Deletes the key from all configuration files\.
Deletes the specified keys from all configuration files\.
.SS edit
.P
.RS 2

View File

@ -5,7 +5,7 @@
.P
.RS 2
.nf
npm deprecate <pkg>[@<version>] <message>
npm deprecate <pkg>[@<version range>] <message>
.fi
.RE
.SS Description
@ -22,8 +22,19 @@ npm deprecate my\-thing@"< 0\.2\.3" "critical bug fixed in v0\.2\.3"
.fi
.RE
.P
Note that you must be the package owner to deprecate something\. See the
\fBowner\fP and \fBadduser\fP help topics\.
SemVer ranges passed to this command are interpreted such that they \fIdo\fR
include prerelease versions\. For example:
.P
.RS 2
.nf
npm deprecate my\-thing@1\.x "1\.x is no longer supported"
.fi
.RE
.P
In this case, a version \fBmy\-thing@1\.0\.0\-beta\.0\fP will also be deprecated\.
.P
You must be the package owner to deprecate something\. See the \fBowner\fP and
\fBadduser\fP help topics\.
.P
To un\-deprecate a package, specify an empty string (\fB""\fP) for the \fBmessage\fP
argument\. Note that you must use double quotes with no space between them to

View File

@ -26,7 +26,7 @@ example, running \fBnpm ls promzard\fP in npm's source tree will show:
.P
.RS 2
.nf
npm@7\.2\.0 /path/to/npm
npm@7\.3\.0 /path/to/npm
└─┬ init\-package\-json@0\.0\.4
└── promzard@0\.1\.5
.fi

View File

@ -64,18 +64,18 @@ on Unix\-like systems it is the \fB/bin/sh\fP command, on Windows it is the \fBc
The actual shell referred to by \fB/bin/sh\fP also depends on the system\.
You can customize the shell with the \fBscript\-shell\fP configuration\.
.P
Scripts are run from the root of the module, regardless of what the current
working directory is when \fBnpm run\fP is called\. If you want your script to
use different behavior based on what subdirectory you're in, you can use the
\fBINIT_CWD\fP environment variable, which holds the full path you were in when
you ran \fBnpm run\fP\|\.
Scripts are run from the root of the package folder, regardless of what the
current working directory is when \fBnpm run\fP is called\. If you want your
script to use different behavior based on what subdirectory you're in, you
can use the \fBINIT_CWD\fP environment variable, which holds the full path you
were in when you ran \fBnpm run\fP\|\.
.P
\fBnpm run\fP sets the \fBNODE\fP environment variable to the \fBnode\fP executable with
which \fBnpm\fP is executed\. Also, if the \fB\-\-scripts\-prepend\-node\-path\fP is passed,
the directory within which \fBnode\fP resides is added to the
\fBPATH\fP\|\. If \fB\-\-scripts\-prepend\-node\-path=auto\fP is passed (which has been the
default in \fBnpm\fP v3), this is only performed when that \fBnode\fP executable is
not found in the \fBPATH\fP\|\.
\fBnpm run\fP sets the \fBNODE\fP environment variable to the \fBnode\fP executable
with which \fBnpm\fP is executed\. Also, if the \fB\-\-scripts\-prepend\-node\-path\fP is
passed, the directory within which \fBnode\fP resides is added to the \fBPATH\fP\|\.
If \fB\-\-scripts\-prepend\-node\-path=auto\fP is passed (which has been the default
in \fBnpm\fP v3), this is only performed when that \fBnode\fP executable is not
found in the \fBPATH\fP\|\.
.P
If you try to run a script without having a \fBnode_modules\fP directory and it fails,
you will be given a warning to run \fBnpm install\fP, just in case you've forgotten\.

View File

@ -10,7 +10,7 @@ npm <command> [args]
.RE
.SS Version
.P
7\.2\.0
7\.3\.0
.SS Description
.P
npm is the package manager for the Node JavaScript platform\. It puts
@ -155,14 +155,29 @@ When you find issues, please report them:
.RS 0
.IP \(bu 2
web:
https://github\.com/npm/npm/issues
.IP \(bu 2
archived web:
https://npm\.community/c/bugs
.RE
.P
Be sure to follow the template and bug reporting guidelines\. You can also ask
for help in the support forum \fIhttps://npm\.community/c/support\fR if you're
unsure if it's actually a bug or are having trouble coming up with a detailed
reproduction to report\.
Be sure to follow the template and bug reporting guidelines\.
.SS Feature Requests
.P
Discuss new feature ideas on our discussion forum:
.RS 0
.IP \(bu 2
https://github\.com/npm/feedback
.RE
.P
Or suggest formal RFC proposals:
.RS 0
.IP \(bu 2
https://github\.com/npm/rfcs
.RE
.SS Author
.P
Isaac Z\. Schlueter \fIhttp://blog\.izs\.me/\fR ::

View File

@ -1005,16 +1005,6 @@ Type: String
Commit message which is used by \fBnpm version\fP when creating version commit\.
.P
Any "%s" in the message will be replaced with the version number\.
.SS metrics\-registry
.RS 0
.IP \(bu 2
Default: The value of \fBregistry\fP (which defaults to "https://registry\.npmjs\.org/")
.IP \(bu 2
Type: String
.RE
.P
The registry you want to send cli metrics to if \fBsend\-metrics\fP is true\.
.SS node\-options
.RS 0
.IP \(bu 2
@ -1462,19 +1452,6 @@ Type: Number
.P
The age of the cache, in seconds, before another registry request is made if
using legacy search endpoint\.
.SS send\-metrics
.RS 0
.IP \(bu 2
Default: false
.IP \(bu 2
Type: Boolean
.RE
.P
If true, success/failure metrics will be reported to the registry stored in
\fBmetrics\-registry\fP\|\. These requests contain the number of successful and
failing runs of the npm CLI and the time period over which those counts were
gathered\. No identifying information is included in these requests\.
.SS shell
.RS 0
.IP \(bu 2

View File

@ -21,7 +21,7 @@ To create "pre" or "post" scripts for any scripts defined in the \fB"scripts"\fP
.RE
.SS Life Cycle Scripts
.P
There are some special life cycle scripts that happen only in certain situations\. These scripts happen in addtion to the "pre" and "post" script\.
There are some special life cycle scripts that happen only in certain situations\. These scripts happen in addition to the "pre" and "post" script\.
.RS 0
.IP \(bu 2
\fBprepare\fP, \fBprepublish\fP, \fBprepublishOnly\fP, \fBprepack\fP, \fBpostpack\fP

View File

@ -178,6 +178,11 @@ class Config {
throw new Error('call config.load() before setting values')
if (!confTypes.has(where))
throw new Error('invalid config location param: ' + where)
if (key === '_auth') {
const { email } = this.getCredentialsByURI(this.get('registry'))
if (!email)
throw new Error('Cannot set _auth without first setting email')
}
this.data.get(where).data[key] = val
// this is now dirty, the next call to this.valid will have to check it
@ -512,6 +517,9 @@ class Config {
if (where === 'user') {
const reg = this.get('registry')
const creds = this.getCredentialsByURI(reg)
// we ignore this error because the failed set already removed
// anything that might be a security hazard, and it won't be
// saved back to the .npmrc file, so we're good.
try { this.setCredentialsByURI(reg, creds) } catch (_) {}
}
@ -576,18 +584,22 @@ class Config {
this.delete(`${nerfed}:email`, 'user')
this.delete(`${nerfed}:always-auth`, 'user')
} else if (username || password || email) {
if (!username)
throw new Error('must include username')
if (!password)
throw new Error('must include password')
if (username || password) {
if (!username)
throw new Error('must include username')
if (!password)
throw new Error('must include password')
}
if (!email)
throw new Error('must include email')
this.delete(`${nerfed}:_authToken`, 'user')
this.set(`${nerfed}:username`, username, 'user')
// note: not encrypted, no idea why we bothered to do this, but oh well
// protects against shoulder-hacks if password is memorable, I guess?
const encoded = Buffer.from(password, 'utf8').toString('base64')
this.set(`${nerfed}:_password`, encoded, 'user')
if (username || password) {
this.set(`${nerfed}:username`, username, 'user')
// note: not encrypted, no idea why we bothered to do this, but oh well
// protects against shoulder-hacks if password is memorable, I guess?
const encoded = Buffer.from(password, 'utf8').toString('base64')
this.set(`${nerfed}:_password`, encoded, 'user')
}
this.set(`${nerfed}:email`, email, 'user')
if (alwaysAuth !== undefined)
this.set(`${nerfed}:always-auth`, alwaysAuth, 'user')

View File

@ -1,6 +1,6 @@
{
"name": "@npmcli/config",
"version": "1.2.7",
"version": "1.2.8",
"files": [
"lib"
],

View File

@ -1,5 +1,5 @@
{
"version": "7.2.0",
"version": "7.3.0",
"name": "npm",
"description": "a package manager for JavaScript",
"keywords": [
@ -44,7 +44,7 @@
"dependencies": {
"@npmcli/arborist": "^2.0.2",
"@npmcli/ci-detect": "^1.2.0",
"@npmcli/config": "^1.2.7",
"@npmcli/config": "^1.2.8",
"@npmcli/run-script": "^1.8.1",
"abbrev": "~1.1.1",
"ansicolors": "~0.3.2",

View File

@ -129,7 +129,7 @@ long = false
; Run \`npm config ls -l\` to show all defaults.
`
exports[`test/lib/config.js TAP config list overrides > should list overriden configs 1`] = `
exports[`test/lib/config.js TAP config list overrides > should list overridden configs 1`] = `
; "cli" config from command line options
editor = "vi"

View File

@ -187,7 +187,7 @@ exports[`test/lib/ls.js TAP ls --parseable --production > should output tree con
{CWD}/ls-ls-parseable--production/node_modules/prod-dep/node_modules/bar
`
exports[`test/lib/ls.js TAP ls --parseable cycle deps > should print tree output ommiting deduped ref 1`] = `
exports[`test/lib/ls.js TAP ls --parseable cycle deps > should print tree output omitting deduped ref 1`] = `
{CWD}/ls-ls-parseable-cycle-deps
{CWD}/ls-ls-parseable-cycle-deps/node_modules/a
{CWD}/ls-ls-parseable-cycle-deps/node_modules/b
@ -287,11 +287,11 @@ exports[`test/lib/ls.js TAP ls --parseable using aliases > should output tree co
{CWD}/ls-ls-parseable-using-aliases/node_modules/a
`
exports[`test/lib/ls.js TAP ls --parseable with filter arg > should output parseable contaning only occurences of filtered by package 1`] = `
exports[`test/lib/ls.js TAP ls --parseable with filter arg > should output parseable contaning only occurrences of filtered by package 1`] = `
{CWD}/ls-ls-parseable-with-filter-arg/node_modules/lorem
`
exports[`test/lib/ls.js TAP ls --parseable with filter arg nested dep > should output parseable contaning only occurences of filtered package 1`] = `
exports[`test/lib/ls.js TAP ls --parseable with filter arg nested dep > should output parseable contaning only occurrences of filtered package 1`] = `
{CWD}/ls-ls-parseable-with-filter-arg-nested-dep/node_modules/bar
`
@ -299,7 +299,7 @@ exports[`test/lib/ls.js TAP ls --parseable with missing filter arg > should outp
`
exports[`test/lib/ls.js TAP ls --parseable with multiple filter args > should output parseable contaning only occurences of multiple filtered packages and their ancestors 1`] = `
exports[`test/lib/ls.js TAP ls --parseable with multiple filter args > should output parseable contaning only occurrences of multiple filtered packages and their ancestors 1`] = `
{CWD}/ls-ls-parseable-with-multiple-filter-args/node_modules/lorem
{CWD}/ls-ls-parseable-with-multiple-filter-args/node_modules/bar
`
@ -319,8 +319,8 @@ npm-broken-resolved-field-test@1.0.0 {CWD}/ls-ls-broken-resolved-field
`
exports[`test/lib/ls.js TAP ls coloured output > should output tree containing color info 1`] = `
test-npm-ls@1.0.0 {CWD}/ls-ls-coloured-output
exports[`test/lib/ls.js TAP ls colored output > should output tree containing color info 1`] = `
test-npm-ls@1.0.0 {CWD}/ls-ls-colored-output
+-- foo@1.0.0 invalid
| \`-- bar@1.0.0
+-- UNMET DEPENDENCY ipsum@^1.0.0
@ -550,19 +550,19 @@ dedupe-entries@1.0.0 {CWD}/ls-ls-with-args-and-different-order-of-items
`
exports[`test/lib/ls.js TAP ls with dot filter arg > should output tree contaning only occurences of filtered by package and coloured output 1`] = `
exports[`test/lib/ls.js TAP ls with dot filter arg > should output tree contaning only occurrences of filtered by package and colored output 1`] = `
test-npm-ls@1.0.0 {CWD}/ls-ls-with-dot-filter-arg
\`-- (empty)
`
exports[`test/lib/ls.js TAP ls with filter arg > should output tree contaning only occurences of filtered by package and coloured output 1`] = `
exports[`test/lib/ls.js TAP ls with filter arg > should output tree contaning only occurrences of filtered by package and colored output 1`] = `
test-npm-ls@1.0.0 {CWD}/ls-ls-with-filter-arg
\`-- lorem@1.0.0

`
exports[`test/lib/ls.js TAP ls with filter arg nested dep > should output tree contaning only occurences of filtered package and its ancestors 1`] = `
exports[`test/lib/ls.js TAP ls with filter arg nested dep > should output tree contaning only occurrences of filtered package and its ancestors 1`] = `
test-npm-ls@1.0.0 {CWD}/ls-ls-with-filter-arg-nested-dep
\`-- foo@1.0.0
\`-- bar@1.0.0
@ -575,7 +575,7 @@ test-npm-ls@1.0.0 {CWD}/ls-ls-with-missing-filter-arg
`
exports[`test/lib/ls.js TAP ls with multiple filter args > should output tree contaning only occurences of multiple filtered packages and their ancestors 1`] = `
exports[`test/lib/ls.js TAP ls with multiple filter args > should output tree contaning only occurrences of multiple filtered packages and their ancestors 1`] = `
test-npm-ls@1.0.0 {CWD}/ls-ls-with-multiple-filter-args
+-- foo@1.0.0
| \`-- bar@1.0.0

View File

@ -0,0 +1,90 @@
/* IMPORTANT
* This snapshot file is auto-generated, but designed for humans.
* It should be checked into source control and tracked carefully.
* Re-generate by setting TAP_SNAPSHOT=1 and running tests.
* Make sure to inspect the output below. Do not ignore changes!
*/
'use strict'
exports[`test/lib/profile.js TAP enable-2fa from token and set otp, retries on pending and verifies with qrcode > should output 2fa enablement success msgs 1`] = `
Scan into your authenticator app:
qrcode
Or enter code:
12342FA successfully enabled. Below are your recovery codes, please print these out.You will need these to recover access to your account if you lose your authentication device. 123456 789101
`
exports[`test/lib/profile.js TAP profile get <key> --parseable > should output parseable result value 1`] = `
foo
`
exports[`test/lib/profile.js TAP profile get multiple args --parseable > should output parseable profile value results 1`] = `
foo foo@github.com (verified) https://github.com/npm
`
exports[`test/lib/profile.js TAP profile get multiple args comma separated > should output all keys 1`] = `
foo foo@github.com (verified) https://github.com/npm
`
exports[`test/lib/profile.js TAP profile get multiple args default output > should output all keys 1`] = `
foo foo@github.com (verified) https://github.com/npm
`
exports[`test/lib/profile.js TAP profile get no args --parseable > should output all profile info as parseable result 1`] = `
tfa auth-and-writesname fooemail foo@github.comemail_verified truecreated 2015-02-26T01:26:37.384Zupdated 2020-08-12T16:19:35.326Zfullname Foo Barhomepage https://github.comfreenode foobartwitter https://twitter.com/npmjsgithub https://github.com/npm
`
exports[`test/lib/profile.js TAP profile get no args default output > should output table with contents 1`] = `
name: foo
email: foo@github.com (verified)
two-factor auth: auth-and-writes
fullname: Foo Bar
homepage: https://github.com
freenode: foobar
twitter: https://twitter.com/npmjs
github: https://github.com/npm
created: 2015-02-26T01:26:37.384Z
updated: 2020-08-12T16:19:35.326Z
`
exports[`test/lib/profile.js TAP profile get no args no tfa enabled > should output expected profile values 1`] = `
name: foo
email: foo@github.com (verified)
two-factor auth: disabled
fullname: Foo Bar
homepage: https://github.com
freenode: foobar
twitter: https://twitter.com/npmjs
github: https://github.com/npm
created: 2015-02-26T01:26:37.384Z
updated: 2020-08-12T16:19:35.326Z
`
exports[`test/lib/profile.js TAP profile get no args profile has cidr_whitelist item > should output table with contents 1`] = `
name: foo
email: foo@github.com (verified)
two-factor auth: auth-and-writes
fullname: Foo Bar
homepage: https://github.com
freenode: foobar
twitter: https://twitter.com/npmjs
github: https://github.com/npm
created: 2015-02-26T01:26:37.384Z
updated: 2020-08-12T16:19:35.326Z
cidr_whitelist: 192.168.1.1
`
exports[`test/lib/profile.js TAP profile get no args unverified email > should output table with contents 1`] = `
name: foo
email: foo@github.com(unverified)
two-factor auth: auth-and-writes
fullname: Foo Bar
homepage: https://github.com
freenode: foobar
twitter: https://twitter.com/npmjs
github: https://github.com/npm
created: 2015-02-26T01:26:37.384Z
updated: 2020-08-12T16:19:35.326Z
`
exports[`test/lib/profile.js TAP profile set <key> <value> writable key --parseable > should output parseable set key success msg 1`] = `
fullname Lorem Ipsum
`

View File

@ -82,7 +82,6 @@ Object {
"long": false,
"maxsockets": 50,
"message": "%s",
"metrics-registry": null,
"node-options": null,
"node-version": "v14.8.0",
"noproxy": null,
@ -120,7 +119,6 @@ Object {
"searchlimit": 20,
"searchopts": "",
"searchstaleness": 900,
"send-metrics": false,
"shell": "cmd.exe",
"shrinkwrap": true,
"sign-git-commit": false,
@ -423,10 +421,6 @@ Object {
"long": "{Boolean TYPE}",
"maxsockets": "{Number TYPE}",
"message": "{String TYPE}",
"metrics-registry": Array [
null,
"{String TYPE}",
],
"node-options": Array [
null,
"{String TYPE}",
@ -509,7 +503,6 @@ Object {
"searchlimit": "{Number TYPE}",
"searchopts": "{String TYPE}",
"searchstaleness": "{Number TYPE}",
"send-metrics": "{Boolean TYPE}",
"shell": "{String TYPE}",
"shrinkwrap": "{Boolean TYPE}",
"sign-git-commit": "{Boolean TYPE}",
@ -616,7 +609,6 @@ Object {
"long": false,
"maxsockets": 50,
"message": "%s",
"metrics-registry": null,
"node-options": null,
"node-version": "v14.8.0",
"noproxy": null,
@ -654,7 +646,6 @@ Object {
"searchlimit": 20,
"searchopts": "",
"searchstaleness": 900,
"send-metrics": false,
"shell": "cmd.exe",
"shrinkwrap": true,
"sign-git-commit": false,
@ -957,10 +948,6 @@ Object {
"long": "{Boolean TYPE}",
"maxsockets": "{Number TYPE}",
"message": "{String TYPE}",
"metrics-registry": Array [
null,
"{String TYPE}",
],
"node-options": Array [
null,
"{String TYPE}",
@ -1043,7 +1030,6 @@ Object {
"searchlimit": "{Number TYPE}",
"searchopts": "{String TYPE}",
"searchstaleness": "{Number TYPE}",
"send-metrics": "{Boolean TYPE}",
"shell": "{String TYPE}",
"shrinkwrap": "{Boolean TYPE}",
"sign-git-commit": "{Boolean TYPE}",
@ -1150,7 +1136,6 @@ Object {
"long": false,
"maxsockets": 50,
"message": "%s",
"metrics-registry": null,
"node-options": null,
"node-version": "v14.8.0",
"noproxy": null,
@ -1188,7 +1173,6 @@ Object {
"searchlimit": 20,
"searchopts": "",
"searchstaleness": 900,
"send-metrics": false,
"shell": "/usr/local/bin/bash",
"shrinkwrap": true,
"sign-git-commit": false,
@ -1493,10 +1477,6 @@ Object {
"long": "{Boolean TYPE}",
"maxsockets": "{Number TYPE}",
"message": "{String TYPE}",
"metrics-registry": Array [
null,
"{String TYPE}",
],
"node-options": Array [
null,
"{String TYPE}",
@ -1579,7 +1559,6 @@ Object {
"searchlimit": "{Number TYPE}",
"searchopts": "{String TYPE}",
"searchstaleness": "{Number TYPE}",
"send-metrics": "{Boolean TYPE}",
"shell": "{String TYPE}",
"shrinkwrap": "{Boolean TYPE}",
"sign-git-commit": "{Boolean TYPE}",

View File

@ -54,7 +54,6 @@ Object {
"log": Object {},
"long": undefined,
"message": "message",
"metricsRegistry": "metrics-registry",
"nodeBin": "/path/to/some/node",
"nodeVersion": "1.2.3",
"noProxy": "noproxy",
@ -100,7 +99,6 @@ Object {
},
"staleness": "searchstaleness",
},
"sendMetrics": "send-metrics",
"shell": undefined,
"signGitCommit": "sign-git-commit",
"signGitTag": "sign-git-tag",

View File

@ -1,4 +1,4 @@
// some real-world examples of ERESOLVE error explaination objects,
// some real-world examples of ERESOLVE error explanation objects,
// copied from arborist or generated there.
module.exports = {
cycleNested: {

View File

@ -9,21 +9,27 @@ const _flatOptions = {
authType: 'legacy',
registry: 'https://registry.npmjs.org/',
scope: '',
fromFlatOptions: true,
}
let failSave = false
let deletedConfig = {}
let registryOutput = ''
let setConfig = {}
const authDummy = () => Promise.resolve({
message: 'success',
newCreds: {
username: 'u',
password: 'p',
email: 'u@npmjs.org',
alwaysAuth: false,
},
})
const authDummy = (options) => {
if (!options.fromFlatOptions)
throw new Error('did not pass full flatOptions to auth function')
return Promise.resolve({
message: 'success',
newCreds: {
username: 'u',
password: 'p',
email: 'u@npmjs.org',
alwaysAuth: false,
},
})
}
const deleteMock = (key, where) => {
deletedConfig = {

View File

@ -122,7 +122,7 @@ t.test('config list overrides', t => {
config(['list'], (err) => {
t.ifError(err, 'npm config list')
t.matchSnapshot(result, 'should list overriden configs')
t.matchSnapshot(result, 'should list overridden configs')
})
})
@ -212,6 +212,33 @@ t.test('config delete key', t => {
})
})
t.test('config delete multiple key', t => {
t.plan(6)
const expect = [
'foo',
'bar',
]
npm.config.delete = (key, where) => {
t.equal(key, expect.shift(), 'should delete expected keyword')
t.equal(where, 'user', 'should delete key from user config by default')
}
npm.config.save = where => {
t.equal(where, 'user', 'should save user config post-delete')
}
config(['delete', 'foo', 'bar'], (err) => {
t.ifError(err, 'npm config delete keys')
})
t.teardown(() => {
delete npm.config.delete
delete npm.config.save
})
})
t.test('config delete key --global', t => {
t.plan(4)
@ -293,12 +320,43 @@ t.test('config set key=val', t => {
})
})
t.test('config set multiple keys', t => {
t.plan(11)
const expect = [
['foo', 'bar'],
['bar', 'baz'],
['asdf', ''],
]
const args = ['foo', 'bar', 'bar=baz', 'asdf']
npm.config.set = (key, val, where) => {
const [expectKey, expectVal] = expect.shift()
t.equal(key, expectKey, 'should set expected key to user config')
t.equal(val, expectVal, 'should set expected value to user config')
t.equal(where, 'user', 'should set key/val in user config by default')
}
npm.config.save = where => {
t.equal(where, 'user', 'should save user config')
}
config(['set', ...args], (err) => {
t.ifError(err, 'npm config set key')
})
t.teardown(() => {
delete npm.config.set
delete npm.config.save
})
})
t.test('config set key to empty value', t => {
t.plan(5)
npm.config.set = (key, val, where) => {
t.equal(key, 'foo', 'should set expected key to user config')
t.equal(val, '', 'should set empty value to user config')
t.equal(val, '', 'should set "" to user config')
t.equal(where, 'user', 'should set key/val in user config by default')
}
@ -403,6 +461,36 @@ t.test('config get key', t => {
})
})
t.test('config get multiple keys', t => {
t.plan(4)
const expect = [
'foo',
'bar',
]
const npmConfigGet = npm.config.get
npm.config.get = (key) => {
t.equal(key, expect.shift(), 'should use expected key')
return 'asdf'
}
npm.config.save = where => {
throw new Error('should not save')
}
config(['get', 'foo', 'bar'], (err) => {
t.ifError(err, 'npm config get multiple keys')
t.equal(result, 'foo=asdf\nbar=asdf')
})
t.teardown(() => {
result = ''
npm.config.get = npmConfigGet
delete npm.config.save
})
})
t.test('config get private key', t => {
config(['get', '//private-reg.npmjs.org/:_authThoken'], (err) => {
t.match(

View File

@ -13,6 +13,7 @@ npmFetch.json = async (uri, opts) => {
versions: {
'1.0.0': {},
'1.0.1': {},
'1.0.1-pre': {},
},
}
}
@ -126,6 +127,9 @@ test('deprecates all versions when no range is specified', t => {
'1.0.1': {
deprecated: 'this version is deprecated',
},
'1.0.1-pre': {
deprecated: 'this version is deprecated',
},
},
})

View File

@ -323,6 +323,6 @@ test('completion', t => {
},
},
}, (err) => {
t.notOk(err, 'should ignore any unkown name')
t.notOk(err, 'should ignore any unknown name')
})
})

View File

@ -40,7 +40,8 @@ const globDir = {
'npm-more-useless.md': 'exec exec',
'npm-extra-useless.md': 'exec\nexec\nexec',
}
const glob = (p, cb) => cb(null, Object.keys(globDir).map((file) => join(globRoot, file)))
const glob = (p, cb) =>
cb(null, Object.keys(globDir).map((file) => join(globRoot, file)))
const helpSearch = requireInject('../../lib/help-search.js', {
'../../lib/npm.js': npm,

View File

@ -209,7 +209,7 @@ t.test('ls', (t) => {
})
ls(['lorem'], (err) => {
t.ifError(err, 'npm ls')
t.matchSnapshot(redactCwd(result), 'should output tree contaning only occurences of filtered by package and coloured output')
t.matchSnapshot(redactCwd(result), 'should output tree contaning only occurrences of filtered by package and colored output')
_flatOptions.color = false
t.end()
})
@ -231,7 +231,7 @@ t.test('ls', (t) => {
})
ls(['.'], (err) => {
t.ifError(err, 'should not throw on missing dep above current level')
t.matchSnapshot(redactCwd(result), 'should output tree contaning only occurences of filtered by package and coloured output')
t.matchSnapshot(redactCwd(result), 'should output tree contaning only occurrences of filtered by package and colored output')
_flatOptions.all = true
_flatOptions.depth = Infinity
t.end()
@ -252,7 +252,7 @@ t.test('ls', (t) => {
})
ls(['bar'], (err) => {
t.ifError(err, 'npm ls')
t.matchSnapshot(redactCwd(result), 'should output tree contaning only occurences of filtered package and its ancestors')
t.matchSnapshot(redactCwd(result), 'should output tree contaning only occurrences of filtered package and its ancestors')
t.end()
})
})
@ -280,7 +280,7 @@ t.test('ls', (t) => {
})
ls(['bar@*', 'lorem@1.0.0'], (err) => {
t.ifError(err, 'npm ls')
t.matchSnapshot(redactCwd(result), 'should output tree contaning only occurences of multiple filtered packages and their ancestors')
t.matchSnapshot(redactCwd(result), 'should output tree contaning only occurrences of multiple filtered packages and their ancestors')
t.end()
})
})
@ -443,7 +443,7 @@ t.test('ls', (t) => {
})
})
t.test('coloured output', (t) => {
t.test('colored output', (t) => {
_flatOptions.color = true
prefix = t.testdir({
'package.json': JSON.stringify({
@ -1588,7 +1588,7 @@ t.test('ls --parseable', (t) => {
})
ls(['lorem'], (err) => {
t.ifError(err, 'npm ls')
t.matchSnapshot(redactCwd(result), 'should output parseable contaning only occurences of filtered by package')
t.matchSnapshot(redactCwd(result), 'should output parseable contaning only occurrences of filtered by package')
t.end()
})
})
@ -1607,7 +1607,7 @@ t.test('ls --parseable', (t) => {
})
ls(['bar'], (err) => {
t.ifError(err, 'npm ls')
t.matchSnapshot(redactCwd(result), 'should output parseable contaning only occurences of filtered package')
t.matchSnapshot(redactCwd(result), 'should output parseable contaning only occurrences of filtered package')
t.end()
})
})
@ -1635,7 +1635,7 @@ t.test('ls --parseable', (t) => {
})
ls(['bar@*', 'lorem@1.0.0'], (err) => {
t.ifError(err, 'npm ls')
t.matchSnapshot(redactCwd(result), 'should output parseable contaning only occurences of multiple filtered packages and their ancestors')
t.matchSnapshot(redactCwd(result), 'should output parseable contaning only occurrences of multiple filtered packages and their ancestors')
t.end()
})
})
@ -2158,7 +2158,7 @@ t.test('ls --parseable', (t) => {
},
})
ls([], () => {
t.matchSnapshot(redactCwd(result), 'should print tree output ommiting deduped ref')
t.matchSnapshot(redactCwd(result), 'should print tree output omitting deduped ref')
t.end()
})
})
@ -2482,7 +2482,7 @@ t.test('ls --json', (t) => {
},
},
},
'should output json contaning only occurences of filtered by package'
'should output json contaning only occurrences of filtered by package'
)
t.equal(
process.exitCode,
@ -2523,7 +2523,7 @@ t.test('ls --json', (t) => {
},
},
},
'should output json contaning only occurences of filtered by package'
'should output json contaning only occurrences of filtered by package'
)
t.end()
})
@ -2571,7 +2571,7 @@ t.test('ls --json', (t) => {
},
},
},
'should output json contaning only occurences of multiple filtered packages and their ancestors'
'should output json contaning only occurrences of multiple filtered packages and their ancestors'
)
t.end()
})

View File

@ -202,8 +202,6 @@ t.test('npm.load', t => {
t.equal(npm.bin, npm.globalBin, 'bin is global bin after prefix setter')
t.notEqual(npm.bin, npm.localBin, 'bin is not local bin after prefix setter')
t.equal(npm.config.get('metrics-registry'), npm.config.get('registry'))
beWindows()
t.equal(npm.bin, npm.globalBin, 'bin is global bin in windows mode')
t.equal(npm.dir, npm.globalDir, 'dir is global dir in windows mode')
@ -261,7 +259,6 @@ t.test('npm.load', t => {
process.argv = [
node,
process.argv[1],
'--metrics-registry', 'http://example.com',
'--prefix', dir,
'--userconfig', `${dir}/.npmrc`,
'--usage',
@ -292,7 +289,6 @@ t.test('npm.load', t => {
throw er
t.equal(npm.config.get('scope'), '@foo', 'added the @ sign to scope')
t.equal(npm.config.get('metrics-registry'), 'http://example.com')
t.match(logs.filter(l => l[0] !== 'timing' || !/^config:/.test(l[1])), [
[
'verbose',
@ -342,7 +338,7 @@ t.test('npm.load', t => {
/Completed in [0-9]+ms/,
],
])
t.same(consoleLogs, [['@foo']])
t.same(consoleLogs, [['scope=@foo\n\u2010not-a-dash=undefined']])
})
// need this here or node 10 will improperly end the promise ahead of time
@ -396,7 +392,6 @@ t.test('set process.title', t => {
argv: [
process.execPath,
process.argv[1],
'--metrics-registry', 'http://example.com',
'--usage',
'--scope=foo',
'ls',
@ -415,7 +410,6 @@ t.test('set process.title', t => {
argv: [
process.execPath,
process.argv[1],
'--metrics-registry', 'http://example.com',
'--usage',
'--scope=foo',
'token',
@ -436,7 +430,6 @@ t.test('set process.title', t => {
argv: [
process.execPath,
process.argv[1],
'--metrics-registry', 'http://example.com',
'--usage',
'--scope=foo',
'token',

View File

@ -119,7 +119,7 @@ t.test('owner ls fails to retrieve packument', t => {
t.match(
err,
/ERR/,
'should throw unkown error'
'should throw unknown error'
)
})
})

1465
deps/npm/test/lib/profile.js vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,14 @@ const requireInject = require('require-inject')
// mock config
const {defaults} = require('../../lib/utils/config.js')
const config = { list: [defaults] }
const credentials = {
token: 'asdfasdf',
alwaysAuth: false,
}
const config = {
list: [defaults],
getCredentialsByURI: () => credentials,
}
const fs = require('fs')
t.test('should publish with libnpmpublish, respecting publishConfig', (t) => {
@ -23,6 +30,7 @@ t.test('should publish with libnpmpublish, respecting publishConfig', (t) => {
flatOptions: {
json: true,
defaultTag: 'latest',
registry: 'https://registry.npmjs.org',
},
config,
},
@ -55,7 +63,7 @@ t.test('should publish with libnpmpublish, respecting publishConfig', (t) => {
},
})
publish([testDir], (er) => {
return publish([testDir], (er) => {
if (er)
throw er
t.pass('got to callback')
@ -77,6 +85,7 @@ t.test('re-loads publishConfig if added during script process', (t) => {
flatOptions: {
json: true,
defaultTag: 'latest',
registry: 'https://registry.npmjs.org/',
},
config,
},
@ -108,7 +117,7 @@ t.test('re-loads publishConfig if added during script process', (t) => {
},
})
publish([testDir], (er) => {
return publish([testDir], (er) => {
if (er)
throw er
t.pass('got to callback')
@ -131,6 +140,7 @@ t.test('should not log if silent', (t) => {
json: false,
defaultTag: 'latest',
dryRun: true,
registry: 'https://registry.npmjs.org/',
},
config,
},
@ -159,7 +169,7 @@ t.test('should not log if silent', (t) => {
},
})
publish([testDir], (er) => {
return publish([testDir], (er) => {
if (er)
throw er
t.pass('got to callback')
@ -181,6 +191,7 @@ t.test('should log tarball contents', (t) => {
json: false,
defaultTag: 'latest',
dryRun: true,
registry: 'https://registry.npmjs.org/',
},
config,
},
@ -206,7 +217,7 @@ t.test('should log tarball contents', (t) => {
},
})
publish([testDir], (er) => {
return publish([testDir], (er) => {
if (er)
throw er
t.pass('got to callback')
@ -220,12 +231,13 @@ t.test('shows usage with wrong set of arguments', (t) => {
flatOptions: {
json: false,
defaultTag: '0.0.13',
registry: 'https://registry.npmjs.org/',
},
config,
},
})
publish(['a', 'b', 'c'], (er) => t.matchSnapshot(er, 'should print usage'))
return publish(['a', 'b', 'c'], (er) => t.matchSnapshot(er, 'should print usage'))
})
t.test('throws when invalid tag', (t) => {
@ -235,12 +247,13 @@ t.test('throws when invalid tag', (t) => {
flatOptions: {
json: false,
defaultTag: '0.0.13',
registry: 'https://registry.npmjs.org/',
},
config,
},
})
publish([], (err) => {
return publish([], (err) => {
t.match(err, {
message: /Tag name must not be a valid SemVer range: /,
}, 'throws when tag name is a valid SemVer range')
@ -274,6 +287,7 @@ t.test('can publish a tarball', t => {
flatOptions: {
json: true,
defaultTag: 'latest',
registry: 'https://registry.npmjs.org/',
},
config,
},
@ -298,9 +312,56 @@ t.test('can publish a tarball', t => {
},
})
publish([`${testDir}/package.tgz`], (er) => {
return publish([`${testDir}/package.tgz`], (er) => {
if (er)
throw er
t.pass('got to callback')
})
})
t.test('throw if no registry', async t => {
t.plan(1)
const publish = requireInject('../../lib/publish.js', {
'../../lib/npm.js': {
flatOptions: {
json: false,
defaultTag: '0.0.13',
registry: null,
},
config,
},
})
return publish([], (err) => {
t.match(err, {
message: 'No registry specified.',
code: 'ENOREGISTRY',
}, 'throws when registry unset')
})
})
t.test('throw if not logged in', async t => {
t.plan(1)
const publish = requireInject('../../lib/publish.js', {
'../../lib/npm.js': {
flatOptions: {
json: false,
defaultTag: '0.0.13',
registry: 'https://registry.npmjs.org/',
},
config: {
...config,
getCredentialsByURI: () => ({
email: 'me@example.com',
}),
},
},
})
return publish([], (err) => {
t.match(err, {
message: 'This command requires you to be logged in.',
code: 'ENEEDAUTH',
}, 'throws when not logged in')
})
})

View File

@ -78,10 +78,6 @@ const npmlog = {
},
}
const metrics = {
stop: () => null,
}
// overrides OS type/release for cross platform snapshots
const os = require('os')
os.type = () => 'Foo'
@ -124,7 +120,6 @@ const mocks = {
summary: [['ERR', err.message]],
detail: [['ERR', err.message]],
}),
'../../../lib/utils/metrics.js': metrics,
'../../../lib/utils/cache-file.js': cacheFile,
}

View File

@ -34,8 +34,6 @@ class MockConfig {
cache: 'cache',
'node-version': '1.2.3',
global: 'global',
'metrics-registry': 'metrics-registry',
'send-metrics': 'send-metrics',
registry: 'registry',
access: 'access',
'always-auth': 'always-auth',
@ -299,15 +297,12 @@ t.test('various default values and falsey fallbacks', t => {
const npm = new Mocknpm({
'script-shell': false,
registry: 'http://example.com',
'metrics-registry': null,
searchlimit: 0,
'save-exact': false,
'save-prefix': '>=',
})
const opts = flatOptions(npm)
t.equal(opts.scriptShell, undefined, 'scriptShell is undefined if falsey')
t.equal(opts.metricsRegistry, 'http://example.com',
'metricsRegistry defaults to registry')
t.equal(opts.search.limit, 20, 'searchLimit defaults to 20')
t.equal(opts.savePrefix, '>=', 'save-prefix respected if no save-exact')
t.equal(opts.scope, '', 'scope defaults to empty string')

View File

@ -245,7 +245,10 @@ t.test('packages changed message', t => {
settings.json = json
npmock.command = command
const mock = {
actualTree: { inventory: { size: audited, has: () => true }, children: [] },
actualTree: {
inventory: { size: audited, has: () => true },
children: [],
},
auditReport: audited ? {
toJSON: () => mock.auditReport,
vulnerabilities: {},

View File

@ -46,7 +46,7 @@ t.equal(
t.equal(
replaceInfo('Something https://user:pass@registry.npmjs.org/ foo bar'),
'Something https://user:***@registry.npmjs.org/ foo bar',
'should replace single item withing a phrase'
'should replace single item within a phrase'
)
t.deepEqual(