diff --git a/deps/npm/bin/npx-cli.js b/deps/npm/bin/npx-cli.js index a495090c64c784..7a3fb39837d276 100755 --- a/deps/npm/bin/npx-cli.js +++ b/deps/npm/bin/npx-cli.js @@ -10,18 +10,18 @@ process.argv.splice(2, 0, 'exec') const removedSwitches = new Set([ 'always-spawn', 'ignore-existing', - 'shell-auto-fallback' + 'shell-auto-fallback', ]) const removedOpts = new Set([ 'npm', 'node-arg', - 'n' + 'n', ]) const removed = new Set([ ...removedSwitches, - ...removedOpts + ...removedOpts, ]) const { definitions, shorthands } = require('../lib/utils/config/index.js') @@ -40,7 +40,7 @@ const switches = new Set([ 'version', 'v', 'help', - 'h' + 'h', ]) // things that do take a value @@ -55,7 +55,7 @@ const opts = new Set([ 'shell', 'npm', 'node-arg', - 'n' + 'n', ]) // break out of loop when we find a positional argument or -- @@ -65,9 +65,9 @@ let i let sawRemovedFlags = false for (i = 3; i < process.argv.length; i++) { const arg = process.argv[i] - if (arg === '--') { + if (arg === '--') break - } else if (/^-/.test(arg)) { + else if (/^-/.test(arg)) { const [key, ...v] = arg.replace(/^-+/, '').split('=') switch (key) { @@ -87,9 +87,8 @@ for (i = 3; i < process.argv.length; i++) { // resolve shorthands and run again if (shorthands[key] && !removed.has(key)) { const a = [...shorthands[key]] - if (v.length) { + if (v.length) a.push(v.join('=')) - } process.argv.splice(i, 1, ...a) i-- continue @@ -110,9 +109,8 @@ for (i = 3; i < process.argv.length; i++) { if (removed.has(key)) { // also remove the value for the cut key. process.argv.splice(i + 1, 1) - } else { + } else i++ - } } } else { // found a positional arg, put -- in front of it, and we're done @@ -121,8 +119,7 @@ for (i = 3; i < process.argv.length; i++) { } } -if (sawRemovedFlags) { +if (sawRemovedFlags) console.error('See `npm help exec` for more information') -} cli(process) diff --git a/deps/npm/docs/content/using-npm/workspaces.md b/deps/npm/docs/content/using-npm/workspaces.md index 612404a9946470..829168864abe45 100644 --- a/deps/npm/docs/content/using-npm/workspaces.md +++ b/deps/npm/docs/content/using-npm/workspaces.md @@ -36,8 +36,8 @@ Workspaces are usually defined via the `workspaces` property of the ``` Given the above `package.json` example living at a current working -directory `.` that contains a folder named `workspace-a` that disposes -of a `package.json` inside it, defining a nodejs package, e.g: +directory `.` that contains a folder named `workspace-a` that itself contains +a `package.json` inside it, defining a nodejs package, e.g: ``` . diff --git a/deps/npm/docs/output/commands/npm-ls.html b/deps/npm/docs/output/commands/npm-ls.html index ef780840c94f8a..9e35f955467094 100644 --- a/deps/npm/docs/output/commands/npm-ls.html +++ b/deps/npm/docs/output/commands/npm-ls.html @@ -159,7 +159,7 @@
npm ls promzard
in npm’s source tree will show:
-npm@7.18.1 /path/to/npm
+npm@7.19.0 /path/to/npm
└─┬ init-package-json@0.0.4
└── promzard@0.1.5
diff --git a/deps/npm/docs/output/commands/npm.html b/deps/npm/docs/output/commands/npm.html
index 16aa3632315643..319135aa33d9c4 100644
--- a/deps/npm/docs/output/commands/npm.html
+++ b/deps/npm/docs/output/commands/npm.html
@@ -148,7 +148,7 @@ Table of contents
npm <command> [args]
Version
-7.18.1
+7.19.0
Description
npm is the package manager for the Node JavaScript platform. It puts
modules in place so that node can find them, and manages dependency
diff --git a/deps/npm/docs/output/using-npm/workspaces.html b/deps/npm/docs/output/using-npm/workspaces.html
index d929729856cba0..55bdb32ec460d8 100644
--- a/deps/npm/docs/output/using-npm/workspaces.html
+++ b/deps/npm/docs/output/using-npm/workspaces.html
@@ -168,8 +168,8 @@
Defining workspaces
}
Given the above package.json
example living at a current working
-directory .
that contains a folder named workspace-a
that disposes
-of a package.json
inside it, defining a nodejs package, e.g:
.
that contains a folder named workspace-a
that itself contains
+a package.json
inside it, defining a nodejs package, e.g:
.
+-- package.json
`-- workspace-a
diff --git a/deps/npm/lib/cli.js b/deps/npm/lib/cli.js
index fbceb459db97c0..9544f8451f8ae0 100644
--- a/deps/npm/lib/cli.js
+++ b/deps/npm/lib/cli.js
@@ -1,5 +1,5 @@
// Separated out for easier unit testing
-module.exports = (process) => {
+module.exports = async (process) => {
// set it here so that regardless of what happens later, we don't
// leak any private CLI configs to other programs
process.title = 'npm'
@@ -19,8 +19,8 @@ module.exports = (process) => {
checkForUnsupportedNode()
const npm = require('../lib/npm.js')
- const errorHandler = require('../lib/utils/error-handler.js')
- errorHandler.setNpm(npm)
+ const exitHandler = require('../lib/utils/exit-handler.js')
+ exitHandler.setNpm(npm)
// if npm is called as "npmg" or "npm_g", then
// run in global mode.
@@ -32,20 +32,18 @@ module.exports = (process) => {
log.info('using', 'npm@%s', npm.version)
log.info('using', 'node@%s', process.version)
- process.on('uncaughtException', errorHandler)
- process.on('unhandledRejection', errorHandler)
+ process.on('uncaughtException', exitHandler)
+ process.on('unhandledRejection', exitHandler)
- // now actually fire up npm and run the command.
- // this is how to use npm programmatically:
const updateNotifier = require('../lib/utils/update-notifier.js')
- npm.load(async er => {
- if (er)
- return errorHandler(er)
- // npm --version=cli
+ // now actually fire up npm and run the command.
+ // this is how to use npm programmatically:
+ try {
+ await npm.load()
if (npm.config.get('version', 'cli')) {
npm.output(npm.version)
- return errorHandler.exit(0)
+ return exitHandler()
}
// npm --versions=cli
@@ -57,22 +55,23 @@ module.exports = (process) => {
updateNotifier(npm)
const cmd = npm.argv.shift()
+ if (!cmd) {
+ npm.output(npm.usage)
+ process.exitCode = 1
+ return exitHandler()
+ }
+
const impl = npm.commands[cmd]
- if (impl)
- impl(npm.argv, errorHandler)
- else {
- try {
- if (cmd) {
- const didYouMean = require('./utils/did-you-mean.js')
- const suggestions = await didYouMean(npm, npm.localPrefix, cmd)
- npm.output(`Unknown command: "${cmd}"${suggestions}\n\nTo see a list of supported npm commands, run:\n npm help`)
- } else
- npm.output(npm.usage)
- process.exitCode = 1
- return errorHandler()
- } catch (err) {
- errorHandler(err)
- }
+ if (!impl) {
+ const didYouMean = require('./utils/did-you-mean.js')
+ const suggestions = await didYouMean(npm, npm.localPrefix, cmd)
+ npm.output(`Unknown command: "${cmd}"${suggestions}\n\nTo see a list of supported npm commands, run:\n npm help`)
+ process.exitCode = 1
+ return exitHandler()
}
- })
+
+ impl(npm.argv, exitHandler)
+ } catch (err) {
+ return exitHandler(err)
+ }
}
diff --git a/deps/npm/lib/init.js b/deps/npm/lib/init.js
index d34f92b882b32d..e4bd20b7210e81 100644
--- a/deps/npm/lib/init.js
+++ b/deps/npm/lib/init.js
@@ -5,8 +5,8 @@ const initJson = require('init-package-json')
const npa = require('npm-package-arg')
const rpj = require('read-package-json-fast')
const libexec = require('libnpmexec')
-const parseJSON = require('json-parse-even-better-errors')
const mapWorkspaces = require('@npmcli/map-workspaces')
+const PackageJson = require('@npmcli/package-json')
const getLocationMsg = require('./exec/get-workspace-location-msg.js')
const BaseCommand = require('./base-command.js')
@@ -199,35 +199,16 @@ class Init extends BaseCommand {
return
}
- let manifest
- try {
- manifest =
- fs.readFileSync(resolve(this.npm.localPrefix, 'package.json'), 'utf-8')
- } catch (error) {
- throw new Error('package.json not found')
- }
-
- try {
- manifest = parseJSON(manifest)
- } catch (error) {
- throw new Error(`Invalid package.json: ${error}`)
- }
+ const pkgJson = await PackageJson.load(this.npm.localPrefix)
- if (!manifest.workspaces)
- manifest.workspaces = []
-
- manifest.workspaces.push(relative(this.npm.localPrefix, workspacePath))
-
- // format content
- const {
- [Symbol.for('indent')]: indent,
- [Symbol.for('newline')]: newline,
- } = manifest
-
- const content = (JSON.stringify(manifest, null, indent) + '\n')
- .replace(/\n/g, newline)
+ pkgJson.update({
+ workspaces: [
+ ...(pkgJson.content.workspaces || []),
+ relative(this.npm.localPrefix, workspacePath),
+ ],
+ })
- fs.writeFileSync(resolve(this.npm.localPrefix, 'package.json'), content)
+ await pkgJson.save()
}
}
diff --git a/deps/npm/lib/ls.js b/deps/npm/lib/ls.js
index f146928a96b41d..7540692911976c 100644
--- a/deps/npm/lib/ls.js
+++ b/deps/npm/lib/ls.js
@@ -145,11 +145,9 @@ class LS extends ArboristWorkspaceCmd {
dev,
development,
link,
- node,
prod,
production,
only,
- tree,
}))
.map(mapEdgesToNodes({ seenPaths }))
.concat(appendExtraneousChildren({ node, seenPaths }))
@@ -310,6 +308,9 @@ const getHumanOutputItem = (node, { args, color, global, long }) => {
const targetLocation = node.root
? relative(node.root.realpath, node.realpath)
: node.targetLocation
+ const invalid = node[_invalid]
+ ? `invalid: ${node[_invalid]}`
+ : ''
const label =
(
node[_missing]
@@ -323,8 +324,8 @@ const getHumanOutputItem = (node, { args, color, global, long }) => {
: ''
) +
(
- node[_invalid]
- ? ' ' + (color ? chalk.red.bgBlack('invalid') : 'invalid')
+ invalid
+ ? ' ' + (color ? chalk.red.bgBlack(invalid) : invalid)
: ''
) +
(
@@ -375,7 +376,7 @@ const getJsonOutputItem = (node, { global, long }) => {
item.extraneous = true
if (node[_invalid])
- item.invalid = true
+ item.invalid = node[_invalid]
if (node[_missing] && !isOptional(node)) {
item.required = node[_required]
@@ -392,11 +393,9 @@ const filterByEdgesTypes = ({
dev,
development,
link,
- node,
prod,
production,
only,
- tree,
}) => {
// filter deps by type, allows for: `npm ls --dev`, `npm ls --prod`,
// `npm ls --link`, `npm ls --only=dev`, etc
@@ -436,9 +435,15 @@ const mapEdgesToNodes = ({ seenPaths }) => (edge) => {
if (node.path)
seenPaths.add(node.path)
- node[_required] = edge.spec
+ node[_required] = edge.spec || '*'
node[_type] = edge.type
- node[_invalid] = edge.invalid
+
+ if (edge.invalid) {
+ const spec = JSON.stringify(node[_required])
+ const from = edge.from.location || 'the root project'
+ node[_invalid] = (node[_invalid] ? node[_invalid] + ', ' : '') +
+ (`${spec} from ${from}`)
+ }
return node
}
diff --git a/deps/npm/lib/npm.js b/deps/npm/lib/npm.js
index 937459501c0a5e..7046a84d0bcfa2 100644
--- a/deps/npm/lib/npm.js
+++ b/deps/npm/lib/npm.js
@@ -11,6 +11,7 @@ const Config = require('@npmcli/config')
// Patch the global fs module here at the app level
require('graceful-fs').gracefulify(require('fs'))
+// TODO make this only ever load once (or unload) in tests
const procLogListener = require('./utils/proc-log-listener.js')
const proxyCmds = new Proxy({}, {
@@ -48,6 +49,7 @@ const _title = Symbol('_title')
const npm = module.exports = new class extends EventEmitter {
constructor () {
super()
+ // TODO make this only ever load once (or unload) in tests
require('./utils/perf.js')
this.started = Date.now()
this.command = null
@@ -77,8 +79,8 @@ const npm = module.exports = new class extends EventEmitter {
[_runCmd] (cmd, impl, args, cb) {
if (!this.loaded) {
throw new Error(
- 'Call npm.load(cb) before using this command.\n' +
- 'See the README.md or bin/npm-cli.js for example usage.'
+ 'Call npm.load() before using this command.\n' +
+ 'See lib/cli.js for example usage.'
)
}
@@ -96,7 +98,7 @@ const npm = module.exports = new class extends EventEmitter {
args.filter(arg => /^[\u2010-\u2015\u2212\uFE58\uFE63\uFF0D]/.test(arg))
.forEach(arg => {
warnedNonDashArg = true
- log.error('arg', 'Argument starts with non-ascii dash, this is probably invalid:', arg)
+ this.log.error('arg', 'Argument starts with non-ascii dash, this is probably invalid:', arg)
})
}
@@ -123,33 +125,32 @@ const npm = module.exports = new class extends EventEmitter {
}
}
- // call with parsed CLI options and a callback when done loading
- // XXX promisify this and stop taking a callback
load (cb) {
- if (!cb || typeof cb !== 'function')
- throw new TypeError('must call as: npm.load(callback)')
-
- this.once('load', cb)
- if (this.loaded || this.loadErr) {
- this.emit('load', this.loadErr)
- return
+ if (cb && typeof cb !== 'function')
+ throw new TypeError('callback must be a function if provided')
+
+ if (!this.loadPromise) {
+ process.emit('time', 'npm:load')
+ this.log.pause()
+ this.loadPromise = new Promise((resolve, reject) => {
+ this[_load]().catch(er => er).then((er) => {
+ this.loadErr = er
+ if (!er && this.config.get('force'))
+ this.log.warn('using --force', 'Recommended protections disabled.')
+
+ process.emit('timeEnd', 'npm:load')
+ if (er)
+ return reject(er)
+ resolve()
+ })
+ })
}
- if (this.loading)
- return
-
- this.loading = true
+ if (!cb)
+ return this.loadPromise
- process.emit('time', 'npm:load')
- this.log.pause()
- return this[_load]().catch(er => er).then((er) => {
- this.loading = false
- this.loadErr = er
- if (!er && this.config.get('force'))
- this.log.warn('using --force', 'Recommended protections disabled.')
-
- process.emit('timeEnd', 'npm:load')
- this.emit('load', er)
- })
+ // loadPromise is returned here for legacy purposes, old code was allowing
+ // the mixing of callback and promise here.
+ return this.loadPromise.then(cb, cb)
}
get loaded () {
@@ -167,10 +168,15 @@ const npm = module.exports = new class extends EventEmitter {
async [_load] () {
process.emit('time', 'npm:load:whichnode')
- const node = await which(process.argv[0]).catch(er => null)
+ let node
+ try {
+ node = which.sync(process.argv[0])
+ } catch (_) {
+ // TODO should we throw here?
+ }
process.emit('timeEnd', 'npm:load:whichnode')
if (node && node.toUpperCase() !== process.execPath.toUpperCase()) {
- log.verbose('node symlink', node)
+ this.log.verbose('node symlink', node)
process.execPath = node
this.config.execPath = node
}
@@ -198,10 +204,10 @@ const npm = module.exports = new class extends EventEmitter {
process.env.COLOR = this.color ? '1' : '0'
process.emit('time', 'npm:load:cleanupLog')
- cleanUpLogFiles(this.cache, this.config.get('logs-max'), log.warn)
+ cleanUpLogFiles(this.cache, this.config.get('logs-max'), this.log.warn)
process.emit('timeEnd', 'npm:load:cleanupLog')
- log.resume()
+ this.log.resume()
process.emit('time', 'npm:load:configScope')
const configScope = this.config.get('scope')
@@ -314,9 +320,8 @@ const npm = module.exports = new class extends EventEmitter {
// now load everything required by the class methods
const log = require('npmlog')
-const { promisify } = require('util')
-const which = promisify(require('which'))
+const which = require('which')
const deref = require('./utils/deref-command.js')
const setupLog = require('./utils/setup-log.js')
diff --git a/deps/npm/lib/set-script.js b/deps/npm/lib/set-script.js
index cd01e28b56b066..24e4d8f20f6663 100644
--- a/deps/npm/lib/set-script.js
+++ b/deps/npm/lib/set-script.js
@@ -1,8 +1,7 @@
+const { resolve } = require('path')
const log = require('npmlog')
-const fs = require('fs')
-const parseJSON = require('json-parse-even-better-errors')
const rpj = require('read-package-json-fast')
-const { resolve } = require('path')
+const PackageJson = require('@npmcli/package-json')
const BaseCommand = require('./base-command.js')
class SetScript extends BaseCommand {
@@ -51,7 +50,7 @@ class SetScript extends BaseCommand {
async setScript (args) {
this.validate(args)
- const warn = this.doSetScript(this.npm.localPrefix, args[0], args[1])
+ const warn = await this.doSetScript(this.npm.localPrefix, args[0], args[1])
if (warn)
log.warn('set-script', `Script "${args[0]}" was overwritten`)
}
@@ -66,7 +65,7 @@ class SetScript extends BaseCommand {
for (const [name, path] of this.workspaces) {
try {
- const warn = this.doSetScript(path, args[0], args[1])
+ const warn = await this.doSetScript(path, args[0], args[1])
if (warn) {
log.warn('set-script', `Script "${args[0]}" was overwritten`)
log.warn(` in workspace: ${name}`)
@@ -84,39 +83,28 @@ class SetScript extends BaseCommand {
// returns a Boolean that will be true if
// the requested script was overwritten
// and false if it was set as a new script
- doSetScript (path, name, value) {
- // Set the script
- let manifest
+ async doSetScript (path, name, value) {
let warn = false
- try {
- manifest = fs.readFileSync(resolve(path, 'package.json'), 'utf-8')
- } catch (error) {
- throw new Error('package.json not found')
- }
-
- try {
- manifest = parseJSON(manifest)
- } catch (error) {
- throw new Error(`Invalid package.json: ${error}`)
- }
+ const pkgJson = await PackageJson.load(path)
+ const { scripts } = pkgJson.content
- if (!manifest.scripts)
- manifest.scripts = {}
+ const overwriting =
+ scripts
+ && scripts[name]
+ && scripts[name] !== value
- if (manifest.scripts[name] && manifest.scripts[name] !== value)
+ if (overwriting)
warn = true
- manifest.scripts[name] = value
- // format content
- const {
- [Symbol.for('indent')]: indent,
- [Symbol.for('newline')]: newline,
- } = manifest
+ pkgJson.update({
+ scripts: {
+ ...scripts,
+ [name]: value,
+ },
+ })
- const content = (JSON.stringify(manifest, null, indent) + '\n')
- .replace(/\n/g, newline)
- fs.writeFileSync(resolve(path, 'package.json'), content)
+ await pkgJson.save()
return warn
}
diff --git a/deps/npm/lib/utils/error-handler.js b/deps/npm/lib/utils/exit-handler.js
similarity index 71%
rename from deps/npm/lib/utils/error-handler.js
rename to deps/npm/lib/utils/exit-handler.js
index f40e1f04fb1802..dc499f526a2085 100644
--- a/deps/npm/lib/utils/error-handler.js
+++ b/deps/npm/lib/utils/exit-handler.js
@@ -1,17 +1,20 @@
-let npm // set by the cli
-let cbCalled = false
const log = require('npmlog')
-let itWorked = false
+const os = require('os')
const path = require('path')
const writeFileAtomic = require('write-file-atomic')
const mkdirp = require('mkdirp-infer-owner')
const fs = require('graceful-fs')
-let wroteLogFile = false
-let exitCode = 0
+
const errorMessage = require('./error-message.js')
const replaceInfo = require('./replace-info.js')
+let exitHandlerCalled = false
let logFileName
+let npm // set by the cli
+let wroteLogFile = false
+
+const timings = {}
+
const getLogFile = () => {
// we call this multiple times, so we need to treat it as a singleton because
// the date is part of the name
@@ -21,7 +24,6 @@ const getLogFile = () => {
return logFileName
}
-const timings = {}
process.on('timing', (name, value) => {
if (timings[name])
timings[name] += value
@@ -53,22 +55,20 @@ process.on('exit', code => {
}
}
- if (code)
- itWorked = false
- if (itWorked)
+ if (!code)
log.info('ok')
else {
- if (!cbCalled) {
- log.error('', 'cb() never called!')
+ if (!exitHandlerCalled) {
+ log.error('', 'Exit handler never called!')
console.error('')
log.error('', 'This is an error with npm itself. Please report this error at:')
log.error('', ' ')
+ // TODO this doesn't have an npm.config.loaded guard
writeLogFile()
}
-
- if (code)
- log.verbose('code', code)
+ log.verbose('code', code)
}
+ // In timing mode we always write the log file
if (npm.config && npm.config.loaded && npm.config.get('timing') && !wroteLogFile)
writeLogFile()
if (wroteLogFile) {
@@ -83,52 +83,46 @@ process.on('exit', code => {
' ' + getLogFile(),
].join('\n')
)
- wroteLogFile = false
}
- // actually exit.
- if (exitCode === 0 && !itWorked)
- exitCode = 1
+ // these are needed for the tests to have a clean slate in each test case
+ exitHandlerCalled = false
+ wroteLogFile = false
- if (exitCode !== 0)
- process.exit(exitCode)
+ // actually exit.
+ process.exit(code)
})
const exit = (code, noLog) => {
- exitCode = exitCode || process.exitCode || code
-
- log.verbose('exit', code)
+ log.verbose('exit', code || 0)
if (log.level === 'silent')
noLog = true
- const reallyExit = () => {
- itWorked = !code
-
- // Exit directly -- nothing in the CLI should still be running in the
- // background at this point, and this makes sure anything left dangling
- // for whatever reason gets thrown away, instead of leaving the CLI open
- //
- // Commands that expect long-running actions should just delay `cb()`
- process.stdout.write('', () => {
- process.exit(code)
- })
- }
-
+ // noLog is true if there was an error, including if config wasn't loaded, so
+ // this doesn't need a config.loaded guard
if (code && !noLog)
writeLogFile()
- reallyExit()
+
+ // Exit directly -- nothing in the CLI should still be running in the
+ // background at this point, and this makes sure anything left dangling
+ // for whatever reason gets thrown away, instead of leaving the CLI open
+ process.stdout.write('', () => {
+ // `|| process.exitCode` supports a single use case, where we set the exit
+ // code to 1 if npm is called with no arguments
+ process.exit(code)
+ })
}
-const errorHandler = (er) => {
+const exitHandler = (err) => {
log.disableProgress()
if (!npm.config || !npm.config.loaded) {
// logging won't work unless we pretend that it's ready
- er = er || new Error('Exit prior to config file resolving.')
- console.error(er.stack || er.message)
+ err = err || new Error('Exit prior to config file resolving.')
+ console.error(err.stack || err.message)
}
- if (cbCalled)
- er = er || new Error('Callback called more than once.')
+ if (exitHandlerCalled)
+ err = err || new Error('Exit handler called more than once.')
// only show the notification if it finished before the other stuff we
// were doing. no need to hang on `npm -v` or something.
@@ -139,40 +133,39 @@ const errorHandler = (er) => {
log.level = level
}
- cbCalled = true
- if (!er)
- return exit(0)
+ exitHandlerCalled = true
+ if (!err)
+ return exit()
// if we got a command that just shells out to something else, then it
// will presumably print its own errors and exit with a proper status
// code if there's a problem. If we got an error with a code=0, then...
// something else went wrong along the way, so maybe an npm problem?
const isShellout = npm.shelloutCommands.includes(npm.command)
- const quietShellout = isShellout && typeof er.code === 'number' && er.code
+ const quietShellout = isShellout && typeof err.code === 'number' && err.code
if (quietShellout)
- return exit(er.code, true)
- else if (typeof er === 'string') {
- log.error('', er)
+ return exit(err.code, true)
+ else if (typeof err === 'string') {
+ log.error('', err)
return exit(1, true)
- } else if (!(er instanceof Error)) {
- log.error('weird error', er)
+ } else if (!(err instanceof Error)) {
+ log.error('weird error', err)
return exit(1, true)
}
- if (!er.code) {
- const matchErrorCode = er.message.match(/^(?:Error: )?(E[A-Z]+)/)
- er.code = matchErrorCode && matchErrorCode[1]
+ if (!err.code) {
+ const matchErrorCode = err.message.match(/^(?:Error: )?(E[A-Z]+)/)
+ err.code = matchErrorCode && matchErrorCode[1]
}
for (const k of ['type', 'stack', 'statusCode', 'pkgid']) {
- const v = er[k]
+ const v = err[k]
if (v)
log.verbose(k, replaceInfo(v))
}
log.verbose('cwd', process.cwd())
- const os = require('os')
const args = replaceInfo(process.argv)
log.verbose('', os.type() + ' ' + os.release())
log.verbose('argv', args.map(JSON.stringify).join(' '))
@@ -180,19 +173,19 @@ const errorHandler = (er) => {
log.verbose('npm ', 'v' + npm.version)
for (const k of ['code', 'syscall', 'file', 'path', 'dest', 'errno']) {
- const v = er[k]
+ const v = err[k]
if (v)
log.error(k, v)
}
- const msg = errorMessage(er, npm)
+ const msg = errorMessage(err, npm)
for (const errline of [...msg.summary, ...msg.detail])
log.error(...errline)
if (npm.config && npm.config.get('json')) {
const error = {
error: {
- code: er.code,
+ code: err.code,
summary: messageText(msg.summary),
detail: messageText(msg.detail),
},
@@ -200,7 +193,7 @@ const errorHandler = (er) => {
console.error(JSON.stringify(error, null, 2))
}
- exit(typeof er.errno === 'number' ? er.errno : typeof er.code === 'number' ? er.code : 1)
+ exit(typeof err.errno === 'number' ? err.errno : typeof err.code === 'number' ? err.code : 1)
}
const messageText = msg => msg.map(line => line.slice(1).join(' ')).join('\n')
@@ -209,8 +202,6 @@ const writeLogFile = () => {
if (wroteLogFile)
return
- const os = require('os')
-
try {
let logOutput = ''
log.record.forEach(m => {
@@ -243,8 +234,7 @@ const writeLogFile = () => {
}
}
-module.exports = errorHandler
-module.exports.exit = exit
+module.exports = exitHandler
module.exports.setNpm = (n) => {
npm = n
}
diff --git a/deps/npm/lib/utils/explain-eresolve.js b/deps/npm/lib/utils/explain-eresolve.js
index b35a32c6f935d1..fa3c6bda52293f 100644
--- a/deps/npm/lib/utils/explain-eresolve.js
+++ b/deps/npm/lib/utils/explain-eresolve.js
@@ -1,4 +1,4 @@
-// this is called when an ERESOLVE error is caught in the error-handler,
+// this is called when an ERESOLVE error is caught in the exit-handler,
// or when there's a log.warn('eresolve', msg, explanation), to turn it
// into a human-intelligible explanation of what's wrong and how to fix.
const { writeFileSync } = require('fs')
diff --git a/deps/npm/lib/utils/perf.js b/deps/npm/lib/utils/perf.js
index 3f81ee4b049e48..4961054d909ad6 100644
--- a/deps/npm/lib/utils/perf.js
+++ b/deps/npm/lib/utils/perf.js
@@ -14,3 +14,10 @@ process.on('timeEnd', (name) => {
} else
log.silly('timing', "Tried to end timer that doesn't exist:", name)
})
+
+// for tests
+/* istanbul ignore next */
+exports.reset = () => {
+ process.removeAllListeners('time')
+ process.removeAllListeners('timeEnd')
+}
diff --git a/deps/npm/lib/utils/proc-log-listener.js b/deps/npm/lib/utils/proc-log-listener.js
index 1dc4b4399eaea1..2cfe94ecb0cf24 100644
--- a/deps/npm/lib/utils/proc-log-listener.js
+++ b/deps/npm/lib/utils/proc-log-listener.js
@@ -14,3 +14,9 @@ module.exports = () => {
}
})
}
+
+// for tests
+/* istanbul ignore next */
+module.exports.reset = () => {
+ process.removeAllListeners('log')
+}
diff --git a/deps/npm/man/man1/npm-ls.1 b/deps/npm/man/man1/npm-ls.1
index 9bba449fbb1343..4cbea890fb8e96 100644
--- a/deps/npm/man/man1/npm-ls.1
+++ b/deps/npm/man/man1/npm-ls.1
@@ -26,7 +26,7 @@ example, running \fBnpm ls promzard\fP in npm's source tree will show:
.P
.RS 2
.nf
-npm@7\.18\.1 /path/to/npm
+npm@7\.19\.0 /path/to/npm
└─┬ init\-package\-json@0\.0\.4
└── promzard@0\.1\.5
.fi
diff --git a/deps/npm/man/man1/npm.1 b/deps/npm/man/man1/npm.1
index 9940f12ade1b8b..7090350c7b6432 100644
--- a/deps/npm/man/man1/npm.1
+++ b/deps/npm/man/man1/npm.1
@@ -10,7 +10,7 @@ npm [args]
.RE
.SS Version
.P
-7\.18\.1
+7\.19\.0
.SS Description
.P
npm is the package manager for the Node JavaScript platform\. It puts
diff --git a/deps/npm/man/man7/workspaces.7 b/deps/npm/man/man7/workspaces.7
index 9a1a417c24d290..70d808ce884606 100644
--- a/deps/npm/man/man7/workspaces.7
+++ b/deps/npm/man/man7/workspaces.7
@@ -34,8 +34,8 @@ npm help \fBpackage\.json\fP file, e\.g:
.RE
.P
Given the above \fBpackage\.json\fP example living at a current working
-directory \fB\|\.\fP that contains a folder named \fBworkspace\-a\fP that disposes
-of a \fBpackage\.json\fP inside it, defining a nodejs package, e\.g:
+directory \fB\|\.\fP that contains a folder named \fBworkspace\-a\fP that itself contains
+a \fBpackage\.json\fP inside it, defining a nodejs package, e\.g:
.P
.RS 2
.nf
diff --git a/deps/npm/node_modules/@npmcli/arborist/bin/lib/timers.js b/deps/npm/node_modules/@npmcli/arborist/bin/lib/timers.js
index e72217c1e4ed9c..b516af92c5b57f 100644
--- a/deps/npm/node_modules/@npmcli/arborist/bin/lib/timers.js
+++ b/deps/npm/node_modules/@npmcli/arborist/bin/lib/timers.js
@@ -1,5 +1,6 @@
const timers = Object.create(null)
const { format } = require('util')
+const options = require('./options.js')
process.on('time', name => {
if (timers[name])
@@ -15,7 +16,8 @@ process.on('timeEnd', name => {
const res = process.hrtime(timers[name])
delete timers[name]
const msg = format(`${process.pid} ${name}`, res[0] * 1e3 + res[1] / 1e6)
- console.error(dim(msg))
+ if (options.timers !== false)
+ console.error(dim(msg))
})
process.on('exit', () => {
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js
index 55360538b901a0..f259a69b548e10 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js
@@ -15,6 +15,7 @@ const mkdirp = require('mkdirp-infer-owner')
const justMkdirp = require('mkdirp')
const moveFile = require('@npmcli/move-file')
const rimraf = promisify(require('rimraf'))
+const PackageJson = require('@npmcli/package-json')
const packageContents = require('@npmcli/installed-package-contents')
const { checkEngine, checkPlatform } = require('npm-install-checks')
@@ -24,7 +25,6 @@ const Diff = require('../diff.js')
const retirePath = require('../retire-path.js')
const promiseAllRejectLate = require('promise-all-reject-late')
const optionalSet = require('../optional-set.js')
-const updateRootPackageJson = require('../update-root-package-json.js')
const calcDepFlags = require('../calc-dep-flags.js')
const { saveTypeMap, hasSubKey } = require('../add-rm-pkg-deps.js')
@@ -1029,6 +1029,25 @@ module.exports = cls => class Reifier extends cls {
const promises = [this[_saveLockFile](saveOpt)]
+ const updatePackageJson = async (tree) => {
+ const pkgJson = await PackageJson.load(tree.path)
+ .catch(() => new PackageJson(tree.path))
+ const {
+ dependencies = {},
+ devDependencies = {},
+ optionalDependencies = {},
+ peerDependencies = {},
+ } = tree.package
+
+ pkgJson.update({
+ dependencies,
+ devDependencies,
+ optionalDependencies,
+ peerDependencies,
+ })
+ await pkgJson.save()
+ }
+
// grab any from explicitRequests that had deps removed
for (const { from: tree } of this.explicitRequests)
updatedTrees.add(tree)
@@ -1036,7 +1055,7 @@ module.exports = cls => class Reifier extends cls {
for (const tree of updatedTrees) {
// refresh the edges so they have the correct specs
tree.package = tree.package
- promises.push(updateRootPackageJson(tree))
+ promises.push(updatePackageJson(tree))
}
await Promise.all(promises)
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/diff.js b/deps/npm/node_modules/@npmcli/arborist/lib/diff.js
index dac7c81f8ecfbf..1f8eff0f0c4d9c 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/diff.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/diff.js
@@ -145,9 +145,9 @@ const allChildren = node => {
if (!node)
return new Map()
- // if the node is a global root, and also a link, then what we really
+ // if the node is root, and also a link, then what we really
// want is to traverse the target's children
- if (node.global && node.isRoot && node.isLink)
+ if (node.isRoot && node.isLink)
return allChildren(node.target)
const kids = new Map()
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/shrinkwrap.js b/deps/npm/node_modules/@npmcli/arborist/lib/shrinkwrap.js
index 9fb0528db497c8..b251539a94c902 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/shrinkwrap.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/shrinkwrap.js
@@ -349,6 +349,7 @@ class Shrinkwrap {
reset () {
this.tree = null
this[_awaitingUpdate] = new Map()
+ this.originalLockfileVersion = lockfileVersion
this.data = {
lockfileVersion,
requires: true,
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/update-root-package-json.js b/deps/npm/node_modules/@npmcli/arborist/lib/update-root-package-json.js
deleted file mode 100644
index 57ec414248756c..00000000000000
--- a/deps/npm/node_modules/@npmcli/arborist/lib/update-root-package-json.js
+++ /dev/null
@@ -1,95 +0,0 @@
-const fs = require('fs')
-const promisify = require('util').promisify
-const readFile = promisify(fs.readFile)
-const writeFile = promisify(fs.writeFile)
-const {resolve} = require('path')
-
-const parseJSON = require('json-parse-even-better-errors')
-
-const depTypes = new Set([
- 'dependencies',
- 'optionalDependencies',
- 'devDependencies',
- 'peerDependencies',
-])
-
-// sort alphabetically all types of deps for a given package
-const orderDeps = (pkg) => {
- for (const type of depTypes) {
- if (pkg && pkg[type]) {
- pkg[type] = Object.keys(pkg[type])
- .sort((a, b) => a.localeCompare(b, 'en'))
- .reduce((res, key) => {
- res[key] = pkg[type][key]
- return res
- }, {})
- }
- }
- return pkg
-}
-const parseJsonSafe = json => {
- try {
- return parseJSON(json)
- } catch (er) {
- return null
- }
-}
-
-const updateRootPackageJson = async tree => {
- const filename = resolve(tree.path, 'package.json')
- const originalJson = await readFile(filename, 'utf8').catch(() => null)
- const originalContent = parseJsonSafe(originalJson)
-
- const depsData = orderDeps({
- ...tree.package,
- })
-
- // optionalDependencies don't need to be repeated in two places
- if (depsData.dependencies) {
- if (depsData.optionalDependencies) {
- for (const name of Object.keys(depsData.optionalDependencies))
- delete depsData.dependencies[name]
- }
- if (Object.keys(depsData.dependencies).length === 0)
- delete depsData.dependencies
- }
-
- // if there's no package.json, just use internal pkg info as source of truth
- // clone the object though, so we can still refer to what it originally was
- const packageJsonContent = !originalContent ? depsData
- : Object.assign({}, originalContent)
-
- // loop through all types of dependencies and update package json content
- for (const type of depTypes)
- packageJsonContent[type] = depsData[type]
-
- // if original package.json had dep in peerDeps AND deps, preserve that.
- const { dependencies: origProd, peerDependencies: origPeer } =
- originalContent || {}
- const { peerDependencies: newPeer } = packageJsonContent
- if (origProd && origPeer && newPeer) {
- // we have original prod/peer deps, and new peer deps
- // copy over any that were in both in the original
- for (const name of Object.keys(origPeer)) {
- if (origProd[name] !== undefined && newPeer[name] !== undefined) {
- packageJsonContent.dependencies = packageJsonContent.dependencies || {}
- packageJsonContent.dependencies[name] = newPeer[name]
- }
- }
- }
-
- // format content
- const {
- [Symbol.for('indent')]: indent,
- [Symbol.for('newline')]: newline,
- } = tree.package
- const format = indent === undefined ? ' ' : indent
- const eol = newline === undefined ? '\n' : newline
- const content = (JSON.stringify(packageJsonContent, null, format) + '\n')
- .replace(/\n/g, eol)
-
- if (content !== originalJson)
- return writeFile(filename, content)
-}
-
-module.exports = updateRootPackageJson
diff --git a/deps/npm/node_modules/@npmcli/arborist/package.json b/deps/npm/node_modules/@npmcli/arborist/package.json
index bd27e4bbffa20a..138d6ec25b4c2d 100644
--- a/deps/npm/node_modules/@npmcli/arborist/package.json
+++ b/deps/npm/node_modules/@npmcli/arborist/package.json
@@ -1,6 +1,6 @@
{
"name": "@npmcli/arborist",
- "version": "2.6.3",
+ "version": "2.6.4",
"description": "Manage node_modules trees",
"dependencies": {
"@npmcli/installed-package-contents": "^1.0.7",
@@ -9,6 +9,7 @@
"@npmcli/move-file": "^1.1.0",
"@npmcli/name-from-folder": "^1.0.1",
"@npmcli/node-gyp": "^1.0.1",
+ "@npmcli/package-json": "^1.0.1",
"@npmcli/run-script": "^1.8.2",
"bin-links": "^2.2.1",
"cacache": "^15.0.3",
diff --git a/deps/npm/node_modules/@npmcli/package-json/LICENSE b/deps/npm/node_modules/@npmcli/package-json/LICENSE
new file mode 100644
index 00000000000000..6a1f3708f6d70e
--- /dev/null
+++ b/deps/npm/node_modules/@npmcli/package-json/LICENSE
@@ -0,0 +1,18 @@
+ISC License
+
+Copyright GitHub Inc.
+
+Permission to use, copy, modify, and/or distribute this
+software for any purpose with or without fee is hereby
+granted, provided that the above copyright notice and this
+permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND NPM DISCLAIMS ALL
+WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+EVENT SHALL NPM BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
+USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/deps/npm/node_modules/@npmcli/package-json/lib/index.js b/deps/npm/node_modules/@npmcli/package-json/lib/index.js
new file mode 100644
index 00000000000000..87c3a630936886
--- /dev/null
+++ b/deps/npm/node_modules/@npmcli/package-json/lib/index.js
@@ -0,0 +1,106 @@
+const fs = require('fs')
+const promisify = require('util').promisify
+const readFile = promisify(fs.readFile)
+const writeFile = promisify(fs.writeFile)
+const { resolve } = require('path')
+const updateDeps = require('./update-dependencies.js')
+const updateScripts = require('./update-scripts.js')
+const updateWorkspaces = require('./update-workspaces.js')
+
+const parseJSON = require('json-parse-even-better-errors')
+
+const _filename = Symbol('filename')
+const _manifest = Symbol('manifest')
+const _readFileContent = Symbol('readFileContent')
+
+// a list of handy specialized helper functions that take
+// care of special cases that are handled by the npm cli
+const knownSteps = new Set([
+ updateDeps,
+ updateScripts,
+ updateWorkspaces,
+])
+
+// list of all keys that are handled by "knownSteps" helpers
+const knownKeys = new Set([
+ ...updateDeps.knownKeys,
+ 'scripts',
+ 'workspaces',
+])
+
+class PackageJson {
+ static async load (path) {
+ return await new PackageJson(path).load()
+ }
+
+ constructor (path) {
+ this[_filename] = resolve(path, 'package.json')
+ this[_manifest] = {}
+ this[_readFileContent] = ''
+ }
+
+ async load () {
+ try {
+ this[_readFileContent] =
+ await readFile(this[_filename], 'utf8')
+ } catch (err) {
+ throw new Error('package.json not found')
+ }
+
+ try {
+ this[_manifest] =
+ parseJSON(this[_readFileContent])
+ } catch (err) {
+ throw new Error(`Invalid package.json: ${err}`)
+ }
+
+ return this
+ }
+
+ get content () {
+ return this[_manifest]
+ }
+
+ update (content) {
+ // validates both current manifest and content param
+ const invalidContent =
+ typeof this[_manifest] !== 'object'
+ || typeof content !== 'object'
+ if (invalidContent) {
+ throw Object.assign(
+ new Error(`Can't update invalid package.json data`),
+ { code: 'EPACKAGEJSONUPDATE' }
+ )
+ }
+
+ for (const step of knownSteps)
+ this[_manifest] = step({ content, originalContent: this[_manifest] })
+
+ // unknown properties will just be overwitten
+ for (const [key, value] of Object.entries(content)) {
+ if (!knownKeys.has(key))
+ this[_manifest][key] = value
+ }
+
+ return this
+ }
+
+ async save () {
+ const {
+ [Symbol.for('indent')]: indent,
+ [Symbol.for('newline')]: newline,
+ } = this[_manifest]
+
+ const format = indent === undefined ? ' ' : indent
+ const eol = newline === undefined ? '\n' : newline
+ const fileContent = `${
+ JSON.stringify(this[_manifest], null, format)
+ }\n`
+ .replace(/\n/g, eol)
+
+ if (fileContent.trim() !== this[_readFileContent].trim())
+ return await writeFile(this[_filename], fileContent)
+ }
+}
+
+module.exports = PackageJson
diff --git a/deps/npm/node_modules/@npmcli/package-json/lib/update-dependencies.js b/deps/npm/node_modules/@npmcli/package-json/lib/update-dependencies.js
new file mode 100644
index 00000000000000..dac45a8bed7bf9
--- /dev/null
+++ b/deps/npm/node_modules/@npmcli/package-json/lib/update-dependencies.js
@@ -0,0 +1,72 @@
+const depTypes = new Set([
+ 'dependencies',
+ 'optionalDependencies',
+ 'devDependencies',
+ 'peerDependencies',
+])
+
+// sort alphabetically all types of deps for a given package
+const orderDeps = (content) => {
+ for (const type of depTypes) {
+ if (content && content[type]) {
+ content[type] = Object.keys(content[type])
+ .sort((a, b) => a.localeCompare(b, 'en'))
+ .reduce((res, key) => {
+ res[key] = content[type][key]
+ return res
+ }, {})
+ }
+ }
+ return content
+}
+
+const updateDependencies = ({ content, originalContent }) => {
+ const pkg = orderDeps({
+ ...content,
+ })
+
+ // optionalDependencies don't need to be repeated in two places
+ if (pkg.dependencies) {
+ if (pkg.optionalDependencies) {
+ for (const name of Object.keys(pkg.optionalDependencies))
+ delete pkg.dependencies[name]
+ }
+ }
+
+ const result = { ...originalContent }
+
+ // loop through all types of dependencies and update package json pkg
+ for (const type of depTypes) {
+ if (pkg[type])
+ result[type] = pkg[type]
+
+ // prune empty type props from resulting object
+ const emptyDepType =
+ pkg[type]
+ && typeof pkg === 'object'
+ && Object.keys(pkg[type]).length === 0
+ if (emptyDepType)
+ delete result[type]
+ }
+
+ // if original package.json had dep in peerDeps AND deps, preserve that.
+ const { dependencies: origProd, peerDependencies: origPeer } =
+ originalContent || {}
+ const { peerDependencies: newPeer } = result
+ if (origProd && origPeer && newPeer) {
+ // we have original prod/peer deps, and new peer deps
+ // copy over any that were in both in the original
+ for (const name of Object.keys(origPeer)) {
+ if (origProd[name] !== undefined && newPeer[name] !== undefined) {
+ result.dependencies = result.dependencies || {}
+ result.dependencies[name] = newPeer[name]
+ }
+ }
+ }
+
+ return result
+}
+
+updateDependencies.knownKeys = depTypes
+
+module.exports = updateDependencies
diff --git a/deps/npm/node_modules/@npmcli/package-json/lib/update-scripts.js b/deps/npm/node_modules/@npmcli/package-json/lib/update-scripts.js
new file mode 100644
index 00000000000000..3a88d3e9a17a80
--- /dev/null
+++ b/deps/npm/node_modules/@npmcli/package-json/lib/update-scripts.js
@@ -0,0 +1,28 @@
+const updateScripts = ({ content, originalContent = {} }) => {
+ const newScripts = content.scripts
+
+ if (!newScripts)
+ return originalContent
+
+ // validate scripts content being appended
+ const hasInvalidScripts = () =>
+ Object.entries(newScripts)
+ .some(([key, value]) =>
+ typeof key !== 'string' || typeof value !== 'string')
+ if (hasInvalidScripts()) {
+ throw Object.assign(
+ new TypeError(
+ 'package.json scripts should be a key-value pair of strings.'),
+ { code: 'ESCRIPTSINVALID' }
+ )
+ }
+
+ return {
+ ...originalContent,
+ scripts: {
+ ...newScripts,
+ },
+ }
+}
+
+module.exports = updateScripts
diff --git a/deps/npm/node_modules/@npmcli/package-json/lib/update-workspaces.js b/deps/npm/node_modules/@npmcli/package-json/lib/update-workspaces.js
new file mode 100644
index 00000000000000..207dd94a236d79
--- /dev/null
+++ b/deps/npm/node_modules/@npmcli/package-json/lib/update-workspaces.js
@@ -0,0 +1,25 @@
+const updateWorkspaces = ({ content, originalContent = {} }) => {
+ const newWorkspaces = content.workspaces
+
+ if (!newWorkspaces)
+ return originalContent
+
+ // validate workspaces content being appended
+ const hasInvalidWorkspaces = () =>
+ newWorkspaces.some(w => !(typeof w === 'string'))
+ if (!newWorkspaces.length || hasInvalidWorkspaces()) {
+ throw Object.assign(
+ new TypeError('workspaces should be an array of strings.'),
+ { code: 'EWORKSPACESINVALID' }
+ )
+ }
+
+ return {
+ ...originalContent,
+ workspaces: [
+ ...newWorkspaces,
+ ],
+ }
+}
+
+module.exports = updateWorkspaces
diff --git a/deps/npm/node_modules/@npmcli/package-json/package.json b/deps/npm/node_modules/@npmcli/package-json/package.json
new file mode 100644
index 00000000000000..8708ec5eb6fb1b
--- /dev/null
+++ b/deps/npm/node_modules/@npmcli/package-json/package.json
@@ -0,0 +1,34 @@
+{
+ "name": "@npmcli/package-json",
+ "version": "1.0.1",
+ "description": "Programmatic API to update package.json",
+ "main": "lib/index.js",
+ "files": [
+ "lib"
+ ],
+ "scripts": {
+ "preversion": "npm test",
+ "postversion": "npm publish",
+ "prepublishOnly": "git push origin --follow-tags",
+ "snap": "tap",
+ "test": "tap",
+ "npmclilint": "npmcli-lint",
+ "lint": "npm run npmclilint -- \"lib/*.*js\" \"test/*.*js\"",
+ "lintfix": "npm run lint -- --fix",
+ "posttest": "npm run lint --",
+ "postsnap": "npm run lintfix --"
+ },
+ "keywords": [
+ "npm",
+ "oss"
+ ],
+ "author": "GitHub Inc.",
+ "license": "ISC",
+ "devDependencies": {
+ "@npmcli/lint": "^1.0.1",
+ "tap": "^15.0.9"
+ },
+ "dependencies": {
+ "json-parse-even-better-errors": "^2.3.1"
+ }
+}
diff --git a/deps/npm/package.json b/deps/npm/package.json
index 58ac5d7f8c6c82..035f30b2be988b 100644
--- a/deps/npm/package.json
+++ b/deps/npm/package.json
@@ -1,5 +1,5 @@
{
- "version": "7.18.1",
+ "version": "7.19.0",
"name": "npm",
"description": "a package manager for JavaScript",
"workspaces": [
@@ -53,9 +53,10 @@
"./package.json": "./package.json"
},
"dependencies": {
- "@npmcli/arborist": "^2.6.3",
+ "@npmcli/arborist": "^2.6.4",
"@npmcli/ci-detect": "^1.2.0",
"@npmcli/config": "^2.2.0",
+ "@npmcli/package-json": "^1.0.1",
"@npmcli/run-script": "^1.8.5",
"abbrev": "~1.1.1",
"ansicolors": "~0.3.2",
@@ -125,6 +126,7 @@
"@npmcli/arborist",
"@npmcli/ci-detect",
"@npmcli/config",
+ "@npmcli/package-json",
"@npmcli/run-script",
"abbrev",
"ansicolors",
@@ -212,7 +214,7 @@
"sudotest:nocleanup": "sudo NO_TEST_CLEANUP=1 npm run test --",
"posttest": "npm run lint",
"eslint": "eslint",
- "lint": "npm run eslint -- test/lib test/bin lib scripts docs smoke-tests",
+ "lint": "npm run eslint -- test/lib test/bin bin lib scripts docs smoke-tests",
"lintfix": "npm run lint -- --fix",
"prelint": "rimraf test/npm_cache*",
"resetdeps": "bash scripts/resetdeps.sh",
diff --git a/deps/npm/tap-snapshots/test/lib/ls.js.test.cjs b/deps/npm/tap-snapshots/test/lib/ls.js.test.cjs
index 3d56d1f432731a..c3d0a87648edbb 100644
--- a/deps/npm/tap-snapshots/test/lib/ls.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/ls.js.test.cjs
@@ -32,16 +32,16 @@ exports[`test/lib/ls.js TAP ignore missing optional deps human output > ls resul
test-npm-ls-ignore-missing-optional@1.2.3 {project}
+-- unmet optional dependency optional-missing@1
+-- optional-ok@1.2.3
-+-- optional-wrong@3.2.1 invalid
++-- optional-wrong@3.2.1 invalid: "1" from the root project
+-- unmet dependency peer-missing@1
+-- peer-ok@1.2.3
+-- unmet optional dependency peer-optional-missing@1
+-- peer-optional-ok@1.2.3
-+-- peer-optional-wrong@3.2.1 invalid
-+-- peer-wrong@3.2.1 invalid
++-- peer-optional-wrong@3.2.1 invalid: "1" from the root project
++-- peer-wrong@3.2.1 invalid: "1" from the root project
+-- unmet dependency prod-missing@1
+-- prod-ok@1.2.3
-\`-- prod-wrong@3.2.1 invalid
+\`-- prod-wrong@3.2.1 invalid: "1" from the root project
`
@@ -356,7 +356,7 @@ npm-broken-resolved-field-test@1.0.0 {CWD}/tap-testdir-ls-ls-broken-resolved-fie
exports[`test/lib/ls.js TAP ls colored output > should output tree containing color info 1`] = `
[0mtest-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls-colored-output[0m
[0m+-- chai@1.0.0 [32m[40mextraneous[49m[39m[0m
-[0m+-- foo@1.0.0 [31m[40minvalid[49m[39m[0m
+[0m+-- foo@1.0.0 [31m[40minvalid: "^2.0.0" from the root project[49m[39m[0m
[0m| \`-- dog@1.0.0[0m
[0m\`-- [31m[40mUNMET DEPENDENCY[49m[39m ipsum@^1.0.0[0m
[0m[0m
@@ -454,8 +454,8 @@ exports[`test/lib/ls.js TAP ls global > should print tree and not mark top-level
exports[`test/lib/ls.js TAP ls invalid deduped dep > should output tree signaling mismatching peer dep in problems 1`] = `
[0minvalid-deduped-dep@1.0.0 {CWD}/tap-testdir-ls-ls-invalid-deduped-dep[0m
[0m+-- a@1.0.0[0m
-[0m| \`-- b@1.0.0 [90mdeduped[39m [31m[40minvalid[49m[39m[0m
-[0m\`-- b@1.0.0 [31m[40minvalid[49m[39m[0m
+[0m| \`-- b@1.0.0 [90mdeduped[39m [31m[40minvalid: "^2.0.0" from the root project, "^2.0.0" from node_modules/a[49m[39m[0m
+[0m\`-- b@1.0.0 [31m[40minvalid: "^2.0.0" from the root project, "^2.0.0" from node_modules/a[49m[39m[0m
[0m[0m
`
@@ -466,7 +466,7 @@ test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls-invalid-peer-dep
| \`-- foo@1.0.0
| \`-- dog@1.0.0
+-- optional-dep@1.0.0
-+-- peer-dep@1.0.0 invalid
++-- peer-dep@1.0.0 invalid: "^2.0.0" from the root project
\`-- prod-dep@1.0.0
\`-- dog@2.0.0
@@ -567,7 +567,7 @@ exports[`test/lib/ls.js TAP ls missing package.json > should output tree missing
exports[`test/lib/ls.js TAP ls missing/invalid/extraneous > should output tree containing missing, invalid, extraneous labels 1`] = `
test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls-missing-invalid-extraneous
+-- chai@1.0.0 extraneous
-+-- foo@1.0.0 invalid
++-- foo@1.0.0 invalid: "^2.0.0" from the root project
| \`-- dog@1.0.0
\`-- UNMET DEPENDENCY ipsum@^1.0.0
@@ -602,7 +602,7 @@ exports[`test/lib/ls.js TAP ls unmet optional dep > should output tree with empt
[0m| \`-- foo@1.0.0[0m
[0m| \`-- dog@1.0.0[0m
[0m+-- [33m[40mUNMET OPTIONAL DEPENDENCY[49m[39m missing-optional-dep@^1.0.0[0m
-[0m+-- optional-dep@1.0.0 [31m[40minvalid[49m[39m[0m
+[0m+-- optional-dep@1.0.0 [31m[40minvalid: "^2.0.0" from the root project[49m[39m[0m
[0m+-- peer-dep@1.0.0[0m
[0m\`-- prod-dep@1.0.0[0m
[0m \`-- dog@2.0.0[0m
@@ -691,3 +691,14 @@ dedupe-entries@1.0.0 {CWD}/tap-testdir-ls-ls-with-no-args-dedupe-entries-and-not
\`-- @npmcli/c@1.0.0
`
+
+exports[`test/lib/ls.js TAP show multiple invalid reasons > ls result 1`] = `
+test-npm-ls@1.0.0 {cwd}/tap-testdir-ls-show-multiple-invalid-reasons
++-- cat@1.0.0 invalid: "^2.0.0" from the root project
+| \`-- dog@1.0.0 deduped invalid: "^1.2.3" from the root project, "^2.0.0" from node_modules/cat
++-- chai@1.0.0 extraneous
+| \`-- dog@1.0.0 deduped invalid: "^1.2.3" from the root project, "^2.0.0" from node_modules/cat, "2.x" from node_modules/chai
+\`-- dog@1.0.0 invalid: "^1.2.3" from the root project, "^2.0.0" from node_modules/cat, "2.x" from node_modules/chai
+ \`-- cat@1.0.0 deduped invalid: "^2.0.0" from the root project
+
+`
diff --git a/deps/npm/tap-snapshots/test/lib/utils/config/definitions.js.test.cjs b/deps/npm/tap-snapshots/test/lib/utils/config/definitions.js.test.cjs
index 35942fea646834..12df9ec89f6f72 100644
--- a/deps/npm/tap-snapshots/test/lib/utils/config/definitions.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/utils/config/definitions.js.test.cjs
@@ -155,3 +155,1696 @@ Array [
exports[`test/lib/utils/config/definitions.js TAP > all config keys that are shared to flatOptions 1`] = `
Array []
`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for _auth 1`] = `
+#### \`_auth\`
+
+* Default: null
+* Type: null or String
+
+A basic-auth string to use when authenticating against the npm registry.
+
+Warning: This should generally not be set via a command-line option. It is
+safer to use a registry-provided authentication bearer token stored in the
+~/.npmrc file by running \`npm login\`.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for access 1`] = `
+#### \`access\`
+
+* Default: 'restricted' for scoped packages, 'public' for unscoped packages
+* Type: null, "restricted", or "public"
+
+When publishing scoped packages, the access level defaults to \`restricted\`.
+If you want your scoped package to be publicly viewable (and installable)
+set \`--access=public\`. The only valid values for \`access\` are \`public\` and
+\`restricted\`. Unscoped packages _always_ have an access level of \`public\`.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for all 1`] = `
+#### \`all\`
+
+* Default: false
+* Type: Boolean
+
+When running \`npm outdated\` and \`npm ls\`, setting \`--all\` will show all
+outdated or installed packages, rather than only those directly depended
+upon by the current project.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for allow-same-version 1`] = `
+#### \`allow-same-version\`
+
+* Default: false
+* Type: Boolean
+
+Prevents throwing an error when \`npm version\` is used to set the new version
+to the same value as the current version.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for also 1`] = `
+#### \`also\`
+
+* Default: null
+* Type: null, "dev", or "development"
+* DEPRECATED: Please use --include=dev instead.
+
+When set to \`dev\` or \`development\`, this is an alias for \`--include=dev\`.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for audit 1`] = `
+#### \`audit\`
+
+* Default: true
+* Type: Boolean
+
+When "true" submit audit reports alongside \`npm install\` runs to the default
+registry and all registries configured for scopes. See the documentation for
+[\`npm audit\`](/commands/npm-audit) for details on what is submitted.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for audit-level 1`] = `
+#### \`audit-level\`
+
+* Default: null
+* Type: null, "info", "low", "moderate", "high", "critical", or "none"
+
+The minimum level of vulnerability for \`npm audit\` to exit with a non-zero
+exit code.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for auth-type 1`] = `
+#### \`auth-type\`
+
+* Default: "legacy"
+* Type: "legacy", "sso", "saml", or "oauth"
+* DEPRECATED: This method of SSO/SAML/OAuth is deprecated and will be removed
+ in a future version of npm in favor of web-based login.
+
+What authentication strategy to use with \`adduser\`/\`login\`.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for before 1`] = `
+#### \`before\`
+
+* Default: null
+* Type: null or Date
+
+If passed to \`npm install\`, will rebuild the npm tree such that only
+versions that were available **on or before** the \`--before\` time get
+installed. If there's no versions available for the current set of direct
+dependencies, the command will error.
+
+If the requested version is a \`dist-tag\` and the given tag does not pass the
+\`--before\` filter, the most recent version less than or equal to that tag
+will be used. For example, \`foo@latest\` might install \`foo@1.2\` even though
+\`latest\` is \`2.0\`.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for bin-links 1`] = `
+#### \`bin-links\`
+
+* Default: true
+* Type: Boolean
+
+Tells npm to create symlinks (or \`.cmd\` shims on Windows) for package
+executables.
+
+Set to false to have it not do this. This can be used to work around the
+fact that some file systems don't support symlinks, even on ostensibly Unix
+systems.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for browser 1`] = `
+#### \`browser\`
+
+* Default: OS X: \`"open"\`, Windows: \`"start"\`, Others: \`"xdg-open"\`
+* Type: null, Boolean, or String
+
+The browser that is called by npm commands to open websites.
+
+Set to \`false\` to suppress browser behavior and instead print urls to
+terminal.
+
+Set to \`true\` to use default system URL opener.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for ca 1`] = `
+#### \`ca\`
+
+* Default: null
+* Type: null or String (can be set multiple times)
+
+The Certificate Authority signing certificate that is trusted for SSL
+connections to the registry. Values should be in PEM format (Windows calls
+it "Base-64 encoded X.509 (.CER)") with newlines replaced by the string
+"\\n". For example:
+
+\`\`\`ini
+ca="-----BEGIN CERTIFICATE-----\\nXXXX\\nXXXX\\n-----END CERTIFICATE-----"
+\`\`\`
+
+Set to \`null\` to only allow "known" registrars, or to a specific CA cert to
+trust only that specific signing authority.
+
+Multiple CAs can be trusted by specifying an array of certificates:
+
+\`\`\`ini
+ca[]="..."
+ca[]="..."
+\`\`\`
+
+See also the \`strict-ssl\` config.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for cache 1`] = `
+#### \`cache\`
+
+* Default: Windows: \`%LocalAppData%\\npm-cache\`, Posix: \`~/.npm\`
+* Type: Path
+
+The location of npm's cache directory. See [\`npm
+cache\`](/commands/npm-cache)
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for cache-max 1`] = `
+#### \`cache-max\`
+
+* Default: Infinity
+* Type: Number
+* DEPRECATED: This option has been deprecated in favor of \`--prefer-online\`
+
+\`--cache-max=0\` is an alias for \`--prefer-online\`
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for cache-min 1`] = `
+#### \`cache-min\`
+
+* Default: 0
+* Type: Number
+* DEPRECATED: This option has been deprecated in favor of \`--prefer-offline\`.
+
+\`--cache-min=9999 (or bigger)\` is an alias for \`--prefer-offline\`.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for cafile 1`] = `
+#### \`cafile\`
+
+* Default: null
+* Type: Path
+
+A path to a file containing one or multiple Certificate Authority signing
+certificates. Similar to the \`ca\` setting, but allows for multiple CA's, as
+well as for the CA information to be stored in a file on disk.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for call 1`] = `
+#### \`call\`
+
+* Default: ""
+* Type: String
+
+Optional companion option for \`npm exec\`, \`npx\` that allows for specifying a
+custom command to be run along with the installed packages.
+
+\`\`\`bash
+npm exec --package yo --package generator-node --call "yo node"
+\`\`\`
+
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for cert 1`] = `
+#### \`cert\`
+
+* Default: null
+* Type: null or String
+
+A client certificate to pass when accessing the registry. Values should be
+in PEM format (Windows calls it "Base-64 encoded X.509 (.CER)") with
+newlines replaced by the string "\\n". For example:
+
+\`\`\`ini
+cert="-----BEGIN CERTIFICATE-----\\nXXXX\\nXXXX\\n-----END CERTIFICATE-----"
+\`\`\`
+
+It is _not_ the path to a certificate file (and there is no "certfile"
+option).
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for ci-name 1`] = `
+#### \`ci-name\`
+
+* Default: The name of the current CI system, or \`null\` when not on a known CI
+ platform.
+* Type: null or String
+
+The name of a continuous integration system. If not set explicitly, npm will
+detect the current CI environment using the
+[\`@npmcli/ci-detect\`](http://npm.im/@npmcli/ci-detect) module.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for cidr 1`] = `
+#### \`cidr\`
+
+* Default: null
+* Type: null or String (can be set multiple times)
+
+This is a list of CIDR address to be used when configuring limited access
+tokens with the \`npm token create\` command.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for color 1`] = `
+#### \`color\`
+
+* Default: true unless the NO_COLOR environ is set to something other than '0'
+* Type: "always" or Boolean
+
+If false, never shows colors. If \`"always"\` then always shows colors. If
+true, then only prints color codes for tty file descriptors.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for commit-hooks 1`] = `
+#### \`commit-hooks\`
+
+* Default: true
+* Type: Boolean
+
+Run git commit hooks when using the \`npm version\` command.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for depth 1`] = `
+#### \`depth\`
+
+* Default: \`Infinity\` if \`--all\` is set, otherwise \`1\`
+* Type: null or Number
+
+The depth to go when recursing packages for \`npm ls\`.
+
+If not set, \`npm ls\` will show only the immediate dependencies of the root
+project. If \`--all\` is set, then npm will show all dependencies by default.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for description 1`] = `
+#### \`description\`
+
+* Default: true
+* Type: Boolean
+
+Show the description in \`npm search\`
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for dev 1`] = `
+#### \`dev\`
+
+* Default: false
+* Type: Boolean
+* DEPRECATED: Please use --include=dev instead.
+
+Alias for \`--include=dev\`.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for diff 1`] = `
+#### \`diff\`
+
+* Default:
+* Type: String (can be set multiple times)
+
+Define arguments to compare in \`npm diff\`.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for diff-dst-prefix 1`] = `
+#### \`diff-dst-prefix\`
+
+* Default: "b/"
+* Type: String
+
+Destination prefix to be used in \`npm diff\` output.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for diff-ignore-all-space 1`] = `
+#### \`diff-ignore-all-space\`
+
+* Default: false
+* Type: Boolean
+
+Ignore whitespace when comparing lines in \`npm diff\`.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for diff-name-only 1`] = `
+#### \`diff-name-only\`
+
+* Default: false
+* Type: Boolean
+
+Prints only filenames when using \`npm diff\`.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for diff-no-prefix 1`] = `
+#### \`diff-no-prefix\`
+
+* Default: false
+* Type: Boolean
+
+Do not show any source or destination prefix in \`npm diff\` output.
+
+Note: this causes \`npm diff\` to ignore the \`--diff-src-prefix\` and
+\`--diff-dst-prefix\` configs.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for diff-src-prefix 1`] = `
+#### \`diff-src-prefix\`
+
+* Default: "a/"
+* Type: String
+
+Source prefix to be used in \`npm diff\` output.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for diff-text 1`] = `
+#### \`diff-text\`
+
+* Default: false
+* Type: Boolean
+
+Treat all files as text in \`npm diff\`.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for diff-unified 1`] = `
+#### \`diff-unified\`
+
+* Default: 3
+* Type: Number
+
+The number of lines of context to print in \`npm diff\`.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for dry-run 1`] = `
+#### \`dry-run\`
+
+* Default: false
+* Type: Boolean
+
+Indicates that you don't want npm to make any changes and that it should
+only report what it would have done. This can be passed into any of the
+commands that modify your local installation, eg, \`install\`, \`update\`,
+\`dedupe\`, \`uninstall\`, as well as \`pack\` and \`publish\`.
+
+Note: This is NOT honored by other network related commands, eg \`dist-tags\`,
+\`owner\`, etc.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for editor 1`] = `
+#### \`editor\`
+
+* Default: The EDITOR or VISUAL environment variables, or 'notepad.exe' on
+ Windows, or 'vim' on Unix systems
+* Type: String
+
+The command to run for \`npm edit\` and \`npm config edit\`.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for engine-strict 1`] = `
+#### \`engine-strict\`
+
+* Default: false
+* Type: Boolean
+
+If set to true, then npm will stubbornly refuse to install (or even consider
+installing) any package that claims to not be compatible with the current
+Node.js version.
+
+This can be overridden by setting the \`--force\` flag.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for fetch-retries 1`] = `
+#### \`fetch-retries\`
+
+* Default: 2
+* Type: Number
+
+The "retries" config for the \`retry\` module to use when fetching packages
+from the registry.
+
+npm will retry idempotent read requests to the registry in the case of
+network failures or 5xx HTTP errors.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for fetch-retry-factor 1`] = `
+#### \`fetch-retry-factor\`
+
+* Default: 10
+* Type: Number
+
+The "factor" config for the \`retry\` module to use when fetching packages.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for fetch-retry-maxtimeout 1`] = `
+#### \`fetch-retry-maxtimeout\`
+
+* Default: 60000 (1 minute)
+* Type: Number
+
+The "maxTimeout" config for the \`retry\` module to use when fetching
+packages.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for fetch-retry-mintimeout 1`] = `
+#### \`fetch-retry-mintimeout\`
+
+* Default: 10000 (10 seconds)
+* Type: Number
+
+The "minTimeout" config for the \`retry\` module to use when fetching
+packages.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for fetch-timeout 1`] = `
+#### \`fetch-timeout\`
+
+* Default: 300000 (5 minutes)
+* Type: Number
+
+The maximum amount of time to wait for HTTP requests to complete.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for force 1`] = `
+#### \`force\`
+
+* Default: false
+* Type: Boolean
+
+Removes various protections against unfortunate side effects, common
+mistakes, unnecessary performance degradation, and malicious input.
+
+* Allow clobbering non-npm files in global installs.
+* Allow the \`npm version\` command to work on an unclean git repository.
+* Allow deleting the cache folder with \`npm cache clean\`.
+* Allow installing packages that have an \`engines\` declaration requiring a
+ different version of npm.
+* Allow installing packages that have an \`engines\` declaration requiring a
+ different version of \`node\`, even if \`--engine-strict\` is enabled.
+* Allow \`npm audit fix\` to install modules outside your stated dependency
+ range (including SemVer-major changes).
+* Allow unpublishing all versions of a published package.
+* Allow conflicting peerDependencies to be installed in the root project.
+* Implicitly set \`--yes\` during \`npm init\`.
+
+If you don't have a clear idea of what you want to do, it is strongly
+recommended that you do not use this option!
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for foreground-scripts 1`] = `
+#### \`foreground-scripts\`
+
+* Default: false
+* Type: Boolean
+
+Run all build scripts (ie, \`preinstall\`, \`install\`, and \`postinstall\`)
+scripts for installed packages in the foreground process, sharing standard
+input, output, and error with the main npm process.
+
+Note that this will generally make installs run slower, and be much noisier,
+but can be useful for debugging.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for format-package-lock 1`] = `
+#### \`format-package-lock\`
+
+* Default: true
+* Type: Boolean
+
+Format \`package-lock.json\` or \`npm-shrinkwrap.json\` as a human readable
+file.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for fund 1`] = `
+#### \`fund\`
+
+* Default: true
+* Type: Boolean
+
+When "true" displays the message at the end of each \`npm install\`
+acknowledging the number of dependencies looking for funding. See [\`npm
+fund\`](/commands/npm-fund) for details.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for git 1`] = `
+#### \`git\`
+
+* Default: "git"
+* Type: String
+
+The command to use for git commands. If git is installed on the computer,
+but is not in the \`PATH\`, then set this to the full path to the git binary.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for git-tag-version 1`] = `
+#### \`git-tag-version\`
+
+* Default: true
+* Type: Boolean
+
+Tag the commit when using the \`npm version\` command.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for global 1`] = `
+#### \`global\`
+
+* Default: false
+* Type: Boolean
+
+Operates in "global" mode, so that packages are installed into the \`prefix\`
+folder instead of the current working directory. See
+[folders](/configuring-npm/folders) for more on the differences in behavior.
+
+* packages are installed into the \`{prefix}/lib/node_modules\` folder, instead
+ of the current working directory.
+* bin files are linked to \`{prefix}/bin\`
+* man pages are linked to \`{prefix}/share/man\`
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for global-style 1`] = `
+#### \`global-style\`
+
+* Default: false
+* Type: Boolean
+
+Causes npm to install the package into your local \`node_modules\` folder with
+the same layout it uses with the global \`node_modules\` folder. Only your
+direct dependencies will show in \`node_modules\` and everything they depend
+on will be flattened in their \`node_modules\` folders. This obviously will
+eliminate some deduping. If used with \`legacy-bundling\`, \`legacy-bundling\`
+will be preferred.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for globalconfig 1`] = `
+#### \`globalconfig\`
+
+* Default: The global --prefix setting plus 'etc/npmrc'. For example,
+ '/usr/local/etc/npmrc'
+* Type: Path
+
+The config file to read for global config options.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for heading 1`] = `
+#### \`heading\`
+
+* Default: "npm"
+* Type: String
+
+The string that starts all the debugging log output.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for https-proxy 1`] = `
+#### \`https-proxy\`
+
+* Default: null
+* Type: null or URL
+
+A proxy to use for outgoing https requests. If the \`HTTPS_PROXY\` or
+\`https_proxy\` or \`HTTP_PROXY\` or \`http_proxy\` environment variables are set,
+proxy settings will be honored by the underlying \`make-fetch-happen\`
+library.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for if-present 1`] = `
+#### \`if-present\`
+
+* Default: false
+* Type: Boolean
+
+If true, npm will not exit with an error code when \`run-script\` is invoked
+for a script that isn't defined in the \`scripts\` section of \`package.json\`.
+This option can be used when it's desirable to optionally run a script when
+it's present and fail if the script fails. This is useful, for example, when
+running scripts that may only apply for some builds in an otherwise generic
+CI setup.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for ignore-scripts 1`] = `
+#### \`ignore-scripts\`
+
+* Default: false
+* Type: Boolean
+
+If true, npm does not run scripts specified in package.json files.
+
+Note that commands explicitly intended to run a particular script, such as
+\`npm start\`, \`npm stop\`, \`npm restart\`, \`npm test\`, and \`npm run-script\`
+will still run their intended script if \`ignore-scripts\` is set, but they
+will *not* run any pre- or post-scripts.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for include 1`] = `
+#### \`include\`
+
+* Default:
+* Type: "prod", "dev", "optional", or "peer" (can be set multiple times)
+
+Option that allows for defining which types of dependencies to install.
+
+This is the inverse of \`--omit=\`.
+
+Dependency types specified in \`--include\` will not be omitted, regardless of
+the order in which omit/include are specified on the command-line.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for include-staged 1`] = `
+#### \`include-staged\`
+
+* Default: false
+* Type: Boolean
+
+Allow installing "staged" published packages, as defined by [npm RFC PR
+#92](https://github.com/npm/rfcs/pull/92).
+
+This is experimental, and not implemented by the npm public registry.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for init-author-email 1`] = `
+#### \`init-author-email\`
+
+* Default: ""
+* Type: String
+
+The value \`npm init\` should use by default for the package author's email.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for init-author-name 1`] = `
+#### \`init-author-name\`
+
+* Default: ""
+* Type: String
+
+The value \`npm init\` should use by default for the package author's name.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for init-author-url 1`] = `
+#### \`init-author-url\`
+
+* Default: ""
+* Type: "" or URL
+
+The value \`npm init\` should use by default for the package author's
+homepage.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for init-license 1`] = `
+#### \`init-license\`
+
+* Default: "ISC"
+* Type: String
+
+The value \`npm init\` should use by default for the package license.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for init-module 1`] = `
+#### \`init-module\`
+
+* Default: "~/.npm-init.js"
+* Type: Path
+
+A module that will be loaded by the \`npm init\` command. See the
+documentation for the
+[init-package-json](https://github.com/npm/init-package-json) module for
+more information, or [npm init](/commands/npm-init).
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for init-version 1`] = `
+#### \`init-version\`
+
+* Default: "1.0.0"
+* Type: SemVer string
+
+The value that \`npm init\` should use by default for the package version
+number, if not already set in package.json.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for init.author.email 1`] = `
+#### \`init.author.email\`
+
+* Default: ""
+* Type: String
+* DEPRECATED: Use \`--init-author-email\` instead.
+
+Alias for \`--init-author-email\`
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for init.author.name 1`] = `
+#### \`init.author.name\`
+
+* Default: ""
+* Type: String
+* DEPRECATED: Use \`--init-author-name\` instead.
+
+Alias for \`--init-author-name\`
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for init.author.url 1`] = `
+#### \`init.author.url\`
+
+* Default: ""
+* Type: "" or URL
+* DEPRECATED: Use \`--init-author-url\` instead.
+
+Alias for \`--init-author-url\`
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for init.license 1`] = `
+#### \`init.license\`
+
+* Default: "ISC"
+* Type: String
+* DEPRECATED: Use \`--init-license\` instead.
+
+Alias for \`--init-license\`
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for init.module 1`] = `
+#### \`init.module\`
+
+* Default: "~/.npm-init.js"
+* Type: Path
+* DEPRECATED: Use \`--init-module\` instead.
+
+Alias for \`--init-module\`
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for init.version 1`] = `
+#### \`init.version\`
+
+* Default: "1.0.0"
+* Type: SemVer string
+* DEPRECATED: Use \`--init-version\` instead.
+
+Alias for \`--init-version\`
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for json 1`] = `
+#### \`json\`
+
+* Default: false
+* Type: Boolean
+
+Whether or not to output JSON data, rather than the normal output.
+
+Not supported by all npm commands.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for key 1`] = `
+#### \`key\`
+
+* Default: null
+* Type: null or String
+
+A client key to pass when accessing the registry. Values should be in PEM
+format with newlines replaced by the string "\\n". For example:
+
+\`\`\`ini
+key="-----BEGIN PRIVATE KEY-----\\nXXXX\\nXXXX\\n-----END PRIVATE KEY-----"
+\`\`\`
+
+It is _not_ the path to a key file (and there is no "keyfile" option).
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for legacy-bundling 1`] = `
+#### \`legacy-bundling\`
+
+* Default: false
+* Type: Boolean
+
+Causes npm to install the package such that versions of npm prior to 1.4,
+such as the one included with node 0.8, can install the package. This
+eliminates all automatic deduping. If used with \`global-style\` this option
+will be preferred.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for legacy-peer-deps 1`] = `
+#### \`legacy-peer-deps\`
+
+* Default: false
+* Type: Boolean
+
+Causes npm to completely ignore \`peerDependencies\` when building a package
+tree, as in npm versions 3 through 6.
+
+If a package cannot be installed because of overly strict \`peerDependencies\`
+that collide, it provides a way to move forward resolving the situation.
+
+This differs from \`--omit=peer\`, in that \`--omit=peer\` will avoid unpacking
+\`peerDependencies\` on disk, but will still design a tree such that
+\`peerDependencies\` _could_ be unpacked in a correct place.
+
+Use of \`legacy-peer-deps\` is not recommended, as it will not enforce the
+\`peerDependencies\` contract that meta-dependencies may rely on.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for link 1`] = `
+#### \`link\`
+
+* Default: false
+* Type: Boolean
+
+Used with \`npm ls\`, limiting output to only those packages that are linked.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for local-address 1`] = `
+#### \`local-address\`
+
+* Default: null
+* Type: IP Address
+
+The IP address of the local interface to use when making connections to the
+npm registry. Must be IPv4 in versions of Node prior to 0.12.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for loglevel 1`] = `
+#### \`loglevel\`
+
+* Default: "notice"
+* Type: "silent", "error", "warn", "notice", "http", "timing", "info",
+ "verbose", or "silly"
+
+What level of logs to report. On failure, *all* logs are written to
+\`npm-debug.log\` in the current working directory.
+
+Any logs of a higher level than the setting are shown. The default is
+"notice".
+
+See also the \`foreground-scripts\` config.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for logs-max 1`] = `
+#### \`logs-max\`
+
+* Default: 10
+* Type: Number
+
+The maximum number of log files to store.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for long 1`] = `
+#### \`long\`
+
+* Default: false
+* Type: Boolean
+
+Show extended information in \`ls\`, \`search\`, and \`help-search\`.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for maxsockets 1`] = `
+#### \`maxsockets\`
+
+* Default: 15
+* Type: Number
+
+The maximum number of connections to use per origin (protocol/host/port
+combination).
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for message 1`] = `
+#### \`message\`
+
+* Default: "%s"
+* Type: String
+
+Commit message which is used by \`npm version\` when creating version commit.
+
+Any "%s" in the message will be replaced with the version number.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for node-options 1`] = `
+#### \`node-options\`
+
+* Default: null
+* Type: null or String
+
+Options to pass through to Node.js via the \`NODE_OPTIONS\` environment
+variable. This does not impact how npm itself is executed but it does impact
+how lifecycle scripts are called.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for node-version 1`] = `
+#### \`node-version\`
+
+* Default: Node.js \`process.version\` value
+* Type: SemVer string
+
+The node version to use when checking a package's \`engines\` setting.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for noproxy 1`] = `
+#### \`noproxy\`
+
+* Default: The value of the NO_PROXY environment variable
+* Type: String (can be set multiple times)
+
+Domain extensions that should bypass any proxies.
+
+Also accepts a comma-delimited string.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for npm-version 1`] = `
+#### \`npm-version\`
+
+* Default: Output of \`npm --version\`
+* Type: SemVer string
+
+The npm version to use when checking a package's \`engines\` setting.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for offline 1`] = `
+#### \`offline\`
+
+* Default: false
+* Type: Boolean
+
+Force offline mode: no network requests will be done during install. To
+allow the CLI to fill in missing cache data, see \`--prefer-offline\`.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for omit 1`] = `
+#### \`omit\`
+
+* Default: 'dev' if the \`NODE_ENV\` environment variable is set to
+ 'production', otherwise empty.
+* Type: "dev", "optional", or "peer" (can be set multiple times)
+
+Dependency types to omit from the installation tree on disk.
+
+Note that these dependencies _are_ still resolved and added to the
+\`package-lock.json\` or \`npm-shrinkwrap.json\` file. They are just not
+physically installed on disk.
+
+If a package type appears in both the \`--include\` and \`--omit\` lists, then
+it will be included.
+
+If the resulting omit list includes \`'dev'\`, then the \`NODE_ENV\` environment
+variable will be set to \`'production'\` for all lifecycle scripts.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for only 1`] = `
+#### \`only\`
+
+* Default: null
+* Type: null, "prod", or "production"
+* DEPRECATED: Use \`--omit=dev\` to omit dev dependencies from the install.
+
+When set to \`prod\` or \`production\`, this is an alias for \`--omit=dev\`.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for optional 1`] = `
+#### \`optional\`
+
+* Default: null
+* Type: null or Boolean
+* DEPRECATED: Use \`--omit=optional\` to exclude optional dependencies, or
+ \`--include=optional\` to include them.
+
+Default value does install optional deps unless otherwise omitted.
+
+Alias for --include=optional or --omit=optional
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for otp 1`] = `
+#### \`otp\`
+
+* Default: null
+* Type: null or String
+
+This is a one-time password from a two-factor authenticator. It's needed
+when publishing or changing package permissions with \`npm access\`.
+
+If not set, and a registry response fails with a challenge for a one-time
+password, npm will prompt on the command line for one.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for pack-destination 1`] = `
+#### \`pack-destination\`
+
+* Default: "."
+* Type: String
+
+Directory in which \`npm pack\` will save tarballs.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for package 1`] = `
+#### \`package\`
+
+* Default:
+* Type: String (can be set multiple times)
+
+The package to install for [\`npm exec\`](/commands/npm-exec)
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for package-lock 1`] = `
+#### \`package-lock\`
+
+* Default: true
+* Type: Boolean
+
+If set to false, then ignore \`package-lock.json\` files when installing. This
+will also prevent _writing_ \`package-lock.json\` if \`save\` is true.
+
+When package package-locks are disabled, automatic pruning of extraneous
+modules will also be disabled. To remove extraneous modules with
+package-locks disabled use \`npm prune\`.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for package-lock-only 1`] = `
+#### \`package-lock-only\`
+
+* Default: false
+* Type: Boolean
+
+If set to true, the current operation will only use the \`package-lock.json\`,
+ignoring \`node_modules\`.
+
+For \`update\` this means only the \`package-lock.json\` will be updated,
+instead of checking \`node_modules\` and downloading dependencies.
+
+For \`list\` this means the output will be based on the tree described by the
+\`package-lock.json\`, rather than the contents of \`node_modules\`.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for parseable 1`] = `
+#### \`parseable\`
+
+* Default: false
+* Type: Boolean
+
+Output parseable results from commands that write to standard output. For
+\`npm search\`, this will be tab-separated table format.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for prefer-offline 1`] = `
+#### \`prefer-offline\`
+
+* Default: false
+* Type: Boolean
+
+If true, staleness checks for cached data will be bypassed, but missing data
+will be requested from the server. To force full offline mode, use
+\`--offline\`.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for prefer-online 1`] = `
+#### \`prefer-online\`
+
+* Default: false
+* Type: Boolean
+
+If true, staleness checks for cached data will be forced, making the CLI
+look for updates immediately even for fresh package data.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for prefix 1`] = `
+#### \`prefix\`
+
+* Default: In global mode, the folder where the node executable is installed.
+ In local mode, the nearest parent folder containing either a package.json
+ file or a node_modules folder.
+* Type: Path
+
+The location to install global items. If set on the command line, then it
+forces non-global commands to run in the specified folder.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for preid 1`] = `
+#### \`preid\`
+
+* Default: ""
+* Type: String
+
+The "prerelease identifier" to use as a prefix for the "prerelease" part of
+a semver. Like the \`rc\` in \`1.2.0-rc.8\`.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for production 1`] = `
+#### \`production\`
+
+* Default: null
+* Type: null or Boolean
+* DEPRECATED: Use \`--omit=dev\` instead.
+
+Alias for \`--omit=dev\`
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for progress 1`] = `
+#### \`progress\`
+
+* Default: \`true\` unless running in a known CI system
+* Type: Boolean
+
+When set to \`true\`, npm will display a progress bar during time intensive
+operations, if \`process.stderr\` is a TTY.
+
+Set to \`false\` to suppress the progress bar.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for proxy 1`] = `
+#### \`proxy\`
+
+* Default: null
+* Type: null, false, or URL
+
+A proxy to use for outgoing http requests. If the \`HTTP_PROXY\` or
+\`http_proxy\` environment variables are set, proxy settings will be honored
+by the underlying \`request\` library.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for read-only 1`] = `
+#### \`read-only\`
+
+* Default: false
+* Type: Boolean
+
+This is used to mark a token as unable to publish when configuring limited
+access tokens with the \`npm token create\` command.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for rebuild-bundle 1`] = `
+#### \`rebuild-bundle\`
+
+* Default: true
+* Type: Boolean
+
+Rebuild bundled dependencies after installation.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for registry 1`] = `
+#### \`registry\`
+
+* Default: "https://registry.npmjs.org/"
+* Type: URL
+
+The base URL of the npm registry.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for save 1`] = `
+#### \`save\`
+
+* Default: true
+* Type: Boolean
+
+Save installed packages to a package.json file as dependencies.
+
+When used with the \`npm rm\` command, removes the dependency from
+package.json.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for save-bundle 1`] = `
+#### \`save-bundle\`
+
+* Default: false
+* Type: Boolean
+
+If a package would be saved at install time by the use of \`--save\`,
+\`--save-dev\`, or \`--save-optional\`, then also put it in the
+\`bundleDependencies\` list.
+
+Ignore if \`--save-peer\` is set, since peerDependencies cannot be bundled.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for save-dev 1`] = `
+#### \`save-dev\`
+
+* Default: false
+* Type: Boolean
+
+Save installed packages to a package.json file as \`devDependencies\`.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for save-exact 1`] = `
+#### \`save-exact\`
+
+* Default: false
+* Type: Boolean
+
+Dependencies saved to package.json will be configured with an exact version
+rather than using npm's default semver range operator.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for save-optional 1`] = `
+#### \`save-optional\`
+
+* Default: false
+* Type: Boolean
+
+Save installed packages to a package.json file as \`optionalDependencies\`.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for save-peer 1`] = `
+#### \`save-peer\`
+
+* Default: false
+* Type: Boolean
+
+Save installed packages. to a package.json file as \`peerDependencies\`
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for save-prefix 1`] = `
+#### \`save-prefix\`
+
+* Default: "^"
+* Type: String
+
+Configure how versions of packages installed to a package.json file via
+\`--save\` or \`--save-dev\` get prefixed.
+
+For example if a package has version \`1.2.3\`, by default its version is set
+to \`^1.2.3\` which allows minor upgrades for that package, but after \`npm
+config set save-prefix='~'\` it would be set to \`~1.2.3\` which only allows
+patch upgrades.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for save-prod 1`] = `
+#### \`save-prod\`
+
+* Default: false
+* Type: Boolean
+
+Save installed packages into \`dependencies\` specifically. This is useful if
+a package already exists in \`devDependencies\` or \`optionalDependencies\`, but
+you want to move it to be a non-optional production dependency.
+
+This is the default behavior if \`--save\` is true, and neither \`--save-dev\`
+or \`--save-optional\` are true.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for scope 1`] = `
+#### \`scope\`
+
+* Default: the scope of the current project, if any, or ""
+* Type: String
+
+Associate an operation with a scope for a scoped registry.
+
+Useful when logging in to or out of a private registry:
+
+\`\`\`
+# log in, linking the scope to the custom registry
+npm login --scope=@mycorp --registry=https://registry.mycorp.com
+
+# log out, removing the link and the auth token
+npm logout --scope=@mycorp
+\`\`\`
+
+This will cause \`@mycorp\` to be mapped to the registry for future
+installation of packages specified according to the pattern
+\`@mycorp/package\`.
+
+This will also cause \`npm init\` to create a scoped package.
+
+\`\`\`
+# accept all defaults, and create a package named "@foo/whatever",
+# instead of just named "whatever"
+npm init --scope=@foo --yes
+\`\`\`
+
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for script-shell 1`] = `
+#### \`script-shell\`
+
+* Default: '/bin/sh' on POSIX systems, 'cmd.exe' on Windows
+* Type: null or String
+
+The shell to use for scripts run with the \`npm exec\`, \`npm run\` and \`npm
+init \` commands.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for searchexclude 1`] = `
+#### \`searchexclude\`
+
+* Default: ""
+* Type: String
+
+Space-separated options that limit the results from search.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for searchlimit 1`] = `
+#### \`searchlimit\`
+
+* Default: 20
+* Type: Number
+
+Number of items to limit search results to. Will not apply at all to legacy
+searches.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for searchopts 1`] = `
+#### \`searchopts\`
+
+* Default: ""
+* Type: String
+
+Space-separated options that are always passed to search.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for searchstaleness 1`] = `
+#### \`searchstaleness\`
+
+* Default: 900
+* Type: Number
+
+The age of the cache, in seconds, before another registry request is made if
+using legacy search endpoint.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for shell 1`] = `
+#### \`shell\`
+
+* Default: SHELL environment variable, or "bash" on Posix, or "cmd.exe" on
+ Windows
+* Type: String
+
+The shell to run for the \`npm explore\` command.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for shrinkwrap 1`] = `
+#### \`shrinkwrap\`
+
+* Default: true
+* Type: Boolean
+* DEPRECATED: Use the --package-lock setting instead.
+
+Alias for --package-lock
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for sign-git-commit 1`] = `
+#### \`sign-git-commit\`
+
+* Default: false
+* Type: Boolean
+
+If set to true, then the \`npm version\` command will commit the new package
+version using \`-S\` to add a signature.
+
+Note that git requires you to have set up GPG keys in your git configs for
+this to work properly.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for sign-git-tag 1`] = `
+#### \`sign-git-tag\`
+
+* Default: false
+* Type: Boolean
+
+If set to true, then the \`npm version\` command will tag the version using
+\`-s\` to add a signature.
+
+Note that git requires you to have set up GPG keys in your git configs for
+this to work properly.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for sso-poll-frequency 1`] = `
+#### \`sso-poll-frequency\`
+
+* Default: 500
+* Type: Number
+* DEPRECATED: The --auth-type method of SSO/SAML/OAuth will be removed in a
+ future version of npm in favor of web-based login.
+
+When used with SSO-enabled \`auth-type\`s, configures how regularly the
+registry should be polled while the user is completing authentication.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for sso-type 1`] = `
+#### \`sso-type\`
+
+* Default: "oauth"
+* Type: null, "oauth", or "saml"
+* DEPRECATED: The --auth-type method of SSO/SAML/OAuth will be removed in a
+ future version of npm in favor of web-based login.
+
+If \`--auth-type=sso\`, the type of SSO type to use.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for strict-peer-deps 1`] = `
+#### \`strict-peer-deps\`
+
+* Default: false
+* Type: Boolean
+
+If set to \`true\`, and \`--legacy-peer-deps\` is not set, then _any_
+conflicting \`peerDependencies\` will be treated as an install failure, even
+if npm could reasonably guess the appropriate resolution based on non-peer
+dependency relationships.
+
+By default, conflicting \`peerDependencies\` deep in the dependency graph will
+be resolved using the nearest non-peer dependency specification, even if
+doing so will result in some packages receiving a peer dependency outside
+the range set in their package's \`peerDependencies\` object.
+
+When such and override is performed, a warning is printed, explaining the
+conflict and the packages involved. If \`--strict-peer-deps\` is set, then
+this warning is treated as a failure.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for strict-ssl 1`] = `
+#### \`strict-ssl\`
+
+* Default: true
+* Type: Boolean
+
+Whether or not to do SSL key validation when making requests to the registry
+via https.
+
+See also the \`ca\` config.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for tag 1`] = `
+#### \`tag\`
+
+* Default: "latest"
+* Type: String
+
+If you ask npm to install a package and don't tell it a specific version,
+then it will install the specified tag.
+
+Also the tag that is added to the package@version specified by the \`npm tag\`
+command, if no explicit tag is given.
+
+When used by the \`npm diff\` command, this is the tag used to fetch the
+tarball that will be compared with the local files by default.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for tag-version-prefix 1`] = `
+#### \`tag-version-prefix\`
+
+* Default: "v"
+* Type: String
+
+If set, alters the prefix used when tagging a new version when performing a
+version increment using \`npm-version\`. To remove the prefix altogether, set
+it to the empty string: \`""\`.
+
+Because other tools may rely on the convention that npm version tags look
+like \`v1.0.0\`, _only use this property if it is absolutely necessary_. In
+particular, use care when overriding this setting for public packages.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for timing 1`] = `
+#### \`timing\`
+
+* Default: false
+* Type: Boolean
+
+If true, writes an \`npm-debug\` log to \`_logs\` and timing information to
+\`_timing.json\`, both in your cache, even if the command completes
+successfully. \`_timing.json\` is a newline delimited list of JSON objects.
+
+You can quickly view it with this [json](https://npm.im/json) command line:
+\`npm exec -- json -g < ~/.npm/_timing.json\`.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for tmp 1`] = `
+#### \`tmp\`
+
+* Default: The value returned by the Node.js \`os.tmpdir()\` method
+
+* Type: Path
+* DEPRECATED: This setting is no longer used. npm stores temporary files in a
+ special location in the cache, and they are managed by
+ [\`cacache\`](http://npm.im/cacache).
+
+Historically, the location where temporary files were stored. No longer
+relevant.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for umask 1`] = `
+#### \`umask\`
+
+* Default: 0
+* Type: Octal numeric string in range 0000..0777 (0..511)
+
+The "umask" value to use when setting the file creation mode on files and
+folders.
+
+Folders and executables are given a mode which is \`0o777\` masked against
+this value. Other files are given a mode which is \`0o666\` masked against
+this value.
+
+Note that the underlying system will _also_ apply its own umask value to
+files and folders that are created, and npm does not circumvent this, but
+rather adds the \`--umask\` config to it.
+
+Thus, the effective default umask value on most POSIX systems is 0o22,
+meaning that folders and executables are created with a mode of 0o755 and
+other files are created with a mode of 0o644.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for unicode 1`] = `
+#### \`unicode\`
+
+* Default: false on windows, true on mac/unix systems with a unicode locale,
+ as defined by the \`LC_ALL\`, \`LC_CTYPE\`, or \`LANG\` environment variables.
+* Type: Boolean
+
+When set to true, npm uses unicode characters in the tree output. When
+false, it uses ascii characters instead of unicode glyphs.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for update-notifier 1`] = `
+#### \`update-notifier\`
+
+* Default: true
+* Type: Boolean
+
+Set to false to suppress the update notification when using an older version
+of npm than the latest.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for usage 1`] = `
+#### \`usage\`
+
+* Default: false
+* Type: Boolean
+
+Show short usage output about the command specified.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for user-agent 1`] = `
+#### \`user-agent\`
+
+* Default: "npm/{npm-version} node/{node-version} {platform} {arch}
+ workspaces/{workspaces} {ci}"
+* Type: String
+
+Sets the User-Agent request header. The following fields are replaced with
+their actual counterparts:
+
+* \`{npm-version}\` - The npm version in use
+* \`{node-version}\` - The Node.js version in use
+* \`{platform}\` - The value of \`process.platform\`
+* \`{arch}\` - The value of \`process.arch\`
+* \`{workspaces}\` - Set to \`true\` if the \`workspaces\` or \`workspace\` options
+ are set.
+* \`{ci}\` - The value of the \`ci-name\` config, if set, prefixed with \`ci/\`, or
+ an empty string if \`ci-name\` is empty.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for userconfig 1`] = `
+#### \`userconfig\`
+
+* Default: "~/.npmrc"
+* Type: Path
+
+The location of user-level configuration settings.
+
+This may be overridden by the \`npm_config_userconfig\` environment variable
+or the \`--userconfig\` command line option, but may _not_ be overridden by
+settings in the \`globalconfig\` file.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for version 1`] = `
+#### \`version\`
+
+* Default: false
+* Type: Boolean
+
+If true, output the npm version and exit successfully.
+
+Only relevant when specified explicitly on the command line.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for versions 1`] = `
+#### \`versions\`
+
+* Default: false
+* Type: Boolean
+
+If true, output the npm version as well as node's \`process.versions\` map and
+the version in the current working directory's \`package.json\` file if one
+exists, and exit successfully.
+
+Only relevant when specified explicitly on the command line.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for viewer 1`] = `
+#### \`viewer\`
+
+* Default: "man" on Posix, "browser" on Windows
+* Type: String
+
+The program to use to view help content.
+
+Set to \`"browser"\` to view html help content in the default web browser.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for which 1`] = `
+#### \`which\`
+
+* Default: null
+* Type: null or Number
+
+If there are multiple funding sources, which 1-indexed source URL to open.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for workspace 1`] = `
+#### \`workspace\`
+
+* Default:
+* Type: String (can be set multiple times)
+
+Enable running a command in the context of the configured workspaces of the
+current project while filtering by running only the workspaces defined by
+this configuration option.
+
+Valid values for the \`workspace\` config are either:
+
+* Workspace names
+* Path to a workspace directory
+* Path to a parent workspace directory (will result to selecting all of the
+ nested workspaces)
+
+When set for the \`npm init\` command, this may be set to the folder of a
+workspace which does not yet exist, to create the folder and set it up as a
+brand new workspace within the project.
+
+This value is not exported to the environment for child processes.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for workspaces 1`] = `
+#### \`workspaces\`
+
+* Default: false
+* Type: Boolean
+
+Enable running a command in the context of **all** the configured
+workspaces.
+
+This value is not exported to the environment for child processes.
+`
+
+exports[`test/lib/utils/config/definitions.js TAP > config description for yes 1`] = `
+#### \`yes\`
+
+* Default: null
+* Type: null or Boolean
+
+Automatically answer "yes" to any prompts that npm might print on the
+command line.
+`
diff --git a/deps/npm/tap-snapshots/test/lib/utils/error-handler.js.test.cjs b/deps/npm/tap-snapshots/test/lib/utils/exit-handler.js.test.cjs
similarity index 66%
rename from deps/npm/tap-snapshots/test/lib/utils/error-handler.js.test.cjs
rename to deps/npm/tap-snapshots/test/lib/utils/exit-handler.js.test.cjs
index 78a9eef217f353..0a5ed59a1157ce 100644
--- a/deps/npm/tap-snapshots/test/lib/utils/error-handler.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/utils/exit-handler.js.test.cjs
@@ -5,14 +5,14 @@
* Make sure to inspect the output below. Do not ignore changes!
*/
'use strict'
-exports[`test/lib/utils/error-handler.js TAP handles unknown error > should have expected log contents for unknown error 1`] = `
+exports[`test/lib/utils/exit-handler.js TAP handles unknown error > should have expected log contents for unknown error 1`] = `
0 verbose code 1
1 error foo A complete log of this run can be found in:
-1 error foo {CWD}/test/lib/utils/tap-testdir-error-handler/_logs/expecteddate-debug.log
+1 error foo {CWD}/test/lib/utils/tap-testdir-exit-handler/_logs/expecteddate-debug.log
2 verbose stack Error: ERROR
3 verbose cwd {CWD}
4 verbose Foo 1.0.0
-5 verbose argv "/node" "{CWD}/test/lib/utils/error-handler.js"
+5 verbose argv "/node" "{CWD}/test/lib/utils/exit-handler.js"
6 verbose node v1.0.0
7 verbose npm v1.0.0
8 error foo code ERROR
diff --git a/deps/npm/test/fixtures/mock-npm.js b/deps/npm/test/fixtures/mock-npm.js
index c972c35b318611..1de080eb10b4a8 100644
--- a/deps/npm/test/fixtures/mock-npm.js
+++ b/deps/npm/test/fixtures/mock-npm.js
@@ -1,9 +1,52 @@
-// Basic npm fixture that you can give a config object that acts like
-// npm.config You still need a separate flatOptions but this is the first step
-// to eventually just using npm itself
+const npmlog = require('npmlog')
+const perf = require('../../lib/utils/perf.js')
+perf.reset()
+const procLog = require('../../lib/utils/proc-log-listener.js')
+procLog.reset()
+
+const realLog = {}
+for (const level of ['silly', 'verbose', 'timing', 'notice', 'warn', 'error'])
+ realLog[level] = npmlog[level]
+
+const { title, execPath } = process
+
+const RealMockNpm = (t, otherMocks = {}) => {
+ t.teardown(() => {
+ for (const level of ['silly', 'verbose', 'timing', 'notice', 'warn', 'error'])
+ npmlog[level] = realLog[level]
+ perf.reset()
+ procLog.reset()
+ process.title = title
+ process.execPath = execPath
+ delete process.env.npm_command
+ delete process.env.COLOR
+ })
+ const logs = []
+ const outputs = []
+ const npm = t.mock('../../lib/npm.js', otherMocks)
+ const command = async (command, args = []) => {
+ return new Promise((resolve, reject) => {
+ npm.commands[command](args, err => {
+ if (err)
+ return reject(err)
+ return resolve()
+ })
+ })
+ }
+ for (const level of ['silly', 'verbose', 'timing', 'notice', 'warn', 'error']) {
+ npmlog[level] = (...msg) => {
+ logs.push([level, ...msg])
+ }
+ }
+ npm.output = (...msg) => outputs.push(msg)
+ return { npm, logs, outputs, command }
+}
const realConfig = require('../../lib/utils/config')
+// Basic npm fixture that you can give a config object that acts like
+// npm.config You still need a separate flatOptions. Tests should migrate to
+// using the real npm mock above
class MockNpm {
constructor (base = {}) {
this._mockOutputs = []
@@ -51,7 +94,11 @@ class MockNpm {
}
}
-// TODO export MockNpm, and change tests to use new MockNpm()
-module.exports = (base = {}) => {
- return new MockNpm(base)
+const FakeMockNpm = (base = {}) => {
+ return new MockNpm(base)
+}
+
+module.exports = {
+ fake: FakeMockNpm,
+ real: RealMockNpm
}
diff --git a/deps/npm/test/lib/audit.js b/deps/npm/test/lib/audit.js
index bb6f06debc51f7..561765a0270b55 100644
--- a/deps/npm/test/lib/audit.js
+++ b/deps/npm/test/lib/audit.js
@@ -1,5 +1,5 @@
const t = require('tap')
-const mockNpm = require('../fixtures/mock-npm')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
t.test('should audit using Arborist', t => {
let ARB_ARGS = null
diff --git a/deps/npm/test/lib/bin.js b/deps/npm/test/lib/bin.js
index 898e7ba439b88e..8ceca8280f52d4 100644
--- a/deps/npm/test/lib/bin.js
+++ b/deps/npm/test/lib/bin.js
@@ -1,5 +1,5 @@
const t = require('tap')
-const mockNpm = require('../fixtures/mock-npm')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
t.test('bin', (t) => {
t.plan(4)
diff --git a/deps/npm/test/lib/birthday.js b/deps/npm/test/lib/birthday.js
index 0589be7a8eedbf..05660d6fa3f205 100644
--- a/deps/npm/test/lib/birthday.js
+++ b/deps/npm/test/lib/birthday.js
@@ -1,5 +1,5 @@
const t = require('tap')
-const mockNpm = require('../fixtures/mock-npm')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
const config = {
yes: false,
diff --git a/deps/npm/test/lib/cache.js b/deps/npm/test/lib/cache.js
index bad0ede89e1013..d3d6f5b8845def 100644
--- a/deps/npm/test/lib/cache.js
+++ b/deps/npm/test/lib/cache.js
@@ -1,5 +1,5 @@
const t = require('tap')
-const mockNpm = require('../fixtures/mock-npm')
+const { fake: mockNpm } = require('../fixtures/mock-npm.js')
const path = require('path')
const usageUtil = () => 'usage instructions'
diff --git a/deps/npm/test/lib/ci.js b/deps/npm/test/lib/ci.js
index b60375c2898427..b6b2af9c111db6 100644
--- a/deps/npm/test/lib/ci.js
+++ b/deps/npm/test/lib/ci.js
@@ -4,7 +4,7 @@ const readdir = util.promisify(fs.readdir)
const t = require('tap')
-const mockNpm = require('../fixtures/mock-npm')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
t.test('should ignore scripts with --ignore-scripts', (t) => {
const SCRIPTS = []
diff --git a/deps/npm/test/lib/cli.js b/deps/npm/test/lib/cli.js
index d0a9e0bd492008..b85c981cd008bb 100644
--- a/deps/npm/test/lib/cli.js
+++ b/deps/npm/test/lib/cli.js
@@ -1,43 +1,22 @@
const t = require('tap')
-let LOAD_ERROR = null
-const npmOutputs = []
-const npmock = {
- log: { level: 'silent' },
- output: (...msg) => npmOutputs.push(msg),
- usage: 'npm usage test example',
- version: '99.99.99',
- load: cb => cb(LOAD_ERROR),
- argv: [],
- config: {
- settings: {},
- get: (k) => npmock.config.settings[k],
- set: (k, v) => {
- npmock.config.settings[k] = v
- },
- },
- commands: {},
-}
+const { real: mockNpm } = require('../fixtures/mock-npm.js')
const unsupportedMock = {
checkForBrokenNode: () => {},
checkForUnsupportedNode: () => {},
}
-let errorHandlerCalled = null
-let errorHandlerNpm = null
-let errorHandlerCb
-const errorHandlerMock = (...args) => {
- errorHandlerCalled = args
- if (errorHandlerCb)
- errorHandlerCb()
-}
-let errorHandlerExitCalled = null
-errorHandlerMock.exit = code => {
- errorHandlerExitCalled = code
+let exitHandlerCalled = null
+let exitHandlerNpm = null
+let exitHandlerCb
+const exitHandlerMock = (...args) => {
+ exitHandlerCalled = args
+ if (exitHandlerCb)
+ exitHandlerCb()
}
-errorHandlerMock.setNpm = npm => {
- errorHandlerNpm = npm
+exitHandlerMock.setNpm = npm => {
+ exitHandlerNpm = npm
}
const logs = []
@@ -47,188 +26,122 @@ const npmlogMock = {
info: (...msg) => logs.push(['info', ...msg]),
}
-const cli = t.mock('../../lib/cli.js', {
- '../../lib/npm.js': npmock,
+const cliMock = (npm) => t.mock('../../lib/cli.js', {
+ '../../lib/npm.js': npm,
'../../lib/utils/update-notifier.js': async () => null,
- '../../lib/utils/did-you-mean.js': () => '\ntest did you mean',
'../../lib/utils/unsupported.js': unsupportedMock,
- '../../lib/utils/error-handler.js': errorHandlerMock,
+ '../../lib/utils/exit-handler.js': exitHandlerMock,
npmlog: npmlogMock,
})
-t.test('print the version, and treat npm_g to npm -g', t => {
- t.teardown(() => {
- delete npmock.config.settings.version
- process.argv = argv
- npmock.argv.length = 0
- proc.argv.length = 0
- logs.length = 0
- npmOutputs.length = 0
- errorHandlerExitCalled = null
- })
-
- const { argv } = process
- const proc = {
- argv: ['node', 'npm_g', '-v'],
- version: '420.69.lol',
+const processMock = (proc) => {
+ const mocked = {
+ ...process,
on: () => {},
+ ...proc,
}
- process.argv = proc.argv
- npmock.config.settings.version = true
+ // nopt looks at process directly
+ process.argv = mocked.argv
+ return mocked
+}
+
+const { argv } = process
+
+t.afterEach(() => {
+ logs.length = 0
+ process.argv = argv
+ exitHandlerCalled = null
+ exitHandlerNpm = null
+})
+
+t.test('print the version, and treat npm_g as npm -g', async t => {
+ const proc = processMock({
+ argv: ['node', 'npm_g', '-v'],
+ version: process.version,
+ })
- cli(proc)
+ const { npm, outputs } = mockNpm(t)
+ const cli = cliMock(npm)
+ await cli(proc)
- t.strictSame(npmock.argv, [])
- t.strictSame(proc.argv, ['node', 'npm', '-g', '-v'])
+ t.strictSame(proc.argv, ['node', 'npm', '-g', '-v'], 'npm process.argv was rewritten')
+ t.strictSame(process.argv, ['node', 'npm', '-g', '-v'], 'system process.argv was rewritten')
t.strictSame(logs, [
'pause',
- ['verbose', 'cli', ['node', 'npm', '-g', '-v']],
- ['info', 'using', 'npm@%s', '99.99.99'],
- ['info', 'using', 'node@%s', '420.69.lol'],
+ ['verbose', 'cli', proc.argv],
+ ['info', 'using', 'npm@%s', npm.version],
+ ['info', 'using', 'node@%s', process.version],
])
- t.strictSame(npmOutputs, [['99.99.99']])
- t.strictSame(errorHandlerExitCalled, 0)
-
- t.end()
+ t.strictSame(outputs, [[npm.version]])
+ t.strictSame(exitHandlerCalled, [])
})
-t.test('calling with --versions calls npm version with no args', t => {
- const processArgv = process.argv
- const proc = {
+t.test('calling with --versions calls npm version with no args', async t => {
+ const proc = processMock({
argv: ['node', 'npm', 'install', 'or', 'whatever', '--versions'],
- on: () => {},
- }
- process.argv = proc.argv
- npmock.config.set('versions', true)
-
- t.teardown(() => {
- delete npmock.config.settings.versions
- process.argv = processArgv
- npmock.argv.length = 0
- proc.argv.length = 0
- logs.length = 0
- npmOutputs.length = 0
- errorHandlerExitCalled = null
- delete npmock.commands.version
})
+ const { npm, outputs } = mockNpm(t)
+ const cli = cliMock(npm)
- npmock.commands.version = (args, cb) => {
- t.equal(proc.title, 'npm')
- t.strictSame(npmock.argv, [])
- t.strictSame(proc.argv, ['node', 'npm', 'install', 'or', 'whatever', '--versions'])
- t.strictSame(logs, [
- 'pause',
- ['verbose', 'cli', ['node', 'npm', 'install', 'or', 'whatever', '--versions']],
- ['info', 'using', 'npm@%s', '99.99.99'],
- ['info', 'using', 'node@%s', undefined],
- ])
-
- t.strictSame(npmOutputs, [])
- t.strictSame(errorHandlerExitCalled, null)
-
- t.strictSame(args, [])
- t.end()
+ let versionArgs
+ npm.commands.version = (args, cb) => {
+ versionArgs = args
+ cb()
}
- cli(proc)
-})
+ await cli(proc)
+ t.strictSame(versionArgs, [])
+ t.equal(proc.title, 'npm')
+ t.strictSame(npm.argv, [])
+ t.strictSame(logs, [
+ 'pause',
+ ['verbose', 'cli', proc.argv],
+ ['info', 'using', 'npm@%s', npm.version],
+ ['info', 'using', 'node@%s', process.version],
+ ])
-t.test('print usage if no params provided', t => {
- const { output } = npmock
- t.teardown(() => {
- npmock.output = output
- })
- const proc = {
- argv: ['node', 'npm'],
- on: () => {},
- }
- npmock.argv = []
- npmock.output = (msg) => {
- if (msg) {
- t.match(msg, 'npm usage test example', 'outputs npm usage')
- t.end()
- }
- }
- cli(proc)
+ t.strictSame(outputs, [])
+ t.strictSame(exitHandlerCalled, [])
})
-t.test('print usage if non-command param provided', t => {
- const { output } = npmock
- t.teardown(() => {
- npmock.output = output
+t.test('print usage if no params provided', async t => {
+ const proc = processMock({
+ argv: ['node', 'npm'],
})
- const proc = {
- argv: ['node', 'npm', 'asdf'],
- on: () => {},
- }
- npmock.argv = ['asdf']
- npmock.output = (msg) => {
- if (msg) {
- t.match(msg, 'Unknown command: "asdf"\ntest did you mean', 'outputs did you mean')
- t.end()
- }
- }
- cli(proc)
-})
-t.test('gracefully handles error printing usage', t => {
- const { output } = npmock
- t.teardown(() => {
- npmock.output = output
- errorHandlerCb = null
- errorHandlerCalled = null
- })
- const proc = {
- argv: ['node', 'npm'],
- on: () => {},
- }
- npmock.argv = []
- errorHandlerCb = () => {
- t.match(errorHandlerCalled, [], 'should call errorHandler with no args')
- t.match(errorHandlerNpm, npmock, 'errorHandler npm is set')
- t.end()
- }
- cli(proc)
+ const { npm, outputs } = mockNpm(t)
+ const cli = cliMock(npm)
+ await cli(proc)
+ t.match(outputs[0][0], 'Usage:', 'outputs npm usage')
+ t.match(exitHandlerCalled, [], 'should call exitHandler with no args')
+ t.ok(exitHandlerNpm, 'exitHandler npm is set')
+ t.match(proc.exitCode, 1)
})
-t.test('handles output error', t => {
- const { output } = npmock
- t.teardown(() => {
- npmock.output = output
- errorHandlerCb = null
- errorHandlerCalled = null
+t.test('print usage if non-command param provided', async t => {
+ const proc = processMock({
+ argv: ['node', 'npm', 'tset'],
})
- const proc = {
- argv: ['node', 'npm'],
- on: () => {},
- }
- npmock.argv = []
- npmock.output = () => {
- throw new Error('ERR')
- }
- errorHandlerCb = () => {
- t.match(errorHandlerCalled, /ERR/, 'should call errorHandler with error')
- t.end()
- }
- cli(proc)
+
+ const { npm, outputs } = mockNpm(t)
+ const cli = cliMock(npm)
+ await cli(proc)
+ t.match(outputs[0][0], 'Unknown command: "tset"')
+ t.match(outputs[0][0], 'Did you mean this?')
+ t.match(exitHandlerCalled, [], 'should call exitHandler with no args')
+ t.ok(exitHandlerNpm, 'exitHandler npm is set')
+ t.match(proc.exitCode, 1)
})
-t.test('load error calls error handler', t => {
- t.teardown(() => {
- errorHandlerCb = null
- errorHandlerCalled = null
- LOAD_ERROR = null
+t.test('load error calls error handler', async t => {
+ const proc = processMock({
+ argv: ['node', 'npm', 'asdf'],
})
+ const { npm } = mockNpm(t)
+ const cli = cliMock(npm)
const er = new Error('test load error')
- LOAD_ERROR = er
- const proc = {
- argv: ['node', 'npm', 'asdf'],
- on: () => {},
- }
- errorHandlerCb = () => {
- t.strictSame(errorHandlerCalled, [er])
- t.end()
- }
- cli(proc)
+ npm.load = () => Promise.reject(er)
+ await cli(proc)
+ t.strictSame(exitHandlerCalled, [er])
})
diff --git a/deps/npm/test/lib/dedupe.js b/deps/npm/test/lib/dedupe.js
index 801e3c96de3cf3..30f8a380e8ea35 100644
--- a/deps/npm/test/lib/dedupe.js
+++ b/deps/npm/test/lib/dedupe.js
@@ -1,21 +1,20 @@
const t = require('tap')
-const mockNpm = require('../fixtures/mock-npm')
+const { real: mockNpm } = require('../fixtures/mock-npm')
-t.test('should throw in global mode', (t) => {
- const Dedupe = t.mock('../../lib/dedupe.js')
- const npm = mockNpm({
- config: { 'dry-run': false, global: true },
- })
- const dedupe = new Dedupe(npm)
-
- dedupe.exec([], er => {
- t.match(er, { code: 'EDEDUPEGLOBAL' }, 'throws EDEDUPEGLOBAL')
- t.end()
- })
+t.test('should throw in global mode', async (t) => {
+ const { npm, command } = mockNpm(t)
+ await npm.load()
+ npm.config.set('global', true)
+ t.rejects(
+ command('dedupe'),
+ { code: 'EDEDUPEGLOBAL' },
+ 'throws EDEDUPEGLOBALE'
+ )
})
-t.test('should remove dupes using Arborist', (t) => {
- const Dedupe = t.mock('../../lib/dedupe.js', {
+t.test('should remove dupes using Arborist', async (t) => {
+ t.plan(5)
+ const { npm, command } = mockNpm(t, {
'@npmcli/arborist': function (args) {
t.ok(args, 'gets options object')
t.ok(args.path, 'gets path option')
@@ -28,37 +27,24 @@ t.test('should remove dupes using Arborist', (t) => {
t.ok(arb, 'gets arborist tree')
},
})
- const npm = mockNpm({
- prefix: 'foo',
- config: {
- 'dry-run': 'true',
- },
- })
- const dedupe = new Dedupe(npm)
- dedupe.exec([], er => {
- if (er)
- throw er
- t.ok(true, 'callback is called')
- t.end()
- })
+ await npm.load()
+ npm.config.set('prefix', 'foo')
+ npm.config.set('dry-run', 'true')
+ await command('dedupe')
})
-t.test('should remove dupes using Arborist - no arguments', (t) => {
- const Dedupe = t.mock('../../lib/dedupe.js', {
+t.test('should remove dupes using Arborist - no arguments', async (t) => {
+ t.plan(1)
+ const { npm, command } = mockNpm(t, {
'@npmcli/arborist': function (args) {
t.ok(args.dryRun, 'gets dryRun from config')
this.dedupe = () => {}
},
'../../lib/utils/reify-output.js': () => {},
+ '../../lib/utils/reify-finish.js': () => {},
})
- const npm = mockNpm({
- prefix: 'foo',
- config: {
- 'dry-run': 'true',
- },
- })
- const dedupe = new Dedupe(npm)
- dedupe.exec(null, () => {
- t.end()
- })
+ await npm.load()
+ npm.config.set('prefix', 'foo')
+ npm.config.set('dry-run', true)
+ await command('dedupe')
})
diff --git a/deps/npm/test/lib/diff.js b/deps/npm/test/lib/diff.js
index 2fb38c9b127e44..fcba802d93b87e 100644
--- a/deps/npm/test/lib/diff.js
+++ b/deps/npm/test/lib/diff.js
@@ -1,6 +1,6 @@
-const { resolve, join } = require('path')
const t = require('tap')
-const mockNpm = require('../fixtures/mock-npm')
+const { resolve, join } = require('path')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
const noop = () => null
let libnpmdiff = noop
diff --git a/deps/npm/test/lib/dist-tag.js b/deps/npm/test/lib/dist-tag.js
index 9af90c309c77ca..1fb5cb3b6ee625 100644
--- a/deps/npm/test/lib/dist-tag.js
+++ b/deps/npm/test/lib/dist-tag.js
@@ -1,5 +1,5 @@
-const mockNpm = require('../fixtures/mock-npm')
const t = require('tap')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
let result = ''
let log = ''
diff --git a/deps/npm/test/lib/docs.js b/deps/npm/test/lib/docs.js
index 0da070d9a7d137..fbd75842012473 100644
--- a/deps/npm/test/lib/docs.js
+++ b/deps/npm/test/lib/docs.js
@@ -1,5 +1,5 @@
const t = require('tap')
-const mockNpm = require('../fixtures/mock-npm.js')
+const { fake: mockNpm } = require('../fixtures/mock-npm.js')
const { join, sep } = require('path')
const pkgDirs = t.testdir({
diff --git a/deps/npm/test/lib/exec.js b/deps/npm/test/lib/exec.js
index dff067619f2ce8..6d99c7959d88e8 100644
--- a/deps/npm/test/lib/exec.js
+++ b/deps/npm/test/lib/exec.js
@@ -1,5 +1,5 @@
const t = require('tap')
-const mockNpm = require('../fixtures/mock-npm')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
const { resolve, delimiter } = require('path')
const ARB_CTOR = []
diff --git a/deps/npm/test/lib/explore.js b/deps/npm/test/lib/explore.js
index b49c885cbcb269..fd9949e73fc4c7 100644
--- a/deps/npm/test/lib/explore.js
+++ b/deps/npm/test/lib/explore.js
@@ -43,15 +43,11 @@ const mockRunScript = ({ pkg, banner, path, event, stdio }) => {
}
const output = []
-let ERROR_HANDLER_CALLED = null
const logs = []
const getExplore = (windows) => {
const Explore = t.mock('../../lib/explore.js', {
'../../lib/utils/is-windows.js': windows,
path: require('path')[windows ? 'win32' : 'posix'],
- '../../lib/utils/error-handler.js': er => {
- ERROR_HANDLER_CALLED = er
- },
'read-package-json-fast': mockRPJ,
'@npmcli/run-script': mockRunScript,
})
@@ -83,11 +79,9 @@ t.test('basic interactive', t => {
throw er
t.strictSame({
- ERROR_HANDLER_CALLED,
RPJ_CALLED,
RUN_SCRIPT_EXEC,
}, {
- ERROR_HANDLER_CALLED: null,
RPJ_CALLED: 'c:\\npm\\dir\\pkg\\package.json',
RUN_SCRIPT_EXEC: 'shell-command',
})
@@ -102,11 +96,9 @@ t.test('basic interactive', t => {
throw er
t.strictSame({
- ERROR_HANDLER_CALLED,
RPJ_CALLED,
RUN_SCRIPT_EXEC,
}, {
- ERROR_HANDLER_CALLED: null,
RPJ_CALLED: '/npm/dir/pkg/package.json',
RUN_SCRIPT_EXEC: 'shell-command',
})
@@ -136,11 +128,9 @@ t.test('interactive tracks exit code', t => {
throw er
t.strictSame({
- ERROR_HANDLER_CALLED,
RPJ_CALLED,
RUN_SCRIPT_EXEC,
}, {
- ERROR_HANDLER_CALLED: null,
RPJ_CALLED: 'c:\\npm\\dir\\pkg\\package.json',
RUN_SCRIPT_EXEC: 'shell-command',
})
@@ -156,11 +146,9 @@ t.test('interactive tracks exit code', t => {
throw er
t.strictSame({
- ERROR_HANDLER_CALLED,
RPJ_CALLED,
RUN_SCRIPT_EXEC,
}, {
- ERROR_HANDLER_CALLED: null,
RPJ_CALLED: '/npm/dir/pkg/package.json',
RUN_SCRIPT_EXEC: 'shell-command',
})
@@ -224,11 +212,9 @@ t.test('basic non-interactive', t => {
throw er
t.strictSame({
- ERROR_HANDLER_CALLED,
RPJ_CALLED,
RUN_SCRIPT_EXEC,
}, {
- ERROR_HANDLER_CALLED: null,
RPJ_CALLED: 'c:\\npm\\dir\\pkg\\package.json',
RUN_SCRIPT_EXEC: 'ls',
})
@@ -241,11 +227,9 @@ t.test('basic non-interactive', t => {
throw er
t.strictSame({
- ERROR_HANDLER_CALLED,
RPJ_CALLED,
RUN_SCRIPT_EXEC,
}, {
- ERROR_HANDLER_CALLED: null,
RPJ_CALLED: '/npm/dir/pkg/package.json',
RUN_SCRIPT_EXEC: 'ls',
})
@@ -310,7 +294,6 @@ t.test('signal fails non-interactive', t => {
t.test('usage if no pkg provided', t => {
t.teardown(() => {
output.length = 0
- ERROR_HANDLER_CALLED = null
})
const noPkg = [
[],
@@ -326,11 +309,9 @@ t.test('usage if no pkg provided', t => {
posixExplore.exec(args, er => {
t.match(er, 'Usage:')
t.strictSame({
- ERROR_HANDLER_CALLED: null,
RPJ_CALLED,
RUN_SCRIPT_EXEC,
}, {
- ERROR_HANDLER_CALLED: null,
RPJ_CALLED: '/npm/dir/pkg/package.json',
RUN_SCRIPT_EXEC: 'ls',
})
@@ -345,11 +326,9 @@ t.test('pkg not installed', t => {
posixExplore.exec(['pkg', 'ls'], er => {
t.strictSame({
- ERROR_HANDLER_CALLED,
RPJ_CALLED,
RUN_SCRIPT_EXEC,
}, {
- ERROR_HANDLER_CALLED: null,
RPJ_CALLED: '/npm/dir/pkg/package.json',
RUN_SCRIPT_EXEC: 'ls',
})
diff --git a/deps/npm/test/lib/fund.js b/deps/npm/test/lib/fund.js
index 65778fca50bd71..784989827edc16 100644
--- a/deps/npm/test/lib/fund.js
+++ b/deps/npm/test/lib/fund.js
@@ -1,5 +1,5 @@
const t = require('tap')
-const mockNpm = require('../fixtures/mock-npm')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
const version = '1.0.0'
const funding = {
diff --git a/deps/npm/test/lib/help-search.js b/deps/npm/test/lib/help-search.js
index 845b3873e3cf9d..2df862d4fc570d 100644
--- a/deps/npm/test/lib/help-search.js
+++ b/deps/npm/test/lib/help-search.js
@@ -1,6 +1,6 @@
const t = require('tap')
const { join } = require('path')
-const mockNpm = require('../fixtures/mock-npm')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
const ansicolors = require('ansicolors')
const OUTPUT = []
diff --git a/deps/npm/test/lib/init.js b/deps/npm/test/lib/init.js
index 44a2af5bcc02b8..1cefb1fc9c8fd7 100644
--- a/deps/npm/test/lib/init.js
+++ b/deps/npm/test/lib/init.js
@@ -1,7 +1,7 @@
+const t = require('tap')
const fs = require('fs')
const { resolve } = require('path')
-const t = require('tap')
-const mockNpm = require('../fixtures/mock-npm')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
const npmLog = {
disableProgress: () => null,
@@ -431,8 +431,10 @@ t.test('workspaces', t => {
const Init = t.mock('../../lib/init.js', {
...mocks,
- 'json-parse-even-better-errors': () => {
- throw new Error('ERR')
+ '@npmcli/package-json': {
+ async load () {
+ throw new Error('ERR')
+ },
},
})
const init = new Init(npm)
@@ -440,7 +442,7 @@ t.test('workspaces', t => {
init.execWorkspaces([], ['a'], err => {
t.match(
err,
- /Invalid package.json: Error: ERR/,
+ /ERR/,
'should exit with error'
)
t.end()
@@ -452,30 +454,16 @@ t.test('workspaces', t => {
// this avoids poluting test output with those logs
console.log = noop
- npm.localPrefix = t.testdir({
- 'package.json': JSON.stringify({
- name: 'top-level',
- }),
- })
+ npm.localPrefix = t.testdir({})
- const Init = t.mock('../../lib/init.js', {
- ...mocks,
- fs: {
- statSync () {
- return true
- },
- readFileSync () {
- throw new Error('ERR')
- },
- },
- })
+ const Init = require('../../lib/init.js')
const init = new Init(npm)
init.execWorkspaces([], ['a'], err => {
t.match(
err,
- /package.json not found/,
- 'should exit with error'
+ { code: 'ENOENT' },
+ 'should exit with missing package.json file error'
)
t.end()
})
diff --git a/deps/npm/test/lib/install.js b/deps/npm/test/lib/install.js
index b7929bddafdba3..6412b34c16f251 100644
--- a/deps/npm/test/lib/install.js
+++ b/deps/npm/test/lib/install.js
@@ -1,7 +1,7 @@
const t = require('tap')
const Install = require('../../lib/install.js')
-const mockNpm = require('../fixtures/mock-npm')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
t.test('should install using Arborist', (t) => {
const SCRIPTS = []
diff --git a/deps/npm/test/lib/link.js b/deps/npm/test/lib/link.js
index 64375cfc13c2c2..736d18cab99068 100644
--- a/deps/npm/test/lib/link.js
+++ b/deps/npm/test/lib/link.js
@@ -1,9 +1,9 @@
+const t = require('tap')
const { resolve } = require('path')
const fs = require('fs')
const Arborist = require('@npmcli/arborist')
-const t = require('tap')
-const mockNpm = require('../fixtures/mock-npm')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
const redactCwd = (path) => {
const normalizePath = p => p
diff --git a/deps/npm/test/lib/load-all-commands.js b/deps/npm/test/lib/load-all-commands.js
index b3b2012d23aa2e..e5f10099cf365c 100644
--- a/deps/npm/test/lib/load-all-commands.js
+++ b/deps/npm/test/lib/load-all-commands.js
@@ -3,17 +3,16 @@
// name, a description, and if it has completion it is a function. That it
// renders also ensures that any params we've defined in our commands work.
const t = require('tap')
-const npm = t.mock('../../lib/npm.js')
+const { real: mockNpm } = require('../fixtures/mock-npm.js')
const { cmdList } = require('../../lib/utils/cmd-list.js')
-let npmOutput = []
-npm.output = (msg) => {
- npmOutput = msg
-}
+const { npm, outputs } = mockNpm(t)
+
t.test('load each command', t => {
- t.plan(cmdList.length + 1)
+ t.plan(cmdList.length)
npm.load((er) => {
- t.notOk(er)
+ if (er)
+ throw er
npm.config.set('usage', true)
for (const cmd of cmdList.sort((a, b) => a.localeCompare(b, 'en'))) {
t.test(cmd, t => {
@@ -26,13 +25,14 @@ t.test('load each command', t => {
t.match(impl.usage, cmd, 'usage contains the command')
impl([], (err) => {
t.notOk(err)
- t.match(npmOutput, impl.usage, 'usage is what is output')
+ t.match(outputs[0][0], impl.usage, 'usage is what is output')
// This ties usage to a snapshot so we have to re-run snap if usage
// changes, which rebuilds the man pages
- t.matchSnapshot(npmOutput)
+ t.matchSnapshot(outputs[0][0])
t.end()
})
})
+ outputs.length = 0
}
})
})
diff --git a/deps/npm/test/lib/load-all.js b/deps/npm/test/lib/load-all.js
index 4a975d49a490e5..e6e407805346d5 100644
--- a/deps/npm/test/lib/load-all.js
+++ b/deps/npm/test/lib/load-all.js
@@ -22,10 +22,10 @@ else {
t.end()
})
- t.test('call the error handle so we dont freak out', t => {
- const errorHandler = require('../../lib/utils/error-handler.js')
- errorHandler.setNpm(npm)
- errorHandler()
+ t.test('call the exit handler so we dont freak out', t => {
+ const exitHandler = require('../../lib/utils/exit-handler.js')
+ exitHandler.setNpm(npm)
+ exitHandler()
t.end()
})
}
diff --git a/deps/npm/test/lib/logout.js b/deps/npm/test/lib/logout.js
index b130d439c88ca6..7cb5c2790d6216 100644
--- a/deps/npm/test/lib/logout.js
+++ b/deps/npm/test/lib/logout.js
@@ -1,5 +1,5 @@
-const mockNpm = require('../fixtures/mock-npm')
const t = require('tap')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
const config = {
registry: 'https://registry.npmjs.org/',
diff --git a/deps/npm/test/lib/ls.js b/deps/npm/test/lib/ls.js
index 64ece6bd8a3fd6..5f196501e55d1a 100644
--- a/deps/npm/test/lib/ls.js
+++ b/deps/npm/test/lib/ls.js
@@ -3,7 +3,7 @@
// of them contain the tap testdir folders, which are auto-generated and
// may change when node-tap is updated.
const t = require('tap')
-const mockNpm = require('../fixtures/mock-npm')
+const { fake: mockNpm } = require('../fixtures/mock-npm.js')
const { resolve } = require('path')
const { utimesSync } = require('fs')
@@ -123,7 +123,23 @@ const ls = new LS(npm)
const redactCwd = res =>
res && res.replace(/\\+/g, '/').replace(new RegExp(__dirname.replace(/\\+/g, '/'), 'gi'), '{CWD}')
-const jsonParse = res => JSON.parse(redactCwd(res))
+const redactCwdObj = obj => {
+ if (Array.isArray(obj))
+ return obj.map(o => redactCwdObj(o))
+ else if (typeof obj === 'string')
+ return redactCwd(obj)
+ else if (!obj)
+ return obj
+ else if (typeof obj === 'object') {
+ return Object.keys(obj).reduce((o, k) => {
+ o[k] = redactCwdObj(obj[k])
+ return o
+ }, {})
+ } else
+ return obj
+}
+
+const jsonParse = res => redactCwdObj(JSON.parse(res))
const cleanUpResult = () => result = ''
@@ -3060,7 +3076,7 @@ t.test('ls --json', (t) => {
dependencies: {
foo: {
version: '1.0.0',
- invalid: true,
+ invalid: '"^2.0.0" from the root project',
problems: [
'invalid: foo@1.0.0 {CWD}/tap-testdir-ls-ls---json-missing-invalid-extraneous/node_modules/foo',
],
@@ -3756,7 +3772,7 @@ t.test('ls --json', (t) => {
dependencies: {
'peer-dep': {
version: '1.0.0',
- invalid: true,
+ invalid: '"^2.0.0" from the root project',
problems: [
'invalid: peer-dep@1.0.0 {CWD}/tap-testdir-ls-ls---json-unmet-peer-dep/node_modules/peer-dep',
],
@@ -3817,7 +3833,7 @@ t.test('ls --json', (t) => {
dependencies: {
'optional-dep': {
version: '1.0.0',
- invalid: true,
+ invalid: '"^2.0.0" from the root project',
problems: [
'invalid: optional-dep@1.0.0 {CWD}/tap-testdir-ls-ls---json-unmet-optional-dep/node_modules/optional-dep',
],
@@ -4175,6 +4191,59 @@ t.test('ls --json', (t) => {
t.end()
})
+t.test('show multiple invalid reasons', (t) => {
+ config.json = false
+ config.all = true
+ config.depth = Infinity
+ npm.prefix = t.testdir({
+ 'package.json': JSON.stringify({
+ name: 'test-npm-ls',
+ version: '1.0.0',
+ dependencies: {
+ cat: '^2.0.0',
+ dog: '^1.2.3',
+ },
+ }),
+ node_modules: {
+ cat: {
+ 'package.json': JSON.stringify({
+ name: 'cat',
+ version: '1.0.0',
+ dependencies: {
+ dog: '^2.0.0',
+ },
+ }),
+ },
+ dog: {
+ 'package.json': JSON.stringify({
+ name: 'dog',
+ version: '1.0.0',
+ dependencies: {
+ cat: '',
+ },
+ }),
+ },
+ chai: {
+ 'package.json': JSON.stringify({
+ name: 'chai',
+ version: '1.0.0',
+ dependencies: {
+ dog: '2.x',
+ },
+ }),
+ },
+ },
+ })
+
+ const cleanupPaths = str =>
+ redactCwd(str).toLowerCase().replace(/\\/g, '/')
+ ls.exec([], (err) => {
+ t.match(err, { code: 'ELSPROBLEMS' }, 'should list dep problems')
+ t.matchSnapshot(cleanupPaths(result), 'ls result')
+ t.end()
+ })
+})
+
t.test('ls --package-lock-only', (t) => {
config['package-lock-only'] = true
t.test('ls --package-lock-only --json', (t) => {
@@ -4751,7 +4820,7 @@ t.test('ls --package-lock-only', (t) => {
dependencies: {
foo: {
version: '1.0.0',
- invalid: true,
+ invalid: '"^2.0.0" from the root project',
problems: [
'invalid: foo@1.0.0 {CWD}/tap-testdir-ls-ls---package-lock-only-ls---package-lock-only---json-missing-invalid-extraneous/node_modules/foo',
],
diff --git a/deps/npm/test/lib/npm.js b/deps/npm/test/lib/npm.js
index 6909c43e4ff0e0..291a58955ceedd 100644
--- a/deps/npm/test/lib/npm.js
+++ b/deps/npm/test/lib/npm.js
@@ -1,8 +1,12 @@
const t = require('tap')
+const npmlog = require('npmlog')
+const { real: mockNpm } = require('../fixtures/mock-npm.js')
+
// delete this so that we don't have configs from the fact that it
// is being run by 'npm test'
const event = process.env.npm_lifecycle_event
+
for (const env of Object.keys(process.env).filter(e => /^npm_/.test(e))) {
if (env === 'npm_command') {
// should only be running this in the 'test' or 'run-script' command!
@@ -23,52 +27,36 @@ for (const env of Object.keys(process.env).filter(e => /^npm_/.test(e))) {
const { resolve, dirname } = require('path')
const actualPlatform = process.platform
-
const beWindows = () => {
Object.defineProperty(process, 'platform', {
value: 'win32',
configurable: true,
})
}
-
const bePosix = () => {
Object.defineProperty(process, 'platform', {
value: 'posix',
configurable: true,
})
}
+const argv = [...process.argv]
-const npmlog = require('npmlog')
-
-const npmPath = resolve(__dirname, '..', '..')
-const Config = require('@npmcli/config')
-const { definitions, shorthands, flatten } = require('../../lib/utils/config')
-const freshConfig = (opts = {}) => {
+t.afterEach(() => {
for (const env of Object.keys(process.env).filter(e => /^npm_/.test(e)))
delete process.env[env]
-
process.env.npm_config_cache = CACHE
-
- npm.config = new Config({
- definitions,
- shorthands,
- npmPath,
- log: npmlog,
- ...opts,
- flatten,
+ process.argv = argv
+ Object.defineProperty(process, 'platform', {
+ value: actualPlatform,
+ configurable: true,
})
-}
-
-const logs = []
-for (const level of ['silly', 'verbose', 'timing', 'notice', 'warn', 'error'])
- npmlog[level] = (...msg) => logs.push([level, ...msg])
-
-const npm = require('../../lib/npm.js')
+})
const CACHE = t.testdir()
process.env.npm_config_cache = CACHE
t.test('not yet loaded', t => {
+ const { npm, logs } = mockNpm(t)
t.match(npm, {
started: Number,
command: null,
@@ -89,160 +77,125 @@ t.test('not yet loaded', t => {
t.equal(npm.commands.asdfasdf, undefined)
t.equal(npm.deref('list'), 'ls')
t.same(logs, [])
- logs.length = 0
t.end()
})
t.test('npm.load', t => {
- t.test('must be called with proper args', t => {
- const er = new TypeError('must call as: npm.load(callback)')
- t.throws(() => npm.load(), er)
+ t.test('callback must be a function', t => {
+ const { npm, logs } = mockNpm(t)
+ const er = new TypeError('callback must be a function if provided')
t.throws(() => npm.load({}), er)
t.same(logs, [])
- logs.length = 0
t.end()
})
- t.test('load error', t => {
- const { load } = npm.config
+ t.test('callback style', t => {
+ const { npm } = mockNpm(t)
+ npm.load((err) => {
+ if (err)
+ throw err
+ t.ok(npm.loaded)
+ t.end()
+ })
+ })
+
+ t.test('load error', async t => {
+ const { npm } = mockNpm(t)
const loadError = new Error('load error')
npm.config.load = async () => {
throw loadError
}
- npm.load(er => {
+ await npm.load().catch(er => {
t.equal(er, loadError)
t.equal(npm.loadErr, loadError)
- npm.config.load = load
- // loading again just returns the same error
- npm.load(er => {
- t.equal(er, loadError)
- t.equal(npm.loadErr, loadError)
- npm.loadErr = null
- t.end()
- })
+ })
+ npm.config.load = async () => {
+ throw new Error('new load error')
+ }
+ await npm.load().catch(er => {
+ t.equal(er, loadError, 'loading again returns the original error')
+ t.equal(npm.loadErr, loadError)
})
})
- t.test('basic loading', t => {
+ t.test('basic loading', async t => {
+ const { npm, logs } = mockNpm(t)
const dir = t.testdir({
node_modules: {},
})
- let firstCalled = false
- const first = (er) => {
- if (er)
- throw er
-
- firstCalled = true
- t.equal(npm.loaded, true)
- t.equal(npm.config.loaded, true)
- t.equal(npm.config.get('force'), false)
- }
-
- let secondCalled = false
- const second = () => {
- secondCalled = true
- }
-
- t.equal(npm.loading, false, 'not loading yet')
- const p = npm.load(first).then(() => {
- t.ok(npm.usage, 'has usage')
- npm.config.set('prefix', dir)
- t.match(npm, {
- loaded: true,
- loading: false,
- flatOptions: {},
- })
- t.equal(firstCalled, true, 'first callback got called')
- t.equal(secondCalled, true, 'second callback got called')
- let thirdCalled = false
- const third = () => {
- thirdCalled = true
- }
- npm.load(third)
- t.equal(thirdCalled, true, 'third callbback got called')
- t.match(logs, [
- ['timing', 'npm:load', /Completed in [0-9.]+ms/],
- ])
- logs.length = 0
-
- bePosix()
- t.equal(resolve(npm.cache), resolve(CACHE), 'cache is cache')
- const newCache = t.testdir()
- npm.cache = newCache
- t.equal(npm.config.get('cache'), newCache, 'cache setter sets config')
- t.equal(npm.cache, newCache, 'cache getter gets new config')
- t.equal(npm.log, npmlog, 'npmlog getter')
- t.equal(npm.lockfileVersion, 2, 'lockfileVersion getter')
- t.equal(npm.prefix, npm.localPrefix, 'prefix is local prefix')
- t.not(npm.prefix, npm.globalPrefix, 'prefix is not global prefix')
- npm.globalPrefix = npm.prefix
- t.equal(npm.prefix, npm.globalPrefix, 'globalPrefix setter')
- npm.localPrefix = dir + '/extra/prefix'
- t.equal(npm.prefix, npm.localPrefix, 'prefix is local prefix after localPrefix setter')
- t.not(npm.prefix, npm.globalPrefix, 'prefix is not global prefix after localPrefix setter')
-
- npm.prefix = dir + '/some/prefix'
- t.equal(npm.prefix, npm.localPrefix, 'prefix is local prefix after prefix setter')
- t.not(npm.prefix, npm.globalPrefix, 'prefix is not global prefix after prefix setter')
- t.equal(npm.bin, npm.localBin, 'bin is local bin after prefix setter')
- t.not(npm.bin, npm.globalBin, 'bin is not global bin after prefix setter')
- t.equal(npm.dir, npm.localDir, 'dir is local dir after prefix setter')
- t.not(npm.dir, npm.globalDir, 'dir is not global dir after prefix setter')
-
- npm.config.set('global', true)
- t.equal(npm.prefix, npm.globalPrefix, 'prefix is global prefix after setting global')
- t.not(npm.prefix, npm.localPrefix, 'prefix is not local prefix after setting global')
- t.equal(npm.bin, npm.globalBin, 'bin is global bin after setting global')
- t.not(npm.bin, npm.localBin, 'bin is not local bin after setting global')
- t.equal(npm.dir, npm.globalDir, 'dir is global dir after setting global')
- t.not(npm.dir, npm.localDir, 'dir is not local dir after setting global')
-
- npm.prefix = dir + '/new/global/prefix'
- t.equal(npm.prefix, npm.globalPrefix, 'prefix is global prefix after prefix setter')
- t.not(npm.prefix, npm.localPrefix, 'prefix is not local prefix after prefix setter')
- t.equal(npm.bin, npm.globalBin, 'bin is global bin after prefix setter')
- t.not(npm.bin, npm.localBin, 'bin is not local bin after prefix setter')
-
- 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')
- bePosix()
-
- const tmp = npm.tmp
- t.match(tmp, String, 'npm.tmp is a string')
- t.equal(tmp, npm.tmp, 'getter only generates it once')
+ await npm.load()
+ t.equal(npm.loaded, true)
+ t.equal(npm.config.loaded, true)
+ t.equal(npm.config.get('force'), false)
+ t.ok(npm.usage, 'has usage')
+ npm.config.set('prefix', dir)
+
+ t.match(npm, {
+ flatOptions: {},
})
-
- t.equal(npm.loaded, false, 'not loaded yet')
- t.equal(npm.loading, true, 'working on it tho')
- t.type(p, Promise, 'npm.load() returned a Promise first time')
- t.equal(npm.load(second), undefined,
- 'npm.load() returns nothing second time')
-
- return p
+ t.match(logs, [
+ ['timing', 'npm:load', /Completed in [0-9.]+ms/],
+ ])
+
+ bePosix()
+ t.equal(resolve(npm.cache), resolve(CACHE), 'cache is cache')
+ const newCache = t.testdir()
+ npm.cache = newCache
+ t.equal(npm.config.get('cache'), newCache, 'cache setter sets config')
+ t.equal(npm.cache, newCache, 'cache getter gets new config')
+ t.equal(npm.log, npmlog, 'npmlog getter')
+ t.equal(npm.lockfileVersion, 2, 'lockfileVersion getter')
+ t.equal(npm.prefix, npm.localPrefix, 'prefix is local prefix')
+ t.not(npm.prefix, npm.globalPrefix, 'prefix is not global prefix')
+ npm.globalPrefix = npm.prefix
+ t.equal(npm.prefix, npm.globalPrefix, 'globalPrefix setter')
+ npm.localPrefix = dir + '/extra/prefix'
+ t.equal(npm.prefix, npm.localPrefix, 'prefix is local prefix after localPrefix setter')
+ t.not(npm.prefix, npm.globalPrefix, 'prefix is not global prefix after localPrefix setter')
+
+ npm.prefix = dir + '/some/prefix'
+ t.equal(npm.prefix, npm.localPrefix, 'prefix is local prefix after prefix setter')
+ t.not(npm.prefix, npm.globalPrefix, 'prefix is not global prefix after prefix setter')
+ t.equal(npm.bin, npm.localBin, 'bin is local bin after prefix setter')
+ t.not(npm.bin, npm.globalBin, 'bin is not global bin after prefix setter')
+ t.equal(npm.dir, npm.localDir, 'dir is local dir after prefix setter')
+ t.not(npm.dir, npm.globalDir, 'dir is not global dir after prefix setter')
+
+ npm.config.set('global', true)
+ t.equal(npm.prefix, npm.globalPrefix, 'prefix is global prefix after setting global')
+ t.not(npm.prefix, npm.localPrefix, 'prefix is not local prefix after setting global')
+ t.equal(npm.bin, npm.globalBin, 'bin is global bin after setting global')
+ t.not(npm.bin, npm.localBin, 'bin is not local bin after setting global')
+ t.equal(npm.dir, npm.globalDir, 'dir is global dir after setting global')
+ t.not(npm.dir, npm.localDir, 'dir is not local dir after setting global')
+
+ npm.prefix = dir + '/new/global/prefix'
+ t.equal(npm.prefix, npm.globalPrefix, 'prefix is global prefix after prefix setter')
+ t.not(npm.prefix, npm.localPrefix, 'prefix is not local prefix after prefix setter')
+ t.equal(npm.bin, npm.globalBin, 'bin is global bin after prefix setter')
+ t.not(npm.bin, npm.localBin, 'bin is not local bin after prefix setter')
+
+ 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')
+ bePosix()
+
+ const tmp = npm.tmp
+ t.match(tmp, String, 'npm.tmp is a string')
+ t.equal(tmp, npm.tmp, 'getter only generates it once')
})
- t.test('forceful loading', t => {
- // also, don't get thrown off if argv[0] isn't found for some reason
- const [argv0] = process.argv
- t.teardown(() => {
- process.argv[0] = argv0
- })
- freshConfig({ argv: [...process.argv, '--force', '--color', 'always'] })
- process.argv[0] = 'this exe does not exist or else this test will fail'
- return npm.load(er => {
- if (er)
- throw er
-
- t.match(logs.filter(l => l[0] !== 'timing'), [
- [
- 'warn',
- 'using --force',
- 'Recommended protections disabled.',
- ],
- ])
- logs.length = 0
- })
+ t.test('forceful loading', async t => {
+ process.argv = [...process.argv, '--force', '--color', 'always']
+ const { npm, logs } = mockNpm(t)
+ await npm.load()
+ t.match(logs.filter(l => l[0] !== 'timing'), [
+ [
+ 'warn',
+ 'using --force',
+ 'Recommended protections disabled.',
+ ],
+ ])
})
t.test('node is a symlink', async t => {
@@ -254,7 +207,6 @@ t.test('npm.load', t => {
const PATH = process.env.PATH || process.env.Path
process.env.PATH = resolve(dir, 'bin')
- const { execPath, argv: processArgv } = process
process.argv = [
node,
process.argv[1],
@@ -267,48 +219,33 @@ t.test('npm.load', t => {
'blergggg',
]
- freshConfig()
- const { log } = console
- const consoleLogs = []
- console.log = (...msg) => consoleLogs.push(msg)
-
t.teardown(() => {
- console.log = log
process.env.PATH = PATH
- process.argv = processArgv
- freshConfig()
- logs.length = 0
- process.execPath = execPath
})
- logs.length = 0
-
- await npm.load(er => {
- if (er)
- throw er
-
- t.equal(npm.config.get('scope'), '@foo', 'added the @ sign to scope')
- t.match(logs.filter(l => l[0] !== 'timing' || !/^config:/.test(l[1])), [
- [
- 'timing',
- 'npm:load:whichnode',
- /Completed in [0-9.]+ms/,
- ],
- [
- 'verbose',
- 'node symlink',
- resolve(dir, 'bin', node),
- ],
- [
- 'timing',
- 'npm:load',
- /Completed in [0-9.]+ms/,
- ],
- ])
- logs.length = 0
- t.equal(process.execPath, resolve(dir, 'bin', node))
- })
+ const { npm, logs, outputs } = mockNpm(t)
+ await npm.load()
+ t.equal(npm.config.get('scope'), '@foo', 'added the @ sign to scope')
+ t.match(logs.filter(l => l[0] !== 'timing' || !/^config:/.test(l[1])), [
+ [
+ 'timing',
+ 'npm:load:whichnode',
+ /Completed in [0-9.]+ms/,
+ ],
+ [
+ 'verbose',
+ 'node symlink',
+ resolve(dir, 'bin', node),
+ ],
+ [
+ 'timing',
+ 'npm:load',
+ /Completed in [0-9.]+ms/,
+ ],
+ ])
+ t.equal(process.execPath, resolve(dir, 'bin', node))
+ outputs.length = 0
await npm.commands.ll([], (er) => {
if (er)
throw er
@@ -316,13 +253,13 @@ t.test('npm.load', t => {
t.equal(npm.command, 'll', 'command set to first npm command')
t.equal(npm.flatOptions.npmCommand, 'll', 'npmCommand flatOption set')
- t.same(consoleLogs, [[npm.commands.ll.usage]], 'print usage')
- consoleLogs.length = 0
+ t.same(outputs, [[npm.commands.ll.usage]], 'print usage')
npm.config.set('usage', false)
t.equal(npm.commands.ll, npm.commands.ll, 'same command, different name')
- logs.length = 0
})
+ outputs.length = 0
+ logs.length = 0
await npm.commands.get(['scope', '\u2010not-a-dash'], (er) => {
if (er)
throw er
@@ -348,7 +285,7 @@ t.test('npm.load', t => {
/Completed in [0-9.]+ms/,
],
])
- t.same(consoleLogs, [['scope=@foo\n\u2010not-a-dash=undefined']])
+ t.same(outputs, [['scope=@foo\n\u2010not-a-dash=undefined']])
})
// need this here or node 10 will improperly end the promise ahead of time
@@ -381,33 +318,19 @@ t.test('npm.load', t => {
'.npmrc': '',
})
- const { log } = console
- const consoleLogs = []
- console.log = (...msg) => consoleLogs.push(msg)
-
- const { execPath } = process
- t.teardown(() => {
- console.log = log
- })
-
- freshConfig({
- argv: [
- execPath,
- process.argv[1],
- '--userconfig',
- resolve(dir, '.npmrc'),
- '--color',
- 'false',
- '--workspaces',
- 'true',
- ],
- })
-
- await npm.load(er => {
- if (er)
- throw er
- })
+ process.argv = [
+ process.execPath,
+ process.argv[1],
+ '--userconfig',
+ resolve(dir, '.npmrc'),
+ '--color',
+ 'false',
+ '--workspaces',
+ 'true',
+ ]
+ const { npm, outputs } = mockNpm(t)
+ await npm.load()
npm.localPrefix = dir
await new Promise((res, rej) => {
@@ -421,7 +344,7 @@ t.test('npm.load', t => {
t.equal(npm.command, 'run-script', 'npm.command set to canonical name')
t.match(
- consoleLogs,
+ outputs,
[
['Lifecycle scripts included in a@1.0.0:'],
[' test\n echo test a'],
@@ -462,24 +385,19 @@ t.test('npm.load', t => {
workspaces: ['./packages/*'],
}),
})
- const { execPath } = process
- freshConfig({
- argv: [
- execPath,
- process.argv[1],
- '--userconfig',
- resolve(dir, '.npmrc'),
- '--color',
- 'false',
- '--workspaces',
- '--global',
- 'true',
- ],
- })
- await npm.load(er => {
- if (er)
- throw er
- })
+ process.argv = [
+ process.execPath,
+ process.argv[1],
+ '--userconfig',
+ resolve(dir, '.npmrc'),
+ '--color',
+ 'false',
+ '--workspaces',
+ '--global',
+ 'true',
+ ]
+ const { npm } = mockNpm(t)
+ await npm.load()
npm.localPrefix = dir
await new Promise((res, rej) => {
// verify that calling the command with a short name still sets
@@ -491,7 +409,6 @@ t.test('npm.load', t => {
})
})
})
-
t.end()
})
@@ -512,82 +429,49 @@ t.test('loading as main will load the cli', t => {
})
t.test('set process.title', t => {
- const { argv: processArgv } = process
- const { log } = console
- const titleDesc = Object.getOwnPropertyDescriptor(process, 'title')
- Object.defineProperty(process, 'title', {
- value: '',
- settable: true,
- enumerable: true,
- configurable: true,
- })
- const consoleLogs = []
- console.log = (...msg) => consoleLogs.push(msg)
-
- t.teardown(() => {
- console.log = log
- process.argv = processArgv
- Object.defineProperty(process, 'title', titleDesc)
- freshConfig()
- })
-
- t.afterEach(() => consoleLogs.length = 0)
-
t.test('basic title setting', async t => {
- freshConfig({
- argv: [
- process.execPath,
- process.argv[1],
- '--usage',
- '--scope=foo',
- 'ls',
- ],
- })
- await npm.load(er => {
- if (er)
- throw er
- t.equal(npm.title, 'npm ls')
- t.equal(process.title, 'npm ls')
- })
+ process.argv = [
+ process.execPath,
+ process.argv[1],
+ '--usage',
+ '--scope=foo',
+ 'ls',
+ ]
+ const { npm } = mockNpm(t)
+ await npm.load()
+ t.equal(npm.title, 'npm ls')
+ t.equal(process.title, 'npm ls')
})
t.test('do not expose token being revoked', async t => {
- freshConfig({
- argv: [
- process.execPath,
- process.argv[1],
- '--usage',
- '--scope=foo',
- 'token',
- 'revoke',
- 'deadbeefcafebad',
- ],
- })
- await npm.load(er => {
- if (er)
- throw er
- t.equal(npm.title, 'npm token revoke ***')
- t.equal(process.title, 'npm token revoke ***')
- })
+ process.argv = [
+ process.execPath,
+ process.argv[1],
+ '--usage',
+ '--scope=foo',
+ 'token',
+ 'revoke',
+ 'deadbeefcafebad',
+ ]
+ const { npm } = mockNpm(t)
+ await npm.load()
+ t.equal(npm.title, 'npm token revoke ***')
+ t.equal(process.title, 'npm token revoke ***')
})
t.test('do show *** unless a token is actually being revoked', async t => {
- freshConfig({
- argv: [
- process.execPath,
- process.argv[1],
- '--usage',
- '--scope=foo',
- 'token',
- 'revoke',
- ],
- })
- await npm.load(er => {
- if (er)
- throw er
- t.equal(npm.title, 'npm token revoke')
- t.equal(process.title, 'npm token revoke')
- })
+ process.argv = [
+ process.execPath,
+ process.argv[1],
+ '--usage',
+ '--scope=foo',
+ 'token',
+ 'revoke',
+ ]
+ const { npm } = mockNpm(t)
+ await npm.load()
+ t.equal(npm.title, 'npm token revoke')
+ t.equal(process.title, 'npm token revoke')
})
t.end()
diff --git a/deps/npm/test/lib/outdated.js b/deps/npm/test/lib/outdated.js
index 462ec0fc62b6ca..34a0aa6c9e03e8 100644
--- a/deps/npm/test/lib/outdated.js
+++ b/deps/npm/test/lib/outdated.js
@@ -1,5 +1,5 @@
const t = require('tap')
-const mockNpm = require('../fixtures/mock-npm')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
const packument = spec => {
const mocks = {
diff --git a/deps/npm/test/lib/owner.js b/deps/npm/test/lib/owner.js
index 10ceb03030a5ac..32944a84edbc40 100644
--- a/deps/npm/test/lib/owner.js
+++ b/deps/npm/test/lib/owner.js
@@ -1,5 +1,5 @@
const t = require('tap')
-const mockNpm = require('../fixtures/mock-npm.js')
+const { fake: mockNpm } = require('../fixtures/mock-npm.js')
let result = ''
let readPackageNamePrefix = null
diff --git a/deps/npm/test/lib/pack.js b/deps/npm/test/lib/pack.js
index 523ba5d6b535d7..3d61abdaf74ca5 100644
--- a/deps/npm/test/lib/pack.js
+++ b/deps/npm/test/lib/pack.js
@@ -1,5 +1,5 @@
const t = require('tap')
-const mockNpm = require('../fixtures/mock-npm')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
const pacote = require('pacote')
const path = require('path')
diff --git a/deps/npm/test/lib/ping.js b/deps/npm/test/lib/ping.js
index c2d53efef5a7e4..f0a10718c46d02 100644
--- a/deps/npm/test/lib/ping.js
+++ b/deps/npm/test/lib/ping.js
@@ -1,5 +1,5 @@
const t = require('tap')
-const mockNpm = require('../fixtures/mock-npm')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
t.test('pings', (t) => {
t.plan(8)
diff --git a/deps/npm/test/lib/profile.js b/deps/npm/test/lib/profile.js
index 17bcf99b9b6539..112aa5c3b75e19 100644
--- a/deps/npm/test/lib/profile.js
+++ b/deps/npm/test/lib/profile.js
@@ -1,5 +1,5 @@
const t = require('tap')
-const mockNpm = require('../fixtures/mock-npm')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
let result = ''
const config = {
diff --git a/deps/npm/test/lib/publish.js b/deps/npm/test/lib/publish.js
index e34f00b477ee13..56590478fc1ae4 100644
--- a/deps/npm/test/lib/publish.js
+++ b/deps/npm/test/lib/publish.js
@@ -1,5 +1,5 @@
const t = require('tap')
-const mockNpm = require('../fixtures/mock-npm')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
const fs = require('fs')
// The way we set loglevel is kind of convoluted, and there is no way to affect
diff --git a/deps/npm/test/lib/rebuild.js b/deps/npm/test/lib/rebuild.js
index e686b6a32ce53a..81768a21fb3b7a 100644
--- a/deps/npm/test/lib/rebuild.js
+++ b/deps/npm/test/lib/rebuild.js
@@ -1,7 +1,7 @@
+const t = require('tap')
const fs = require('fs')
const { resolve } = require('path')
-const mockNpm = require('../fixtures/mock-npm')
-const t = require('tap')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
let result = ''
diff --git a/deps/npm/test/lib/repo.js b/deps/npm/test/lib/repo.js
index 0701750b58c63c..e1ac90b1e7577b 100644
--- a/deps/npm/test/lib/repo.js
+++ b/deps/npm/test/lib/repo.js
@@ -1,5 +1,5 @@
const t = require('tap')
-const mockNpm = require('../fixtures/mock-npm.js')
+const { fake: mockNpm } = require('../fixtures/mock-npm.js')
const { join, sep } = require('path')
const pkgDirs = t.testdir({
diff --git a/deps/npm/test/lib/run-script.js b/deps/npm/test/lib/run-script.js
index 897c80817e2549..a3f04ea6790fa4 100644
--- a/deps/npm/test/lib/run-script.js
+++ b/deps/npm/test/lib/run-script.js
@@ -1,6 +1,6 @@
-const { resolve } = require('path')
const t = require('tap')
-const mockNpm = require('../fixtures/mock-npm')
+const { resolve } = require('path')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
const normalizePath = p => p
.replace(/\\+/g, '/')
diff --git a/deps/npm/test/lib/search.js b/deps/npm/test/lib/search.js
index ac894a9e3369da..510a470f48088e 100644
--- a/deps/npm/test/lib/search.js
+++ b/deps/npm/test/lib/search.js
@@ -1,6 +1,6 @@
-const Minipass = require('minipass')
const t = require('tap')
-const mockNpm = require('../fixtures/mock-npm')
+const Minipass = require('minipass')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
const libnpmsearchResultFixture =
require('../fixtures/libnpmsearch-stream-result.js')
diff --git a/deps/npm/test/lib/set-script.js b/deps/npm/test/lib/set-script.js
index 96b455785c5095..37ba9a1cc71a20 100644
--- a/deps/npm/test/lib/set-script.js
+++ b/deps/npm/test/lib/set-script.js
@@ -1,7 +1,7 @@
const t = require('tap')
const fs = require('fs')
const parseJSON = require('json-parse-even-better-errors')
-const mockNpm = require('../fixtures/mock-npm.js')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
const { resolve } = require('path')
const flatOptions = {}
@@ -121,25 +121,6 @@ t.test('warns when overwriting', (t) => {
})
})
-t.test('provided indentation and eol is used', (t) => {
- npm.localPrefix = t.testdir({
- 'package.json': JSON.stringify({
- name: 'foo',
- }, null, ' '.repeat(6)).replace(/\n/g, '\r\n'),
- })
-
- t.plan(3)
- setScript.exec(['arg1', 'arg2'], (error) => {
- t.equal(error, undefined)
- // rather than checking every line's content
- // we parse the result and verify the symbols match
- const contents = fs.readFileSync(resolve(npm.localPrefix, 'package.json'))
- const data = parseJSON(contents)
- t.equal(data[Symbol.for('indent')], ' '.repeat(6), 'keeps indenting')
- t.equal(data[Symbol.for('newline')], '\r\n', 'keeps newlines')
- })
-})
-
t.test('workspaces', (t) => {
ERROR_OUTPUT.length = 0
WARN_OUTPUT.length = 0
@@ -153,7 +134,7 @@ t.test('workspaces', (t) => {
'package.json': '{}',
},
'workspace-b': {
- 'package.json': '"notjson"',
+ 'package.json': '"notajsonobject"',
},
'workspace-c': {
'package.json': JSON.stringify({
@@ -176,8 +157,8 @@ t.test('workspaces', (t) => {
t.hasStrict(dataA, { scripts: { arg1: 'arg2' } }, 'defined the script')
// workspace-b logged an error
- t.match(ERROR_OUTPUT, [
- ['set-script', `Cannot create property 'scripts' on string 'notjson'`],
+ t.strictSame(ERROR_OUTPUT, [
+ ['set-script', `Can't update invalid package.json data`],
[' in workspace: workspace-b'],
[` at location: ${resolve(npm.localPrefix, 'workspace-b')}`],
], 'logged workspace-b error')
diff --git a/deps/npm/test/lib/shrinkwrap.js b/deps/npm/test/lib/shrinkwrap.js
index 8bd18f7fbd7c64..ab3b8d0ffe447e 100644
--- a/deps/npm/test/lib/shrinkwrap.js
+++ b/deps/npm/test/lib/shrinkwrap.js
@@ -1,6 +1,6 @@
const t = require('tap')
const fs = require('fs')
-const mockNpm = require('../fixtures/mock-npm')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
const config = {
global: false,
diff --git a/deps/npm/test/lib/star.js b/deps/npm/test/lib/star.js
index 0c584e4a3f0cf8..8820d6e9cfb0b1 100644
--- a/deps/npm/test/lib/star.js
+++ b/deps/npm/test/lib/star.js
@@ -1,5 +1,5 @@
-const mockNpm = require('../fixtures/mock-npm')
const t = require('tap')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
let result = ''
diff --git a/deps/npm/test/lib/uninstall.js b/deps/npm/test/lib/uninstall.js
index 8cf35bd428d3b7..272adb86836028 100644
--- a/deps/npm/test/lib/uninstall.js
+++ b/deps/npm/test/lib/uninstall.js
@@ -1,7 +1,7 @@
+const t = require('tap')
const fs = require('fs')
const { resolve } = require('path')
-const t = require('tap')
-const mockNpm = require('../fixtures/mock-npm')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
const npm = mockNpm({
globalDir: '',
diff --git a/deps/npm/test/lib/unpublish.js b/deps/npm/test/lib/unpublish.js
index 6ad45e958c22f7..9199b8aed94420 100644
--- a/deps/npm/test/lib/unpublish.js
+++ b/deps/npm/test/lib/unpublish.js
@@ -1,5 +1,5 @@
const t = require('tap')
-const mockNpm = require('../fixtures/mock-npm')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
let result = ''
const noop = () => null
diff --git a/deps/npm/test/lib/update.js b/deps/npm/test/lib/update.js
index 411d07592a155b..487b12e5fa2970 100644
--- a/deps/npm/test/lib/update.js
+++ b/deps/npm/test/lib/update.js
@@ -1,6 +1,6 @@
-const { resolve } = require('path')
const t = require('tap')
-const mockNpm = require('../fixtures/mock-npm')
+const { resolve } = require('path')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
const config = {
depth: 0,
diff --git a/deps/npm/test/lib/utils/config/definitions.js b/deps/npm/test/lib/utils/config/definitions.js
index a87698c1813594..8724f0e3bd3ebd 100644
--- a/deps/npm/test/lib/utils/config/definitions.js
+++ b/deps/npm/test/lib/utils/config/definitions.js
@@ -17,6 +17,11 @@ const defpath = '../../../../lib/utils/config/definitions.js'
delete process.env.NODE_ENV
const definitions = require(defpath)
+// Tie the definitions to a snapshot so that if they change we are forced to
+// update snapshots, which rebuilds the docs
+for (const key of Object.keys(definitions))
+ t.matchSnapshot(definitions[key].describe(), `config description for ${key}`)
+
const isWin = '../../../../lib/utils/is-windows.js'
// snapshot these just so we note when they change
diff --git a/deps/npm/test/lib/utils/error-handler.js b/deps/npm/test/lib/utils/exit-handler.js
similarity index 86%
rename from deps/npm/test/lib/utils/error-handler.js
rename to deps/npm/test/lib/utils/exit-handler.js
index 9a681e52ce5db0..72f94bfded7b04 100644
--- a/deps/npm/test/lib/utils/error-handler.js
+++ b/deps/npm/test/lib/utils/exit-handler.js
@@ -121,8 +121,8 @@ const mocks = {
}),
}
-let errorHandler = t.mock('../../../lib/utils/error-handler.js', mocks)
-errorHandler.setNpm(npm)
+let exitHandler = t.mock('../../../lib/utils/exit-handler.js', mocks)
+exitHandler.setNpm(npm)
t.test('default exit code', (t) => {
t.plan(1)
@@ -165,7 +165,7 @@ t.test('handles unknown error', (t) => {
writeFileAtomic.sync = (filename, content) => {
t.equal(
redactCwd(filename),
- '{CWD}/test/lib/utils/tap-testdir-error-handler/_logs/expecteddate-debug.log',
+ '{CWD}/test/lib/utils/tap-testdir-exit-handler/_logs/expecteddate-debug.log',
'should use expected log filename'
)
t.matchSnapshot(
@@ -174,7 +174,7 @@ t.test('handles unknown error', (t) => {
)
}
- errorHandler(err)
+ exitHandler(err)
t.teardown(() => {
writeFileAtomic.sync = sync
@@ -197,7 +197,7 @@ t.test('npm.config not ready', (t) => {
)
}
- errorHandler()
+ exitHandler()
t.teardown(() => {
console.error = _error
@@ -219,7 +219,7 @@ t.test('fail to write logfile', (t) => {
})
t.doesNotThrow(
- () => errorHandler(err),
+ () => exitHandler(err),
'should not throw on cache write failure'
)
})
@@ -244,7 +244,7 @@ t.test('console.log output using --json', (t) => {
)
}
- errorHandler(new Error('Error: EBADTHING Something happened'))
+ exitHandler(new Error('Error: EBADTHING Something happened'))
t.teardown(() => {
console.error = _error
@@ -271,7 +271,7 @@ t.test('throw a non-error obj', (t) => {
t.equal(code, 1, 'should exit with code 1')
}
- errorHandler(weirdError)
+ exitHandler(weirdError)
t.teardown(() => {
process.exit = _exit
@@ -295,7 +295,7 @@ t.test('throw a string error', (t) => {
t.equal(code, 1, 'should exit with code 1')
}
- errorHandler(error)
+ exitHandler(error)
t.teardown(() => {
process.exit = _exit
@@ -315,7 +315,7 @@ t.test('update notification', (t) => {
t.equal(msg, updateMsg, 'should show update message')
}
- errorHandler(err)
+ exitHandler(err)
t.teardown(() => {
npmlog.notice = _notice
@@ -355,7 +355,7 @@ t.test('it worked', (t) => {
const _exit = process.exit
process.exit = (code) => {
process.exit = _exit
- t.equal(code, 0, 'should exit with code 0')
+ t.notOk(code, 'should exit with no code')
const _info = npmlog.info
npmlog.info = (msg) => {
@@ -371,14 +371,14 @@ t.test('it worked', (t) => {
config.values.timing = true
})
- errorHandler.exit(0)
+ exitHandler()
})
t.test('uses code from errno', (t) => {
t.plan(1)
- errorHandler = t.mock('../../../lib/utils/error-handler.js', mocks)
- errorHandler.setNpm(npm)
+ exitHandler = t.mock('../../../lib/utils/exit-handler.js', mocks)
+ exitHandler.setNpm(npm)
npmlog.level = 'silent'
const _exit = process.exit
@@ -386,7 +386,7 @@ t.test('uses code from errno', (t) => {
t.equal(code, 127, 'should use set errno')
}
- errorHandler(Object.assign(
+ exitHandler(Object.assign(
new Error('Error with errno'),
{
errno: 127,
@@ -402,8 +402,8 @@ t.test('uses code from errno', (t) => {
t.test('uses exitCode as code if using a number', (t) => {
t.plan(1)
- errorHandler = t.mock('../../../lib/utils/error-handler.js', mocks)
- errorHandler.setNpm(npm)
+ exitHandler = t.mock('../../../lib/utils/exit-handler.js', mocks)
+ exitHandler.setNpm(npm)
npmlog.level = 'silent'
const _exit = process.exit
@@ -411,7 +411,7 @@ t.test('uses exitCode as code if using a number', (t) => {
t.equal(code, 404, 'should use code if a number')
}
- errorHandler(Object.assign(
+ exitHandler(Object.assign(
new Error('Error with code type number'),
{
code: 404,
@@ -424,25 +424,25 @@ t.test('uses exitCode as code if using a number', (t) => {
})
})
-t.test('call errorHandler with no error', (t) => {
+t.test('call exitHandler with no error', (t) => {
t.plan(1)
- errorHandler = t.mock('../../../lib/utils/error-handler.js', mocks)
- errorHandler.setNpm(npm)
+ exitHandler = t.mock('../../../lib/utils/exit-handler.js', mocks)
+ exitHandler.setNpm(npm)
const _exit = process.exit
process.exit = (code) => {
- t.equal(code, 0, 'should exit with code 0')
+ t.equal(code, undefined, 'should exit with code undefined')
}
t.teardown(() => {
process.exit = _exit
})
- errorHandler()
+ exitHandler()
})
-t.test('callback called twice', (t) => {
+t.test('exit handler called twice', (t) => {
t.plan(2)
const _verbose = npmlog.verbose
@@ -450,13 +450,13 @@ t.test('callback called twice', (t) => {
t.equal(key, 'stack', 'should log stack in verbose level')
t.match(
value,
- /Error: Callback called more than once./,
+ /Error: Exit handler called more than once./,
'should have expected error msg'
)
npmlog.verbose = _verbose
}
- errorHandler()
+ exitHandler()
})
t.test('defaults to log error msg if stack is missing', (t) => {
@@ -480,35 +480,17 @@ t.test('defaults to log error msg if stack is missing', (t) => {
t.equal(msg, 'Error with no stack', 'should use error msg')
}
- errorHandler(noStackErr)
+ exitHandler(noStackErr)
})
-t.test('set it worked', (t) => {
- t.plan(1)
-
- errorHandler = t.mock('../../../lib/utils/error-handler.js', mocks)
- errorHandler.setNpm(npm)
-
- const _exit = process.exit
- process.exit = () => {
- t.ok('ok')
- }
-
- t.teardown(() => {
- process.exit = _exit
- })
-
- errorHandler.exit(0, true)
-})
-
-t.test('use exitCode when emitting exit event', (t) => {
+t.test('exits cleanly when emitting exit event', (t) => {
t.plan(1)
npmlog.level = 'silent'
const _exit = process.exit
process.exit = (code) => {
process.exit = _exit
- t.equal(code, 1, 'should exit with code 1')
+ t.same(code, null, 'should exit with code null')
}
t.teardown(() => {
@@ -549,7 +531,7 @@ t.test('do no fancy handling for shellouts', t => {
t.test('shellout with a numeric error code', t => {
EXPECT_EXIT = 5
- errorHandler(Object.assign(new Error(), { code: 5 }))
+ exitHandler(Object.assign(new Error(), { code: 5 }))
t.equal(EXPECT_EXIT, 0, 'called process.exit')
// should log no warnings or errors, verbose/silly is fine.
t.strictSame(loudNoises(), [], 'no noisy warnings')
@@ -558,7 +540,7 @@ t.test('do no fancy handling for shellouts', t => {
t.test('shellout without a numeric error code (something in npm)', t => {
EXPECT_EXIT = 1
- errorHandler(Object.assign(new Error(), { code: 'banana stand' }))
+ exitHandler(Object.assign(new Error(), { code: 'banana stand' }))
t.equal(EXPECT_EXIT, 0, 'called process.exit')
// should log some warnings and errors, because something weird happened
t.strictNotSame(loudNoises(), [], 'bring the noise')
@@ -567,7 +549,7 @@ t.test('do no fancy handling for shellouts', t => {
t.test('shellout with code=0 (extra weird?)', t => {
EXPECT_EXIT = 1
- errorHandler(Object.assign(new Error(), { code: 0 }))
+ exitHandler(Object.assign(new Error(), { code: 0 }))
t.equal(EXPECT_EXIT, 0, 'called process.exit')
// should log some warnings and errors, because something weird happened
t.strictNotSame(loudNoises(), [], 'bring the noise')
diff --git a/deps/npm/test/lib/utils/read-package-name.js b/deps/npm/test/lib/utils/read-package-name.js
index c8f88bacd4b840..a1a1b4a1504dce 100644
--- a/deps/npm/test/lib/utils/read-package-name.js
+++ b/deps/npm/test/lib/utils/read-package-name.js
@@ -1,17 +1,15 @@
const t = require('tap')
-const mockNpm = require('../../fixtures/mock-npm')
-const npm = mockNpm()
const readPackageName = require('../../../lib/utils/read-package-name.js')
t.test('read local package.json', async (t) => {
- npm.prefix = t.testdir({
+ const prefix = t.testdir({
'package.json': JSON.stringify({
name: 'my-local-package',
version: '1.0.0',
}),
})
- const packageName = await readPackageName(npm.prefix)
+ const packageName = await readPackageName(prefix)
t.equal(
packageName,
'my-local-package',
@@ -20,13 +18,13 @@ t.test('read local package.json', async (t) => {
})
t.test('read local scoped-package.json', async (t) => {
- npm.prefix = t.testdir({
+ const prefix = t.testdir({
'package.json': JSON.stringify({
name: '@my-scope/my-local-package',
version: '1.0.0',
}),
})
- const packageName = await readPackageName(npm.prefix)
+ const packageName = await readPackageName(prefix)
t.equal(
packageName,
'@my-scope/my-local-package',
diff --git a/deps/npm/test/lib/version.js b/deps/npm/test/lib/version.js
index 6a83375b0025c9..df6d0dd797d0a5 100644
--- a/deps/npm/test/lib/version.js
+++ b/deps/npm/test/lib/version.js
@@ -1,5 +1,5 @@
const t = require('tap')
-const mockNpm = require('../fixtures/mock-npm')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
let result = []
diff --git a/deps/npm/test/lib/view.js b/deps/npm/test/lib/view.js
index 4544d7d5d1a94a..5f2e5a8add5e9d 100644
--- a/deps/npm/test/lib/view.js
+++ b/deps/npm/test/lib/view.js
@@ -3,7 +3,7 @@ const t = require('tap')
// run the same as tap does when running directly with node
process.stdout.columns = undefined
-const mockNpm = require('../fixtures/mock-npm')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
let logs
const cleanLogs = () => {
diff --git a/deps/npm/test/lib/whoami.js b/deps/npm/test/lib/whoami.js
index 5e350a32ebfb4c..9190e3858b137a 100644
--- a/deps/npm/test/lib/whoami.js
+++ b/deps/npm/test/lib/whoami.js
@@ -1,5 +1,5 @@
const t = require('tap')
-const mockNpm = require('../fixtures/mock-npm')
+const { fake: mockNpm } = require('../fixtures/mock-npm')
t.test('whoami', (t) => {
t.plan(3)