aboutsummaryrefslogtreecommitdiff
path: root/deps
diff options
context:
space:
mode:
authorMyles Borins <mylesborins@github.com>2020-12-16 14:12:26 -0500
committerNode.js GitHub Bot <github-bot@iojs.org>2020-12-17 01:05:51 +0000
commitd0b1b135b2b0197d93f4fb12649e0970ab68eeb0 (patch)
tree42b54c0e93b6483dc990e7e25c3e81be674dc148 /deps
parent0e96dc1f95be48a70de0beaef20b56cbb510365c (diff)
downloadios-node-v8-d0b1b135b2b0197d93f4fb12649e0970ab68eeb0.tar.gz
ios-node-v8-d0b1b135b2b0197d93f4fb12649e0970ab68eeb0.tar.bz2
ios-node-v8-d0b1b135b2b0197d93f4fb12649e0970ab68eeb0.zip
deps: upgrade npm to 7.2.0
PR-URL: https://github.com/nodejs/node/pull/36543 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Ruy Adorno <ruyadorno@github.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Diffstat (limited to 'deps')
-rw-r--r--deps/npm/CHANGELOG.md59
-rw-r--r--deps/npm/docs/output/commands/npm-ls.html2
-rw-r--r--deps/npm/docs/output/commands/npm.html2
-rw-r--r--deps/npm/lib/config.js15
-rw-r--r--deps/npm/lib/edit.js72
-rw-r--r--deps/npm/lib/help-search.js27
-rw-r--r--deps/npm/lib/help.js7
-rw-r--r--deps/npm/lib/org.js4
-rw-r--r--deps/npm/lib/rebuild.js13
-rw-r--r--deps/npm/lib/utils/child-path.js9
-rw-r--r--deps/npm/lib/utils/completion/file-completion.js23
-rw-r--r--deps/npm/lib/utils/deep-sort-object.js14
-rw-r--r--deps/npm/lib/utils/git.js55
-rw-r--r--deps/npm/lib/utils/module-name.js38
-rw-r--r--deps/npm/lib/utils/split-package-names.js23
-rw-r--r--deps/npm/man/man1/npm-ls.12
-rw-r--r--deps/npm/man/man1/npm.12
-rw-r--r--deps/npm/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js8
-rw-r--r--deps/npm/node_modules/@npmcli/arborist/package.json2
-rw-r--r--deps/npm/node_modules/@npmcli/config/package.json4
-rw-r--r--deps/npm/node_modules/editor/LICENSE21
-rw-r--r--deps/npm/node_modules/editor/README.markdown54
-rw-r--r--deps/npm/node_modules/editor/example/beep.json5
-rw-r--r--deps/npm/node_modules/editor/example/edit.js4
-rw-r--r--deps/npm/node_modules/editor/index.js20
-rw-r--r--deps/npm/node_modules/editor/package.json34
-rw-r--r--deps/npm/node_modules/ini/ini.js178
-rw-r--r--deps/npm/node_modules/ini/package.json7
-rw-r--r--deps/npm/node_modules/sorted-object/LICENSE.txt47
-rw-r--r--deps/npm/node_modules/sorted-object/lib/sorted-object.js11
-rw-r--r--deps/npm/node_modules/sorted-object/package.json25
-rw-r--r--deps/npm/package.json14
-rw-r--r--deps/npm/test/lib/config.js44
-rw-r--r--deps/npm/test/lib/edit.js123
-rw-r--r--deps/npm/test/lib/help-search.js181
-rw-r--r--deps/npm/test/lib/help.js362
-rw-r--r--deps/npm/test/lib/hook.js589
-rw-r--r--deps/npm/test/lib/org.js585
-rw-r--r--deps/npm/test/lib/rebuild.js44
-rw-r--r--deps/npm/test/lib/set.js33
-rw-r--r--deps/npm/test/lib/utils/split-package-names.js17
41 files changed, 2217 insertions, 562 deletions
diff --git a/deps/npm/CHANGELOG.md b/deps/npm/CHANGELOG.md
index 0922176c6b..923c565ab3 100644
--- a/deps/npm/CHANGELOG.md
+++ b/deps/npm/CHANGELOG.md
@@ -1,3 +1,62 @@
+## 7.2.0 (2020-12-15)
+
+### FEATURES
+
+* [`a9c4b158c`](https://github.com/npm/cli/commit/a9c4b158c46dd0d0c8d8744a97750ffd0c30cc09)
+ [#2342](https://github.com/npm/cli/issues/2342)
+ allow npm rebuild to accept a path to a module
+ ([@nlf](https://github.com/nlf))
+
+### DEPENDENCIES
+
+* [`beb371800`](https://github.com/npm/cli/commit/beb371800292140bf3882253c447168a378bc154)
+ [#2334](https://github.com/npm/cli/issues/2334)
+ remove unused top level dep tough-cookie
+ ([@darcyclarke](https://github.com/darcyclarke))
+* [`d45e181d1`](https://github.com/npm/cli/commit/d45e181d17dd88d82b3a97f8d9cd5fa5b6230e48)
+ [#2335](https://github.com/npm/cli/issues/2335)
+ `ini@2.0.0`, `@npmcli/config@1.2.7`
+ ([@isaacs](https://github.com/isaacs))
+* [`ef4b18b5a`](https://github.com/npm/cli/commit/ef4b18b5a70381b264d234817cff32eeb6848a73)
+ [#2309](https://github.com/npm/cli/issues/2309)
+ `@npmcli/arborist@2.0.2`
+ * properly remove deps when no lockfile and package.json is present
+* [`c6c013e6e`](https://github.com/npm/cli/commit/c6c013e6ebc4fe036695db1fd491eb68f3b57c68)
+ `readdir-scoped-modules@1.1.0`
+* [`a1a2134aa`](https://github.com/npm/cli/commit/a1a2134aa9a1092493db6d6c9a729ff5203f0dd4)
+ remove unused sorted-object dep
+ ([@nlf](https://github.com/nlf))
+* [`85c2a2d31`](https://github.com/npm/cli/commit/85c2a2d318ae066fb2c161174f5aea97e18bc9c5)
+ [#2344](https://github.com/npm/cli/issues/2344)
+ remove editor dependency
+ ([@nlf](https://github.com/nlf))
+
+### TESTING
+
+* [`3a6dd511c`](https://github.com/npm/cli/commit/3a6dd511c944c5f2699825a99bba1dde333a45ef)
+ npm edit
+ ([@nlf](https://github.com/nlf))
+* [`3ba5de4e7`](https://github.com/npm/cli/commit/3ba5de4e7f6c5c0f995a29844926d6ed2833addd)
+ [#2347](https://github.com/npm/cli/issues/2347)
+ npm help-search
+ ([@nlf](https://github.com/nlf))
+* [`6caf19f49`](https://github.com/npm/cli/commit/6caf19f491e144be3e2a1a50f492dad48b01f361)
+ [#2348](https://github.com/npm/cli/issues/2348)
+ npm help
+ ([@nlf](https://github.com/nlf))
+* [`cb5847e32`](https://github.com/npm/cli/commit/cb5847e3203c52062485b5de68e4f6d29b33c361)
+ [#2349](https://github.com/npm/cli/issues/2349)
+ npm hook
+ ([@nlf](https://github.com/nlf))
+* [`996a2f6b1`](https://github.com/npm/cli/commit/996a2f6b130d6678998a2f6a5ec97d75534d5f66)
+ [#2353](https://github.com/npm/cli/issues/2353)
+ npm org
+ ([@nlf](https://github.com/nlf))
+* [`8c67c38a4`](https://github.com/npm/cli/commit/8c67c38a4f476ff5be938db6b6b3ee9ac6b44db5)
+ [#2354](https://github.com/npm/cli/issues/2354)
+ npm set
+ ([@nlf](https://github.com/nlf))
+
## 7.1.2 (2020-12-11)
### DEPENDENCIES
diff --git a/deps/npm/docs/output/commands/npm-ls.html b/deps/npm/docs/output/commands/npm-ls.html
index 3963629acc..125bbb6193 100644
--- a/deps/npm/docs/output/commands/npm-ls.html
+++ b/deps/npm/docs/output/commands/npm-ls.html
@@ -159,7 +159,7 @@ tree at all, use <a href="../commands/npm-explain.html"><code>npm explain</code>
the results to only the paths to the packages named. Note that nested
packages will <em>also</em> show the paths to the specified packages. For
example, running <code>npm ls promzard</code> in npm’s source tree will show:</p>
-<pre lang="bash"><code>npm@7.1.2 /path/to/npm
+<pre lang="bash"><code>npm@7.2.0 /path/to/npm
└─┬ init-package-json@0.0.4
└── promzard@0.1.5
</code></pre>
diff --git a/deps/npm/docs/output/commands/npm.html b/deps/npm/docs/output/commands/npm.html
index 92ed591092..03c7849761 100644
--- a/deps/npm/docs/output/commands/npm.html
+++ b/deps/npm/docs/output/commands/npm.html
@@ -148,7 +148,7 @@ npm command-line interface
<pre lang="bash"><code>npm &lt;command&gt; [args]
</code></pre>
<h3 id="version">Version</h3>
-<p>7.1.2</p>
+<p>7.2.0</p>
<h3 id="description">Description</h3>
<p>npm is the package manager for the Node JavaScript platform. It puts
modules in place so that node can find them, and manages dependency
diff --git a/deps/npm/lib/config.js b/deps/npm/lib/config.js
index ad8db4ff53..561c31e0b3 100644
--- a/deps/npm/lib/config.js
+++ b/deps/npm/lib/config.js
@@ -9,7 +9,7 @@ const { promisify } = require('util')
const fs = require('fs')
const readFile = promisify(fs.readFile)
const writeFile = promisify(fs.writeFile)
-const editor = promisify(require('editor'))
+const { spawn } = require('child_process')
const { EOL } = require('os')
const ini = require('ini')
@@ -138,9 +138,6 @@ const del = async key => {
const edit = async () => {
const { editor: e, global } = npm.flatOptions
- if (!e)
- throw new Error('No `editor` config or EDITOR environment variable set')
-
const where = global ? 'global' : 'user'
const file = npm.config.data.get(where).source
@@ -183,7 +180,15 @@ ${defData}
`.split('\n').join(EOL)
await mkdirp(dirname(file))
await writeFile(file, tmpData, 'utf8')
- await editor(file, { editor: e })
+ await new Promise((resolve, reject) => {
+ const [bin, ...args] = e.split(/\s+/)
+ const editor = spawn(bin, [...args, file], { stdio: 'inherit' })
+ editor.on('exit', (code) => {
+ if (code)
+ return reject(new Error(`editor process exited with code: ${code}`))
+ return resolve()
+ })
+ })
}
const publicVar = k => !/^(\/\/[^:]+:)?_/.test(k)
diff --git a/deps/npm/lib/edit.js b/deps/npm/lib/edit.js
index 43f86dfe70..9ae6349262 100644
--- a/deps/npm/lib/edit.js
+++ b/deps/npm/lib/edit.js
@@ -1,52 +1,36 @@
// npm edit <pkg>
// open the package folder in the $EDITOR
-module.exports = edit
-edit.usage = 'npm edit <pkg>[/<subpkg>...]'
+const { resolve } = require('path')
+const fs = require('graceful-fs')
+const { spawn } = require('child_process')
+const npm = require('./npm.js')
+const usageUtil = require('./utils/usage.js')
+const splitPackageNames = require('./utils/split-package-names.js')
-edit.completion = require('./utils/completion/installed-shallow.js')
-
-var npm = require('./npm.js')
-var path = require('path')
-var fs = require('graceful-fs')
-var editor = require('editor')
-var noProgressTillDone = require('./utils/no-progress-while-running').tillDone
+const usage = usageUtil('edit', 'npm edit <pkg>[/<subpkg>...]')
+const completion = require('./utils/completion/installed-shallow.js')
function edit (args, cb) {
- var p = args[0]
- if (args.length !== 1 || !p)
- return cb(edit.usage)
- var e = npm.config.get('editor')
- if (!e) {
- return cb(new Error(
- "No editor set. Set the 'editor' config, or $EDITOR environ."
- ))
- }
- p = p.split('/')
- // combine scoped parts
- .reduce(function (parts, part) {
- if (parts.length === 0)
- return [part]
-
- var lastPart = parts[parts.length - 1]
- // check if previous part is the first part of a scoped package
- if (lastPart[0] === '@' && !lastPart.includes('/'))
- parts[parts.length - 1] += '/' + part
- else
- parts.push(part)
-
- return parts
- }, [])
- .join('/node_modules/')
- .replace(/(\/node_modules)+/, '/node_modules')
- var f = path.resolve(npm.dir, p)
- fs.lstat(f, function (er) {
- if (er)
- return cb(er)
- editor(f, { editor: e }, noProgressTillDone(function (er) {
- if (er)
- return cb(er)
- npm.commands.rebuild(args, cb)
- }))
+ if (args.length !== 1)
+ return cb(usage)
+
+ const path = splitPackageNames(args[0])
+ const dir = resolve(npm.dir, path)
+
+ fs.lstat(dir, (err) => {
+ if (err)
+ return cb(err)
+
+ const [bin, ...args] = npm.config.get('editor').split(/\s+/)
+ const editor = spawn(bin, [...args, dir], { stdio: 'inherit' })
+ editor.on('exit', (code) => {
+ if (code)
+ return cb(new Error(`editor process exited with code: ${code}`))
+
+ npm.commands.rebuild([dir], cb)
+ })
})
}
+
+module.exports = Object.assign(edit, { completion, usage })
diff --git a/deps/npm/lib/help-search.js b/deps/npm/lib/help-search.js
index ae4302e8cc..c1814b4e53 100644
--- a/deps/npm/lib/help-search.js
+++ b/deps/npm/lib/help-search.js
@@ -1,11 +1,11 @@
const fs = require('fs')
const path = require('path')
const npm = require('./npm.js')
-const glob = require('glob')
const color = require('ansicolors')
const output = require('./utils/output.js')
const usageUtil = require('./utils/usage.js')
const { promisify } = require('util')
+const glob = promisify(require('glob'))
const readFile = promisify(fs.readFile)
const didYouMean = require('./utils/did-you-mean.js')
const { cmdList } = require('./utils/cmd-list.js')
@@ -23,12 +23,17 @@ const helpSearch = async args => {
const docPath = path.resolve(__dirname, '..', 'docs/content')
- // XXX: make glob return a promise and remove this wrapping
- const files = await new Promise((res, rej) =>
- glob(`${docPath}/*/*.md`, (er, files) => er ? rej(er) : res(files)))
-
+ const files = await glob(`${docPath}/*/*.md`)
const data = await readFiles(files)
const results = await searchFiles(args, data, files)
+ // if only one result, then just show that help section.
+ if (results.length === 1) {
+ return npm.commands.help([path.basename(results[0].file, '.md')], er => {
+ if (er)
+ throw er
+ })
+ }
+
const formatted = formatResults(args, results)
if (!formatted.trim())
npmUsage(false)
@@ -125,15 +130,6 @@ const searchFiles = async (args, data, files) => {
})
}
- // if only one result, then just show that help section.
- if (results.length === 1) {
- npm.commands.help([results[0].file.replace(/\.md$/, '')], er => {
- if (er)
- throw er
- })
- return []
- }
-
// sort results by number of results found, then by number of hits
// then by number of matching lines
return results.sort((a, b) =>
@@ -147,9 +143,6 @@ const searchFiles = async (args, data, files) => {
}
const formatResults = (args, results) => {
- if (!results)
- return 'No results for ' + args.map(JSON.stringify).join(' ')
-
const cols = Math.min(process.stdout.columns || Infinity, 80) + 1
const out = results.map(res => {
diff --git a/deps/npm/lib/help.js b/deps/npm/lib/help.js
index 5f9563e1cf..171c52704d 100644
--- a/deps/npm/lib/help.js
+++ b/deps/npm/lib/help.js
@@ -133,7 +133,12 @@ function viewMan (man, cb) {
break
case 'browser':
- openUrl(htmlMan(man), 'help available at the following URL', cb)
+ try {
+ var url = htmlMan(man)
+ } catch (err) {
+ return cb(err)
+ }
+ openUrl(url, 'help available at the following URL', cb)
break
default:
diff --git a/deps/npm/lib/org.js b/deps/npm/lib/org.js
index d430131f83..b7af3f3a30 100644
--- a/deps/npm/lib/org.js
+++ b/deps/npm/lib/org.js
@@ -73,9 +73,9 @@ function orgSet (org, user, role, opts) {
memDeets.org.size,
memDeets.user,
memDeets.role,
- ])
+ ].join('\t'))
} else if (!opts.silent && opts.loglevel !== 'silent')
- output(`Added ${memDeets.user} as ${memDeets.role} to ${memDeets.org.name}. You now ${memDeets.org.size} member${memDeets.org.size === 1 ? '' : 's'} in this org.`)
+ output(`Added ${memDeets.user} as ${memDeets.role} to ${memDeets.org.name}. You now have ${memDeets.org.size} member${memDeets.org.size === 1 ? '' : 's'} in this org.`)
return memDeets
})
diff --git a/deps/npm/lib/rebuild.js b/deps/npm/lib/rebuild.js
index e02c89bd79..ab34b7f3df 100644
--- a/deps/npm/lib/rebuild.js
+++ b/deps/npm/lib/rebuild.js
@@ -39,16 +39,25 @@ const getFilterFn = args => {
const spec = npa(arg)
if (spec.type === 'tag' && spec.rawSpec === '')
return spec
- if (spec.type !== 'range' && spec.type !== 'version')
+
+ if (spec.type !== 'range' && spec.type !== 'version' && spec.type !== 'directory')
throw new Error('`npm rebuild` only supports SemVer version/range specifiers')
+
return spec
})
+
return node => specs.some(spec => {
- const { version } = node.package
+ if (spec.type === 'directory')
+ return node.path === spec.fetchSpec
+
if (spec.name !== node.name)
return false
+
if (spec.rawSpec === '' || spec.rawSpec === '*')
return true
+
+ const { version } = node.package
+ // TODO: add tests for a package with missing version
return semver.satisfies(version, spec.fetchSpec)
})
}
diff --git a/deps/npm/lib/utils/child-path.js b/deps/npm/lib/utils/child-path.js
deleted file mode 100644
index 38b9df1380..0000000000
--- a/deps/npm/lib/utils/child-path.js
+++ /dev/null
@@ -1,9 +0,0 @@
-var path = require('path')
-var validate = require('aproba')
-var moduleName = require('../utils/module-name.js')
-
-module.exports = childPath
-function childPath (parentPath, child) {
- validate('SO', arguments)
- return path.join(parentPath, 'node_modules', moduleName(child))
-}
diff --git a/deps/npm/lib/utils/completion/file-completion.js b/deps/npm/lib/utils/completion/file-completion.js
deleted file mode 100644
index b32eda52df..0000000000
--- a/deps/npm/lib/utils/completion/file-completion.js
+++ /dev/null
@@ -1,23 +0,0 @@
-module.exports = fileCompletion
-
-const mkdir = require('mkdirp')
-const glob = require('glob')
-
-function fileCompletion (root, req, depth, cb) {
- if (typeof cb !== 'function') {
- cb = depth
- depth = Infinity
- }
- mkdir(root).catch(cb).then(() => {
- // can be either exactly the req, or a descendent
- var pattern = root + '/{' + req + ',' + req + '/**/*}'
- var opts = { mark: true, dot: true, maxDepth: depth }
- glob(pattern, opts, function (er, files) {
- if (er)
- return cb(er)
- return cb(null, (files || []).map(function (f) {
- return f.substr(root.length + 1).replace(/^\/|\/$/g, '')
- }))
- })
- })
-}
diff --git a/deps/npm/lib/utils/deep-sort-object.js b/deps/npm/lib/utils/deep-sort-object.js
deleted file mode 100644
index 56f1854f1e..0000000000
--- a/deps/npm/lib/utils/deep-sort-object.js
+++ /dev/null
@@ -1,14 +0,0 @@
-var sortedObject = require('sorted-object')
-
-module.exports = function deepSortObject (obj) {
- if (obj == null || typeof obj !== 'object')
- return obj
- if (obj instanceof Array)
- return obj.map(deepSortObject)
-
- obj = sortedObject(obj)
- Object.keys(obj).forEach(function (key) {
- obj[key] = deepSortObject(obj[key])
- })
- return obj
-}
diff --git a/deps/npm/lib/utils/git.js b/deps/npm/lib/utils/git.js
deleted file mode 100644
index 299302b277..0000000000
--- a/deps/npm/lib/utils/git.js
+++ /dev/null
@@ -1,55 +0,0 @@
-const exec = require('child_process').execFile
-const spawn = require('./spawn')
-const npm = require('../npm.js')
-const which = require('which')
-const git = npm.config.get('git')
-const log = require('npmlog')
-const noProgressTillDone = require('./no-progress-while-running.js').tillDone
-const { promisify } = require('util')
-
-exports.spawn = spawnGit
-exports.exec = promisify(execGit)
-exports.chainableExec = chainableExec
-exports.whichAndExec = whichAndExec
-
-function prefixGitArgs () {
- return process.platform === 'win32' ? ['-c', 'core.longpaths=true'] : []
-}
-
-function execGit (args, options, cb) {
- log.info('git', args)
- const fullArgs = prefixGitArgs().concat(args || [])
- return exec(git, fullArgs, options, noProgressTillDone(cb))
-}
-
-function spawnGit (args, options) {
- log.info('git', args)
- // If we're already in a git command (eg, running test as an exec
- // line in an interactive rebase) then these environment variables
- // will force git to operate on the current project, instead of
- // checking out/fetching/etc. whatever the user actually intends.
- options.env = options.env || Object.keys(process.env)
- .filter(k => !/^GIT/.test(k))
- .reduce((set, k) => {
- set[k] = process.env[k]
- return set
- }, {})
- return spawn(git, prefixGitArgs().concat(args || []), options)
-}
-
-function chainableExec () {
- var args = Array.prototype.slice.call(arguments)
- return [execGit].concat(args)
-}
-
-function whichAndExec (args, options, cb) {
- // check for git
- which(git, function (err) {
- if (err) {
- err.code = 'ENOGIT'
- return cb(err)
- }
-
- execGit(args, options, cb)
- })
-}
diff --git a/deps/npm/lib/utils/module-name.js b/deps/npm/lib/utils/module-name.js
deleted file mode 100644
index c58050e55e..0000000000
--- a/deps/npm/lib/utils/module-name.js
+++ /dev/null
@@ -1,38 +0,0 @@
-var path = require('path')
-
-module.exports = moduleName
-module.exports.test = {}
-
-module.exports.test.pathToPackageName = pathToPackageName
-function pathToPackageName (dir) {
- if (dir == null)
- return ''
- if (dir === '')
- return ''
- var name = path.relative(path.resolve(dir, '..'), dir)
- var scoped = path.relative(path.resolve(dir, '../..'), dir)
- if (scoped[0] === '@')
- return scoped.replace(/\\/g, '/')
- return name.trim()
-}
-
-module.exports.test.isNotEmpty = isNotEmpty
-function isNotEmpty (str) {
- return str != null && str !== ''
-}
-
-var unknown = 0
-function moduleName (tree) {
- if (tree.name)
- return tree.name
- var pkg = tree.package || tree
- if (isNotEmpty(pkg.name) && typeof pkg.name === 'string')
- return pkg.name.trim()
- var pkgName = pathToPackageName(tree.path)
- if (pkgName !== '')
- return pkgName
- if (tree._invalidName != null)
- return tree._invalidName
- tree._invalidName = '!invalid#' + (++unknown)
- return tree._invalidName
-}
diff --git a/deps/npm/lib/utils/split-package-names.js b/deps/npm/lib/utils/split-package-names.js
new file mode 100644
index 0000000000..bb6e449bac
--- /dev/null
+++ b/deps/npm/lib/utils/split-package-names.js
@@ -0,0 +1,23 @@
+'use strict'
+
+const splitPackageNames = (path) => {
+ return path.split('/')
+ // combine scoped parts
+ .reduce((parts, part) => {
+ if (parts.length === 0)
+ return [part]
+
+ const lastPart = parts[parts.length - 1]
+ // check if previous part is the first part of a scoped package
+ if (lastPart[0] === '@' && !lastPart.includes('/'))
+ parts[parts.length - 1] += '/' + part
+ else
+ parts.push(part)
+
+ return parts
+ }, [])
+ .join('/node_modules/')
+ .replace(/(\/node_modules)+/, '/node_modules')
+}
+
+module.exports = splitPackageNames
diff --git a/deps/npm/man/man1/npm-ls.1 b/deps/npm/man/man1/npm-ls.1
index 0f486c67cc..9db81f7290 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\.1\.2 /path/to/npm
+npm@7\.2\.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 59655ec71e..e18720c1ed 100644
--- a/deps/npm/man/man1/npm.1
+++ b/deps/npm/man/man1/npm.1
@@ -10,7 +10,7 @@ npm <command> [args]
.RE
.SS Version
.P
-7\.1\.2
+7\.2\.0
.SS Description
.P
npm is the package manager for the Node JavaScript platform\. It puts
diff --git a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js
index 731b785187..c1f18af7e4 100644
--- a/deps/npm/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js
+++ b/deps/npm/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js
@@ -312,8 +312,14 @@ module.exports = cls => class IdealTreeBuilder extends cls {
// Load on a new Arborist object, so the Nodes aren't the same,
// or else it'll get super confusing when we change them!
.then(async root => {
- if (!this[_updateAll] && !this[_global] && !root.meta.loadedFromDisk)
+ if (!this[_updateAll] && !this[_global] && !root.meta.loadedFromDisk) {
await new this.constructor(this.options).loadActual({ root })
+ // even though we didn't load it from a package-lock.json FILE,
+ // we still loaded it "from disk", meaning we have to reset
+ // dep flags before assuming that any mutations were reflected.
+ if (root.children.size)
+ root.meta.loadedFromDisk = true
+ }
return root
})
diff --git a/deps/npm/node_modules/@npmcli/arborist/package.json b/deps/npm/node_modules/@npmcli/arborist/package.json
index 2f3ccb6131..b8b27c29fd 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.0.1",
+ "version": "2.0.2",
"description": "Manage node_modules trees",
"dependencies": {
"@npmcli/installed-package-contents": "^1.0.5",
diff --git a/deps/npm/node_modules/@npmcli/config/package.json b/deps/npm/node_modules/@npmcli/config/package.json
index f8334ab51d..26581f385c 100644
--- a/deps/npm/node_modules/@npmcli/config/package.json
+++ b/deps/npm/node_modules/@npmcli/config/package.json
@@ -1,6 +1,6 @@
{
"name": "@npmcli/config",
- "version": "1.2.6",
+ "version": "1.2.7",
"files": [
"lib"
],
@@ -27,7 +27,7 @@
"tap": "^14.10.8"
},
"dependencies": {
- "ini": "^1.3.5",
+ "ini": "^2.0.0",
"mkdirp-infer-owner": "^2.0.0",
"nopt": "^5.0.0",
"semver": "^7.3.4",
diff --git a/deps/npm/node_modules/editor/LICENSE b/deps/npm/node_modules/editor/LICENSE
deleted file mode 100644
index 8b856bc4a4..0000000000
--- a/deps/npm/node_modules/editor/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-Copyright 2013 James Halliday (mail@substack.net)
-
-This project is free software released under the MIT license:
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/deps/npm/node_modules/editor/README.markdown b/deps/npm/node_modules/editor/README.markdown
deleted file mode 100644
index c1121cad2f..0000000000
--- a/deps/npm/node_modules/editor/README.markdown
+++ /dev/null
@@ -1,54 +0,0 @@
-editor
-======
-
-Launch $EDITOR in your program.
-
-example
-=======
-
-``` js
-var editor = require('editor');
-editor('beep.json', function (code, sig) {
- console.log('finished editing with code ' + code);
-});
-```
-
-***
-
-```
-$ node edit.js
-```
-
-![editor](http://substack.net/images/screenshots/editor.png)
-
-```
-finished editing with code 0
-```
-
-methods
-=======
-
-``` js
-var editor = require('editor')
-```
-
-editor(file, opts={}, cb)
--------------------------
-
-Launch the `$EDITOR` (or `opts.editor`) for `file`.
-
-When the editor exits, `cb(code, sig)` fires.
-
-install
-=======
-
-With [npm](http://npmjs.org) do:
-
-```
-npm install editor
-```
-
-license
-=======
-
-MIT
diff --git a/deps/npm/node_modules/editor/example/beep.json b/deps/npm/node_modules/editor/example/beep.json
deleted file mode 100644
index ac07d2da87..0000000000
--- a/deps/npm/node_modules/editor/example/beep.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "a" : 3,
- "b" : 4,
- "c" : 5
-}
diff --git a/deps/npm/node_modules/editor/example/edit.js b/deps/npm/node_modules/editor/example/edit.js
deleted file mode 100644
index ee11728710..0000000000
--- a/deps/npm/node_modules/editor/example/edit.js
+++ /dev/null
@@ -1,4 +0,0 @@
-var editor = require('../');
-editor(__dirname + '/beep.json', function (code, sig) {
- console.log('finished editing with code ' + code);
-});
diff --git a/deps/npm/node_modules/editor/index.js b/deps/npm/node_modules/editor/index.js
deleted file mode 100644
index 3774edbe37..0000000000
--- a/deps/npm/node_modules/editor/index.js
+++ /dev/null
@@ -1,20 +0,0 @@
-var spawn = require('child_process').spawn;
-
-module.exports = function (file, opts, cb) {
- if (typeof opts === 'function') {
- cb = opts;
- opts = {};
- }
- if (!opts) opts = {};
-
- var ed = /^win/.test(process.platform) ? 'notepad' : 'vim';
- var editor = opts.editor || process.env.VISUAL || process.env.EDITOR || ed;
- var args = editor.split(/\s+/);
- var bin = args.shift();
-
- var ps = spawn(bin, args.concat([ file ]), { stdio: 'inherit' });
-
- ps.on('exit', function (code, sig) {
- if (typeof cb === 'function') cb(code, sig)
- });
-};
diff --git a/deps/npm/node_modules/editor/package.json b/deps/npm/node_modules/editor/package.json
deleted file mode 100644
index d956a68024..0000000000
--- a/deps/npm/node_modules/editor/package.json
+++ /dev/null
@@ -1,34 +0,0 @@
-{
- "name" : "editor",
- "version" : "1.0.0",
- "description" : "launch $EDITOR in your program",
- "main" : "index.js",
- "directories" : {
- "example" : "example",
- "test" : "test"
- },
- "dependencies" : {},
- "devDependencies" : {
- "tap" : "~0.4.4"
- },
- "scripts" : {
- "test" : "tap test/*.js"
- },
- "repository" : {
- "type" : "git",
- "url" : "git://github.com/substack/node-editor.git"
- },
- "homepage" : "https://github.com/substack/node-editor",
- "keywords" : [
- "text",
- "edit",
- "shell"
- ],
- "author" : {
- "name" : "James Halliday",
- "email" : "mail@substack.net",
- "url" : "http://substack.net"
- },
- "license" : "MIT",
- "engine" : { "node" : ">=0.6" }
-}
diff --git a/deps/npm/node_modules/ini/ini.js b/deps/npm/node_modules/ini/ini.js
index b576f08d7a..7d05a719b0 100644
--- a/deps/npm/node_modules/ini/ini.js
+++ b/deps/npm/node_modules/ini/ini.js
@@ -1,16 +1,11 @@
-exports.parse = exports.decode = decode
+const { hasOwnProperty } = Object.prototype
-exports.stringify = exports.encode = encode
-
-exports.safe = safe
-exports.unsafe = unsafe
-
-var eol = typeof process !== 'undefined' &&
+const eol = typeof process !== 'undefined' &&
process.platform === 'win32' ? '\r\n' : '\n'
-function encode (obj, opt) {
- var children = []
- var out = ''
+const encode = (obj, opt) => {
+ const children = []
+ let out = ''
if (typeof opt === 'string') {
opt = {
@@ -18,93 +13,90 @@ function encode (obj, opt) {
whitespace: false,
}
} else {
- opt = opt || {}
+ opt = opt || Object.create(null)
opt.whitespace = opt.whitespace === true
}
- var separator = opt.whitespace ? ' = ' : '='
+ const separator = opt.whitespace ? ' = ' : '='
- Object.keys(obj).forEach(function (k, _, __) {
- var val = obj[k]
+ for (const k of Object.keys(obj)) {
+ const val = obj[k]
if (val && Array.isArray(val)) {
- val.forEach(function (item) {
+ for (const item of val)
out += safe(k + '[]') + separator + safe(item) + '\n'
- })
} else if (val && typeof val === 'object')
children.push(k)
else
out += safe(k) + separator + safe(val) + eol
- })
+ }
if (opt.section && out.length)
out = '[' + safe(opt.section) + ']' + eol + out
- children.forEach(function (k, _, __) {
- var nk = dotSplit(k).join('\\.')
- var section = (opt.section ? opt.section + '.' : '') + nk
- var child = encode(obj[k], {
- section: section,
- whitespace: opt.whitespace,
+ for (const k of children) {
+ const nk = dotSplit(k).join('\\.')
+ const section = (opt.section ? opt.section + '.' : '') + nk
+ const { whitespace } = opt
+ const child = encode(obj[k], {
+ section,
+ whitespace,
})
if (out.length && child.length)
out += eol
out += child
- })
+ }
return out
}
-function dotSplit (str) {
- return str.replace(/\1/g, '\u0002LITERAL\\1LITERAL\u0002')
+const dotSplit = str =>
+ str.replace(/\1/g, '\u0002LITERAL\\1LITERAL\u0002')
.replace(/\\\./g, '\u0001')
- .split(/\./).map(function (part) {
- return part.replace(/\1/g, '\\.')
- .replace(/\2LITERAL\\1LITERAL\2/g, '\u0001')
- })
-}
-
-function decode (str) {
- var out = {}
- var p = out
- var section = null
+ .split(/\./)
+ .map(part =>
+ part.replace(/\1/g, '\\.')
+ .replace(/\2LITERAL\\1LITERAL\2/g, '\u0001'))
+
+const decode = str => {
+ const out = Object.create(null)
+ let p = out
+ let section = null
// section |key = value
- var re = /^\[([^\]]*)\]$|^([^=]+)(=(.*))?$/i
- var lines = str.split(/[\r\n]+/g)
+ const re = /^\[([^\]]*)\]$|^([^=]+)(=(.*))?$/i
+ const lines = str.split(/[\r\n]+/g)
- lines.forEach(function (line, _, __) {
+ for (const line of lines) {
if (!line || line.match(/^\s*[;#]/))
- return
- var match = line.match(re)
+ continue
+ const match = line.match(re)
if (!match)
- return
+ continue
if (match[1] !== undefined) {
section = unsafe(match[1])
if (section === '__proto__') {
// not allowed
// keep parsing the section, but don't attach it.
- p = {}
- return
+ p = Object.create(null)
+ continue
}
- p = out[section] = out[section] || {}
- return
+ p = out[section] = out[section] || Object.create(null)
+ continue
}
- var key = unsafe(match[2])
+ const keyRaw = unsafe(match[2])
+ const isArray = keyRaw.length > 2 && keyRaw.slice(-2) === '[]'
+ const key = isArray ? keyRaw.slice(0, -2) : keyRaw
if (key === '__proto__')
- return
- var value = match[3] ? unsafe(match[4]) : true
- switch (value) {
- case 'true':
- case 'false':
- case 'null': value = JSON.parse(value)
- }
+ continue
+ const valueRaw = match[3] ? unsafe(match[4]) : true
+ const value = valueRaw === 'true' ||
+ valueRaw === 'false' ||
+ valueRaw === 'null' ? JSON.parse(valueRaw)
+ : valueRaw
// Convert keys with '[]' suffix to an array
- if (key.length > 2 && key.slice(-2) === '[]') {
- key = key.substring(0, key.length - 2)
- if (key === '__proto__')
- return
- if (!p[key])
+ if (isArray) {
+ if (!hasOwnProperty.call(p, key))
p[key] = []
else if (!Array.isArray(p[key]))
p[key] = [p[key]]
@@ -116,48 +108,48 @@ function decode (str) {
p[key].push(value)
else
p[key] = value
- })
+ }
// {a:{y:1},"a.b":{x:2}} --> {a:{y:1,b:{x:2}}}
// use a filter to return the keys that have to be deleted.
- Object.keys(out).filter(function (k, _, __) {
- if (!out[k] ||
- typeof out[k] !== 'object' ||
- Array.isArray(out[k]))
- return false
+ const remove = []
+ for (const k of Object.keys(out)) {
+ if (!hasOwnProperty.call(out, k) ||
+ typeof out[k] !== 'object' ||
+ Array.isArray(out[k]))
+ continue
// see if the parent section is also an object.
// if so, add it to that, and mark this one for deletion
- var parts = dotSplit(k)
- var p = out
- var l = parts.pop()
- var nl = l.replace(/\\\./g, '.')
- parts.forEach(function (part, _, __) {
+ const parts = dotSplit(k)
+ let p = out
+ const l = parts.pop()
+ const nl = l.replace(/\\\./g, '.')
+ for (const part of parts) {
if (part === '__proto__')
- return
- if (!p[part] || typeof p[part] !== 'object')
- p[part] = {}
+ continue
+ if (!hasOwnProperty.call(p, part) || typeof p[part] !== 'object')
+ p[part] = Object.create(null)
p = p[part]
- })
+ }
if (p === out && nl === l)
- return false
+ continue
p[nl] = out[k]
- return true
- }).forEach(function (del, _, __) {
+ remove.push(k)
+ }
+ for (const del of remove)
delete out[del]
- })
return out
}
-function isQuoted (val) {
- return (val.charAt(0) === '"' && val.slice(-1) === '"') ||
+const isQuoted = val =>
+ (val.charAt(0) === '"' && val.slice(-1) === '"') ||
(val.charAt(0) === "'" && val.slice(-1) === "'")
-}
-function safe (val) {
- return (typeof val !== 'string' ||
+const safe = val =>
+ (typeof val !== 'string' ||
val.match(/[=\r\n]/) ||
val.match(/^\[/) ||
(val.length > 1 &&
@@ -165,9 +157,8 @@ function safe (val) {
val !== val.trim())
? JSON.stringify(val)
: val.replace(/;/g, '\\;').replace(/#/g, '\\#')
-}
-function unsafe (val, doUnesc) {
+const unsafe = (val, doUnesc) => {
val = (val || '').trim()
if (isQuoted(val)) {
// remove the single quotes before calling JSON.parse
@@ -179,10 +170,10 @@ function unsafe (val, doUnesc) {
} catch (_) {}
} else {
// walk the val to find the first not-escaped ; character
- var esc = false
- var unesc = ''
- for (var i = 0, l = val.length; i < l; i++) {
- var c = val.charAt(i)
+ let esc = false
+ let unesc = ''
+ for (let i = 0, l = val.length; i < l; i++) {
+ const c = val.charAt(i)
if (esc) {
if ('\\;#'.indexOf(c) !== -1)
unesc += c
@@ -204,3 +195,12 @@ function unsafe (val, doUnesc) {
}
return val
}
+
+module.exports = {
+ parse: decode,
+ decode,
+ stringify: encode,
+ encode,
+ safe,
+ unsafe,
+}
diff --git a/deps/npm/node_modules/ini/package.json b/deps/npm/node_modules/ini/package.json
index c830a3556e..59b7d5d0ad 100644
--- a/deps/npm/node_modules/ini/package.json
+++ b/deps/npm/node_modules/ini/package.json
@@ -2,7 +2,7 @@
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
"name": "ini",
"description": "An ini encoder/decoder for node",
- "version": "1.3.8",
+ "version": "2.0.0",
"repository": {
"type": "git",
"url": "git://github.com/isaacs/ini.git"
@@ -29,5 +29,8 @@
"license": "ISC",
"files": [
"ini.js"
- ]
+ ],
+ "engines": {
+ "node": ">=10"
+ }
}
diff --git a/deps/npm/node_modules/sorted-object/LICENSE.txt b/deps/npm/node_modules/sorted-object/LICENSE.txt
deleted file mode 100644
index 2edd064bf5..0000000000
--- a/deps/npm/node_modules/sorted-object/LICENSE.txt
+++ /dev/null
@@ -1,47 +0,0 @@
-Dual licensed under WTFPL and MIT:
-
----
-
-Copyright © 2014–2016 Domenic Denicola <d@domenic.me>
-
-This work is free. You can redistribute it and/or modify it under the
-terms of the Do What The Fuck You Want To Public License, Version 2,
-as published by Sam Hocevar. See below for more details.
-
- DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
- Version 2, December 2004
-
- Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
-
- Everyone is permitted to copy and distribute verbatim or modified
- copies of this license document, and changing it is allowed as long
- as the name is changed.
-
- DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. You just DO WHAT THE FUCK YOU WANT TO.
-
----
-
-The MIT License (MIT)
-
-Copyright © 2014–2016 Domenic Denicola <d@domenic.me>
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/deps/npm/node_modules/sorted-object/lib/sorted-object.js b/deps/npm/node_modules/sorted-object/lib/sorted-object.js
deleted file mode 100644
index 1b3fe81a6b..0000000000
--- a/deps/npm/node_modules/sorted-object/lib/sorted-object.js
+++ /dev/null
@@ -1,11 +0,0 @@
-"use strict";
-
-module.exports = function (input) {
- var output = {};
-
- Object.keys(input).sort().forEach(function (key) {
- output[key] = input[key];
- });
-
- return output;
-};
diff --git a/deps/npm/node_modules/sorted-object/package.json b/deps/npm/node_modules/sorted-object/package.json
deleted file mode 100644
index 2e81f36d6e..0000000000
--- a/deps/npm/node_modules/sorted-object/package.json
+++ /dev/null
@@ -1,25 +0,0 @@
-{
- "name": "sorted-object",
- "description": "Returns a copy of an object with its keys sorted",
- "keywords": [
- "sort",
- "keys",
- "object"
- ],
- "version": "2.0.1",
- "author": "Domenic Denicola <d@domenic.me> (https://domenic.me/)",
- "license": "(WTFPL OR MIT)",
- "repository": "domenic/sorted-object",
- "main": "lib/sorted-object.js",
- "files": [
- "lib/"
- ],
- "scripts": {
- "test": "tape test/tests.js",
- "lint": "eslint ."
- },
- "devDependencies": {
- "eslint": "^2.4.0",
- "tape": "^4.5.1"
- }
-}
diff --git a/deps/npm/package.json b/deps/npm/package.json
index 89cb0e6aad..8e2917c5ed 100644
--- a/deps/npm/package.json
+++ b/deps/npm/package.json
@@ -1,5 +1,5 @@
{
- "version": "7.1.2",
+ "version": "7.2.0",
"name": "npm",
"description": "a package manager for JavaScript",
"keywords": [
@@ -42,9 +42,9 @@
"./package.json": "./package.json"
},
"dependencies": {
- "@npmcli/arborist": "^2.0.1",
+ "@npmcli/arborist": "^2.0.2",
"@npmcli/ci-detect": "^1.2.0",
- "@npmcli/config": "^1.2.6",
+ "@npmcli/config": "^1.2.7",
"@npmcli/run-script": "^1.8.1",
"abbrev": "~1.1.1",
"ansicolors": "~0.3.2",
@@ -58,11 +58,10 @@
"cli-columns": "^3.1.2",
"cli-table3": "^0.6.0",
"columnify": "~1.5.4",
- "editor": "~1.0.0",
"glob": "^7.1.4",
"graceful-fs": "^4.2.3",
"hosted-git-info": "^3.0.6",
- "ini": "^1.3.8",
+ "ini": "^2.0.0",
"init-package-json": "^2.0.1",
"is-cidr": "^4.0.2",
"leven": "^3.1.0",
@@ -97,9 +96,9 @@
"read": "~1.0.7",
"read-package-json": "^3.0.0",
"read-package-json-fast": "^1.2.1",
+ "readdir-scoped-modules": "^1.1.0",
"rimraf": "^3.0.2",
"semver": "^7.3.4",
- "sorted-object": "~2.0.1",
"ssri": "^8.0.0",
"tar": "^6.0.5",
"text-table": "~0.2.0",
@@ -127,7 +126,6 @@
"cli-columns",
"cli-table3",
"columnify",
- "editor",
"glob",
"graceful-fs",
"hosted-git-info",
@@ -167,9 +165,9 @@
"read",
"read-package-json",
"read-package-json-fast",
+ "readdir-scoped-modules",
"rimraf",
"semver",
- "sorted-object",
"ssri",
"tar",
"text-table",
diff --git a/deps/npm/test/lib/config.js b/deps/npm/test/lib/config.js
index 8a11a40c81..74cd530c68 100644
--- a/deps/npm/test/lib/config.js
+++ b/deps/npm/test/lib/config.js
@@ -1,5 +1,6 @@
const t = require('tap')
const requireInject = require('require-inject')
+const { EventEmitter } = require('events')
const redactCwd = (path) => {
const normalizePath = p => p
@@ -437,10 +438,16 @@ sign-git-commit=true`
cb()
},
},
- editor: (file, { editor }, cb) => {
- t.equal(file, '~/.npmrc', 'should match user source data')
- t.equal(editor, 'vi', 'should use default editor')
- cb()
+ child_process: {
+ spawn: (bin, args) => {
+ t.equal(bin, 'vi', 'should use default editor')
+ t.strictSame(args, ['~/.npmrc'], 'should match user source data')
+ const ee = new EventEmitter()
+ process.nextTick(() => {
+ ee.emit('exit', 0)
+ })
+ return ee
+ },
},
}
const config = requireInject('../../lib/config.js', editMocks)
@@ -487,15 +494,21 @@ t.test('config edit --global', t => {
cb()
},
},
- editor: (file, { editor }, cb) => {
- t.equal(file, '/etc/npmrc', 'should match global source data')
- t.equal(editor, 'vi', 'should use default editor')
- cb()
+ child_process: {
+ spawn: (bin, args, cb) => {
+ t.equal(bin, 'vi', 'should use default editor')
+ t.strictSame(args, ['/etc/npmrc'], 'should match global source data')
+ const ee = new EventEmitter()
+ process.nextTick(() => {
+ ee.emit('exit', 137)
+ })
+ return ee
+ },
},
}
const config = requireInject('../../lib/config.js', editMocks)
config(['edit'], (err) => {
- t.ifError(err, 'npm config edit --global')
+ t.match(err, /exited with code: 137/, 'propagated exit code from editor')
})
t.teardown(() => {
@@ -505,19 +518,6 @@ t.test('config edit --global', t => {
})
})
-t.test('config edit no editor set', t => {
- flatOptions.editor = undefined
- config(['edit'], (err) => {
- t.match(
- err,
- /No `editor` config or EDITOR environment variable set/,
- 'should throw no available editor error'
- )
- flatOptions.editor = 'vi'
- t.end()
- })
-})
-
t.test('completion', t => {
const { completion } = config
diff --git a/deps/npm/test/lib/edit.js b/deps/npm/test/lib/edit.js
new file mode 100644
index 0000000000..0d3bbb4c57
--- /dev/null
+++ b/deps/npm/test/lib/edit.js
@@ -0,0 +1,123 @@
+const { test } = require('tap')
+const { resolve } = require('path')
+const requireInject = require('require-inject')
+const { EventEmitter } = require('events')
+
+let editorBin = null
+let editorArgs = null
+let editorOpts = null
+let EDITOR_CODE = 0
+const childProcess = {
+ spawn: (bin, args, opts) => {
+ // save for assertions
+ editorBin = bin
+ editorArgs = args
+ editorOpts = opts
+
+ const editorEvents = new EventEmitter()
+ process.nextTick(() => {
+ editorEvents.emit('exit', EDITOR_CODE)
+ })
+ return editorEvents
+ },
+}
+
+let rebuildArgs = null
+let EDITOR = 'vim'
+const npm = {
+ config: {
+ get: () => EDITOR,
+ },
+ dir: resolve(__dirname, '../../node_modules'),
+ commands: {
+ rebuild: (args, cb) => {
+ rebuildArgs = args
+ return cb()
+ },
+ },
+}
+
+const gracefulFs = require('graceful-fs')
+const edit = requireInject('../../lib/edit.js', {
+ '../../lib/npm.js': npm,
+ child_process: childProcess,
+ 'graceful-fs': gracefulFs,
+})
+
+test('npm edit', t => {
+ t.teardown(() => {
+ rebuildArgs = null
+ editorBin = null
+ editorArgs = null
+ editorOpts = null
+ })
+
+ return edit(['semver'], (err) => {
+ if (err)
+ throw err
+
+ const path = resolve(__dirname, '../../node_modules/semver')
+ t.strictSame(editorBin, EDITOR, 'used the correct editor')
+ t.strictSame(editorArgs, [path], 'edited the correct directory')
+ t.strictSame(editorOpts, { stdio: 'inherit' }, 'passed the correct opts')
+ t.strictSame(rebuildArgs, [path], 'passed the correct path to rebuild')
+ t.end()
+ })
+})
+
+test('npm edit editor has flags', t => {
+ EDITOR = 'code -w'
+ t.teardown(() => {
+ rebuildArgs = null
+ editorBin = null
+ editorArgs = null
+ editorOpts = null
+ EDITOR = 'vim'
+ })
+
+ return edit(['semver'], (err) => {
+ if (err)
+ throw err
+
+ const path = resolve(__dirname, '../../node_modules/semver')
+ t.strictSame(editorBin, 'code', 'used the correct editor')
+ t.strictSame(editorArgs, ['-w', path], 'edited the correct directory, keeping flags')
+ t.strictSame(editorOpts, { stdio: 'inherit' }, 'passed the correct opts')
+ t.strictSame(rebuildArgs, [path], 'passed the correct path to rebuild')
+ t.end()
+ })
+})
+
+test('npm edit no args', t => {
+ return edit([], (err) => {
+ t.match(err, /npm edit/, 'throws usage error')
+ t.end()
+ })
+})
+
+test('npm edit lstat error propagates', t => {
+ const _lstat = gracefulFs.lstat
+ gracefulFs.lstat = (dir, cb) => {
+ return cb(new Error('lstat failed'))
+ }
+ t.teardown(() => {
+ gracefulFs.lstat = _lstat
+ })
+
+ return edit(['semver'], (err) => {
+ t.match(err, /lstat failed/, 'user received correct error')
+ t.end()
+ })
+})
+
+test('npm edit editor exit code error propagates', t => {
+ EDITOR_CODE = 137
+ t.teardown(() => {
+ EDITOR_CODE = 0
+ })
+
+ return edit(['semver'], (err) => {
+ t.match(err, /exited with code: 137/, 'user received correct error')
+ t.end()
+ })
+})
diff --git a/deps/npm/test/lib/help-search.js b/deps/npm/test/lib/help-search.js
new file mode 100644
index 0000000000..5ecf5db061
--- /dev/null
+++ b/deps/npm/test/lib/help-search.js
@@ -0,0 +1,181 @@
+const { test } = require('tap')
+const { join } = require('path')
+const requireInject = require('require-inject')
+const ansicolors = require('ansicolors')
+
+const OUTPUT = []
+const output = (msg) => {
+ OUTPUT.push(msg)
+}
+
+let npmHelpArgs = null
+let npmHelpErr = null
+const npm = {
+ color: false,
+ flatOptions: {
+ long: false,
+ },
+ commands: {
+ help: (args, cb) => {
+ npmHelpArgs = args
+ return cb(npmHelpErr)
+ },
+ },
+}
+
+let npmUsageArg = null
+const npmUsage = (arg) => {
+ npmUsageArg = arg
+}
+
+let globRoot = null
+const globDir = {
+ 'npm-exec.md': 'the exec command\nhelp has multiple lines of exec help\none of them references exec',
+ 'npm-something.md': 'another\ncommand you run\nthat\nreferences exec\nand has multiple lines\nwith no matches\nthat will be ignored\nand another line\nthat does have exec as well',
+ 'npm-run-script.md': 'the scripted run-script command runs scripts\nand has lines\nsome of which dont match the string run\nor script\nscript',
+ 'npm-install.md': 'does a thing in a script\nif a thing does not exist in a thing you run\nto install it and run it maybe in a script',
+ 'npm-help.md': 'will run the `help-search` command if you need to run it to help you search',
+ 'npm-help-search.md': 'is the help search command\nthat you get if you run help-search',
+ 'npm-useless.md': 'exec\nexec',
+ 'npm-more-useless.md': 'exec exec',
+ 'npm-extra-useless.md': 'exec\nexec\nexec',
+}
+const glob = (p, cb) => cb(null, Object.keys(globDir).map((file) => join(globRoot, file)))
+
+const helpSearch = requireInject('../../lib/help-search.js', {
+ '../../lib/npm.js': npm,
+ '../../lib/utils/npm-usage.js': npmUsage,
+ '../../lib/utils/output.js': output,
+ glob,
+})
+
+test('npm help-search', t => {
+ globRoot = t.testdir(globDir)
+ t.teardown(() => {
+ OUTPUT.length = 0
+ globRoot = null
+ })
+
+ return helpSearch(['exec'], (err) => {
+ if (err)
+ throw err
+
+ t.match(OUTPUT, /Top hits for/, 'outputs results')
+ t.match(OUTPUT, /Did you mean this\?\n\s+exec/, 'matched command, so suggest it')
+ t.end()
+ })
+})
+
+test('npm help-search multiple terms', t => {
+ globRoot = t.testdir(globDir)
+ t.teardown(() => {
+ OUTPUT.length = 0
+ globRoot = null
+ })
+
+ return helpSearch(['run', 'script'], (err) => {
+ if (err)
+ throw err
+
+ t.match(OUTPUT, /Top hits for/, 'outputs results')
+ t.match(OUTPUT, /run:\d+ script:\d+/, 'shows hit counts for both terms')
+ t.end()
+ })
+})
+
+test('npm help-search single result prints full section', t => {
+ globRoot = t.testdir(globDir)
+ t.teardown(() => {
+ OUTPUT.length = 0
+ npmHelpArgs = null
+ globRoot = null
+ })
+
+ return helpSearch(['does not exist in'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(npmHelpArgs, ['npm-install'], 'identified the correct man page and called help with it')
+ t.end()
+ })
+})
+
+test('npm help-search single result propagates error', t => {
+ globRoot = t.testdir(globDir)
+ npmHelpErr = new Error('help broke')
+ t.teardown(() => {
+ OUTPUT.length = 0
+ npmHelpArgs = null
+ npmHelpErr = null
+ globRoot = null
+ })
+
+ return helpSearch(['does not exist in'], (err) => {
+ t.strictSame(npmHelpArgs, ['npm-install'], 'identified the correct man page and called help with it')
+ t.match(err, /help broke/, 'propagated the error from help')
+ t.end()
+ })
+})
+
+test('npm help-search long output', t => {
+ globRoot = t.testdir(globDir)
+ npm.flatOptions.long = true
+ t.teardown(() => {
+ OUTPUT.length = 0
+ npm.flatOptions.long = false
+ globRoot = null
+ })
+
+ return helpSearch(['exec'], (err) => {
+ if (err)
+ throw err
+
+ t.match(OUTPUT, /has multiple lines of exec help/, 'outputs detailed results')
+ t.end()
+ })
+})
+
+test('npm help-search long output with color', t => {
+ globRoot = t.testdir(globDir)
+ npm.flatOptions.long = true
+ npm.color = true
+ t.teardown(() => {
+ OUTPUT.length = 0
+ npm.flatOptions.long = false
+ npm.color = false
+ globRoot = null
+ })
+
+ return helpSearch(['help-search'], (err) => {
+ if (err)
+ throw err
+
+ const highlightedText = ansicolors.bgBlack(ansicolors.red('help-search'))
+ t.equal(OUTPUT.some((line) => line.includes(highlightedText)), true, 'returned highlighted search terms')
+ t.end()
+ })
+})
+
+test('npm help-search no args', t => {
+ return helpSearch([], (err) => {
+ t.match(err, /npm help-search/, 'throws usage')
+ t.end()
+ })
+})
+
+test('npm help-search no matches', t => {
+ globRoot = t.testdir(globDir)
+ t.teardown(() => {
+ OUTPUT.length = 0
+ npmUsageArg = null
+ globRoot = null
+ })
+
+ return helpSearch(['asdfasdf'], (err) => {
+ if (err)
+ throw err
+
+ t.equal(npmUsageArg, false, 'called npmUsage for no matches')
+ t.end()
+ })
+})
diff --git a/deps/npm/test/lib/help.js b/deps/npm/test/lib/help.js
new file mode 100644
index 0000000000..17018acc61
--- /dev/null
+++ b/deps/npm/test/lib/help.js
@@ -0,0 +1,362 @@
+const { test } = require('tap')
+const requireInject = require('require-inject')
+const { EventEmitter } = require('events')
+
+let npmUsageArg = null
+const npmUsage = (arg) => {
+ npmUsageArg = arg
+}
+
+const npmConfig = {
+ usage: false,
+ viewer: undefined,
+ loglevel: undefined,
+}
+
+let helpSearchArgs = null
+const npm = {
+ config: {
+ get: (key) => npmConfig[key],
+ set: (key, value) => {
+ npmConfig[key] = value
+ },
+ parsedArgv: {
+ cooked: [],
+ },
+ },
+ commands: {
+ 'help-search': (args, cb) => {
+ helpSearchArgs = args
+ return cb()
+ },
+ help: {
+ usage: 'npm help <term>',
+ },
+ },
+ deref: (cmd) => {},
+}
+
+const OUTPUT = []
+const output = (msg) => {
+ OUTPUT.push(msg)
+}
+
+const globDefaults = [
+ '/root/man/man1/npm-whoami.1',
+ '/root/man/man5/npmrc.5',
+ '/root/man/man7/disputes.7',
+]
+
+let globErr = null
+let globResult = globDefaults
+const glob = (p, cb) => {
+ return cb(globErr, globResult)
+}
+
+let spawnBin = null
+let spawnArgs = null
+const spawn = (bin, args) => {
+ spawnBin = bin
+ spawnArgs = args
+ const spawnEmitter = new EventEmitter()
+ process.nextTick(() => {
+ spawnEmitter.emit('close', 0)
+ })
+ return spawnEmitter
+}
+
+let openUrlArg = null
+const openUrl = (url, msg, cb) => {
+ openUrlArg = url
+ return cb()
+}
+
+const help = requireInject('../../lib/help.js', {
+ '../../lib/npm.js': npm,
+ '../../lib/utils/npm-usage.js': npmUsage,
+ '../../lib/utils/open-url.js': openUrl,
+ '../../lib/utils/output.js': output,
+ '../../lib/utils/spawn.js': spawn,
+ glob,
+})
+
+test('npm help', t => {
+ t.teardown(() => {
+ npmUsageArg = null
+ })
+
+ return help([], (err) => {
+ if (err)
+ throw err
+
+ t.equal(npmUsageArg, false, 'called npmUsage')
+ t.end()
+ })
+})
+
+test('npm help completion', async t => {
+ t.teardown(() => {
+ globErr = null
+ })
+ const completion = (opts) => new Promise((resolve, reject) => {
+ help.completion(opts, (err, res) => {
+ if (err)
+ return reject(err)
+ return resolve(res)
+ })
+ })
+
+ const noArgs = await completion({ conf: { argv: { remain: [] } } })
+ t.strictSame(noArgs, ['help', 'whoami', 'npmrc', 'disputes'], 'outputs available help pages')
+ const threeArgs = await completion({ conf: { argv: { remain: ['one', 'two', 'three'] } } })
+ t.strictSame(threeArgs, [], 'outputs no results when more than 2 args are provided')
+ globErr = new Error('glob failed')
+ t.rejects(completion({ conf: { argv: { remain: [] } } }), /glob failed/, 'glob errors propagate')
+})
+
+test('npm help -h', t => {
+ npmConfig.usage = true
+ t.teardown(() => {
+ npmConfig.usage = false
+ OUTPUT.length = 0
+ })
+
+ return help(['help'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(OUTPUT, ['npm help <term>'], 'outputs usage information for command')
+ t.end()
+ })
+})
+
+test('npm help multiple args calls search', t => {
+ t.teardown(() => {
+ helpSearchArgs = null
+ })
+
+ return help(['run', 'script'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(helpSearchArgs, ['run', 'script'], 'passed the args to help-search')
+ t.end()
+ })
+})
+
+test('npm help no matches calls search', t => {
+ globResult = []
+ t.teardown(() => {
+ helpSearchArgs = null
+ globResult = globDefaults
+ })
+
+ return help(['asdfasdf'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(helpSearchArgs, ['asdfasdf'], 'passed the args to help-search')
+ t.end()
+ })
+})
+
+test('npm help glob errors propagate', t => {
+ globErr = new Error('glob failed')
+ t.teardown(() => {
+ globErr = null
+ spawnBin = null
+ spawnArgs = null
+ })
+
+ return help(['whoami'], (err) => {
+ t.match(err, /glob failed/, 'glob error propagates')
+ t.end()
+ })
+})
+
+test('npm help whoami', t => {
+ globResult = ['/root/man/man1/npm-whoami.1.xz']
+ t.teardown(() => {
+ globResult = globDefaults
+ spawnBin = null
+ spawnArgs = null
+ })
+
+ return help(['whoami'], (err) => {
+ if (err)
+ throw err
+
+ t.equal(spawnBin, 'man', 'calls man by default')
+ t.strictSame(spawnArgs, ['1', 'npm-whoami'], 'passes the correct arguments')
+ t.end()
+ })
+})
+
+test('npm help 1 install', t => {
+ npmConfig.viewer = 'browser'
+ globResult = [
+ '/root/man/man5/install.5',
+ '/root/man/man1/npm-install.1',
+ ]
+
+ t.teardown(() => {
+ npmConfig.viewer = undefined
+ globResult = globDefaults
+ spawnBin = null
+ spawnArgs = null
+ })
+
+ return help(['1', 'install'], (err) => {
+ if (err)
+ throw err
+
+ t.match(openUrlArg, /commands(\/|\\)npm-install.html$/, 'attempts to open the correct url')
+ t.end()
+ })
+})
+
+test('npm help 5 install', t => {
+ npmConfig.viewer = 'browser'
+ globResult = [
+ '/root/man/man5/install.5',
+ '/root/man/man1/npm-install.1',
+ ]
+
+ t.teardown(() => {
+ npmConfig.viewer = undefined
+ globResult = globDefaults
+ spawnBin = null
+ spawnArgs = null
+ })
+
+ return help(['5', 'install'], (err) => {
+ if (err)
+ throw err
+
+ t.match(openUrlArg, /configuring-npm(\/|\\)install.html$/, 'attempts to open the correct url')
+ t.end()
+ })
+})
+
+test('npm help 7 config', t => {
+ npmConfig.viewer = 'browser'
+ globResult = [
+ '/root/man/man1/npm-config.1',
+ '/root/man/man7/config.7',
+ ]
+ t.teardown(() => {
+ npmConfig.viewer = undefined
+ globResult = globDefaults
+ spawnBin = null
+ spawnArgs = null
+ })
+
+ return help(['7', 'config'], (err) => {
+ if (err)
+ throw err
+
+ t.match(openUrlArg, /using-npm(\/|\\)config.html$/, 'attempts to open the correct url')
+ t.end()
+ })
+})
+
+test('npm help with browser viewer and invalid section throws', t => {
+ npmConfig.viewer = 'browser'
+ globResult = [
+ '/root/man/man1/npm-config.1',
+ '/root/man/man7/config.7',
+ '/root/man/man9/config.9',
+ ]
+ t.teardown(() => {
+ npmConfig.viewer = undefined
+ globResult = globDefaults
+ spawnBin = null
+ spawnArgs = null
+ })
+
+ return help(['9', 'config'], (err) => {
+ t.match(err, /invalid man section: 9/, 'throws appropriate error')
+ t.end()
+ })
+})
+
+test('npm help global redirects to folders', t => {
+ globResult = ['/root/man/man5/folders.5']
+ t.teardown(() => {
+ globResult = globDefaults
+ spawnBin = null
+ spawnArgs = null
+ })
+
+ return help(['global'], (err) => {
+ if (err)
+ throw err
+
+ t.equal(spawnBin, 'man', 'calls man by default')
+ t.strictSame(spawnArgs, ['5', 'folders'], 'passes the correct arguments')
+ t.end()
+ })
+})
+
+test('npm help package.json redirects to package-json', t => {
+ globResult = ['/root/man/man5/package-json.5']
+ t.teardown(() => {
+ globResult = globDefaults
+ spawnBin = null
+ spawnArgs = null
+ })
+
+ return help(['package.json'], (err) => {
+ if (err)
+ throw err
+
+ t.equal(spawnBin, 'man', 'calls man by default')
+ t.strictSame(spawnArgs, ['5', 'package-json'], 'passes the correct arguments')
+ t.end()
+ })
+})
+
+test('npm help ?(un)star', t => {
+ npmConfig.viewer = 'woman'
+ globResult = [
+ '/root/man/man1/npm-star.1',
+ '/root/man/man1/npm-unstar.1',
+ ]
+ t.teardown(() => {
+ npmConfig.viewer = undefined
+ globResult = globDefaults
+ spawnBin = null
+ spawnArgs = null
+ })
+
+ return help(['?(un)star'], (err) => {
+ if (err)
+ throw err
+
+ t.equal(spawnBin, 'emacsclient', 'maps woman to emacs correctly')
+ t.strictSame(spawnArgs, ['-e', `(woman-find-file '/root/man/man1/npm-unstar.1')`], 'passes the correct arguments')
+ t.end()
+ })
+})
+
+test('npm help un*', t => {
+ globResult = [
+ '/root/man/man1/npm-unstar.1',
+ '/root/man/man1/npm-uninstall.1',
+ '/root/man/man1/npm-unpublish.1',
+ ]
+ t.teardown(() => {
+ globResult = globDefaults
+ spawnBin = null
+ spawnArgs = null
+ })
+
+ return help(['un*'], (err) => {
+ if (err)
+ throw err
+
+ t.equal(spawnBin, 'man', 'calls man by default')
+ t.strictSame(spawnArgs, ['1', 'npm-unstar'], 'passes the correct arguments')
+ t.end()
+ })
+})
diff --git a/deps/npm/test/lib/hook.js b/deps/npm/test/lib/hook.js
new file mode 100644
index 0000000000..3599042021
--- /dev/null
+++ b/deps/npm/test/lib/hook.js
@@ -0,0 +1,589 @@
+const { test } = require('tap')
+const requireInject = require('require-inject')
+
+const npm = {
+ flatOptions: {
+ json: false,
+ parseable: false,
+ silent: false,
+ loglevel: 'info',
+ unicode: false,
+ },
+}
+
+const pkgTypes = {
+ semver: 'package',
+ '@npmcli': 'scope',
+ npm: 'owner',
+}
+
+const now = Date.now()
+let hookResponse = null
+let hookArgs = null
+const libnpmhook = {
+ add: async (pkg, uri, secret, opts) => {
+ hookArgs = { pkg, uri, secret, opts }
+ return { id: 1, name: pkg.replace(/^@/, ''), type: pkgTypes[pkg], endpoint: uri }
+ },
+ ls: async (opts) => {
+ hookArgs = opts
+ let id = 0
+ if (hookResponse)
+ return hookResponse
+
+ return Object.keys(pkgTypes).map((name) => ({
+ id: ++id,
+ name: name.replace(/^@/, ''),
+ type: pkgTypes[name],
+ endpoint: 'https://google.com',
+ last_delivery: id % 2 === 0 ? now : undefined,
+ }))
+ },
+ rm: async (id, opts) => {
+ hookArgs = { id, opts }
+ const pkg = Object.keys(pkgTypes)[0]
+ return { id: 1, name: pkg.replace(/^@/, ''), type: pkgTypes[pkg], endpoint: 'https://google.com' }
+ },
+ update: async (id, uri, secret, opts) => {
+ hookArgs = { id, uri, secret, opts }
+ const pkg = Object.keys(pkgTypes)[0]
+ return { id, name: pkg.replace(/^@/, ''), type: pkgTypes[pkg], endpoint: uri }
+ },
+}
+
+const output = []
+const hook = requireInject('../../lib/hook.js', {
+ '../../lib/npm.js': npm,
+ '../../lib/utils/otplease.js': async (opts, fn) => fn(opts),
+ '../../lib/utils/output.js': (msg) => {
+ output.push(msg)
+ },
+ libnpmhook,
+})
+
+test('npm hook no args', t => {
+ return hook([], (err) => {
+ t.match(err, /npm hook add/, 'throws usage with no arguments')
+ t.end()
+ })
+})
+
+test('npm hook add', t => {
+ t.teardown(() => {
+ hookArgs = null
+ output.length = 0
+ })
+
+ return hook(['add', 'semver', 'https://google.com', 'some-secret'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(hookArgs, {
+ pkg: 'semver',
+ uri: 'https://google.com',
+ secret: 'some-secret',
+ opts: npm.flatOptions,
+ }, 'provided the correct arguments to libnpmhook')
+ t.strictSame(output, ['+ semver -> https://google.com'], 'prints the correct output')
+ t.end()
+ })
+})
+
+test('npm hook add - unicode output', t => {
+ npm.flatOptions.unicode = true
+ t.teardown(() => {
+ npm.flatOptions.unicode = false
+ hookArgs = null
+ output.length = 0
+ })
+
+ return hook(['add', 'semver', 'https://google.com', 'some-secret'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(hookArgs, {
+ pkg: 'semver',
+ uri: 'https://google.com',
+ secret: 'some-secret',
+ opts: npm.flatOptions,
+ }, 'provided the correct arguments to libnpmhook')
+ t.strictSame(output, ['+ semver ➜ https://google.com'], 'prints the correct output')
+ t.end()
+ })
+})
+
+test('npm hook add - json output', t => {
+ npm.flatOptions.json = true
+ t.teardown(() => {
+ npm.flatOptions.json = false
+ hookArgs = null
+ output.length = 0
+ })
+
+ return hook(['add', '@npmcli', 'https://google.com', 'some-secret'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(hookArgs, {
+ pkg: '@npmcli',
+ uri: 'https://google.com',
+ secret: 'some-secret',
+ opts: npm.flatOptions,
+ }, 'provided the correct arguments to libnpmhook')
+ t.strictSame(JSON.parse(output[0]), {
+ id: 1,
+ name: 'npmcli',
+ endpoint: 'https://google.com',
+ type: 'scope',
+ }, 'prints the correct json output')
+ t.end()
+ })
+})
+
+test('npm hook add - parseable output', t => {
+ npm.flatOptions.parseable = true
+ t.teardown(() => {
+ npm.flatOptions.parseable = false
+ hookArgs = null
+ output.length = 0
+ })
+
+ return hook(['add', '@npmcli', 'https://google.com', 'some-secret'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(hookArgs, {
+ pkg: '@npmcli',
+ uri: 'https://google.com',
+ secret: 'some-secret',
+ opts: npm.flatOptions,
+ }, 'provided the correct arguments to libnpmhook')
+ t.strictSame(output[0].split(/\t/), [
+ 'id', 'name', 'type', 'endpoint',
+ ], 'prints the correct parseable output headers')
+ t.strictSame(output[1].split(/\t/), [
+ '1', 'npmcli', 'scope', 'https://google.com',
+ ], 'prints the correct parseable values')
+ t.end()
+ })
+})
+
+test('npm hook add - silent output', t => {
+ npm.flatOptions.silent = true
+ t.teardown(() => {
+ npm.flatOptions.silent = false
+ hookArgs = null
+ output.length = 0
+ })
+
+ return hook(['add', '@npmcli', 'https://google.com', 'some-secret'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(hookArgs, {
+ pkg: '@npmcli',
+ uri: 'https://google.com',
+ secret: 'some-secret',
+ opts: npm.flatOptions,
+ }, 'provided the correct arguments to libnpmhook')
+ t.strictSame(output, [], 'printed no output')
+ t.end()
+ })
+})
+
+test('npm hook ls', t => {
+ t.teardown(() => {
+ hookArgs = null
+ output.length = 0
+ })
+
+ return hook(['ls'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(hookArgs, {
+ ...npm.flatOptions,
+ package: undefined,
+ }, 'received the correct arguments')
+ t.equal(output[0], 'You have 3 hooks configured.', 'prints the correct header')
+ const out = require('../../lib/utils/ansi-trim')(output[1])
+ t.match(out, /semver.*https:\/\/google.com.*\n.*\n.*never triggered/, 'prints package hook')
+ t.match(out, /@npmcli.*https:\/\/google.com.*\n.*\n.*triggered just now/, 'prints scope hook')
+ t.match(out, /~npm.*https:\/\/google.com.*\n.*\n.*never triggered/, 'prints owner hook')
+ t.end()
+ })
+})
+
+test('npm hook ls, no results', t => {
+ hookResponse = []
+ t.teardown(() => {
+ hookResponse = null
+ hookArgs = null
+ output.length = 0
+ })
+
+ return hook(['ls'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(hookArgs, {
+ ...npm.flatOptions,
+ package: undefined,
+ }, 'received the correct arguments')
+ t.equal(output[0], 'You don\'t have any hooks configured yet.', 'prints the correct result')
+ t.end()
+ })
+})
+
+test('npm hook ls, single result', t => {
+ hookResponse = [{
+ id: 1,
+ name: 'semver',
+ type: 'package',
+ endpoint: 'https://google.com',
+ }]
+
+ t.teardown(() => {
+ hookResponse = null
+ hookArgs = null
+ output.length = 0
+ })
+
+ return hook(['ls'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(hookArgs, {
+ ...npm.flatOptions,
+ package: undefined,
+ }, 'received the correct arguments')
+ t.equal(output[0], 'You have one hook configured.', 'prints the correct header')
+ const out = require('../../lib/utils/ansi-trim')(output[1])
+ t.match(out, /semver.*https:\/\/google.com.*\n.*\n.*never triggered/, 'prints package hook')
+ t.end()
+ })
+})
+
+test('npm hook ls - json output', t => {
+ npm.flatOptions.json = true
+ t.teardown(() => {
+ npm.flatOptions.json = false
+ hookArgs = null
+ output.length = 0
+ })
+
+ return hook(['ls'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(hookArgs, {
+ ...npm.flatOptions,
+ package: undefined,
+ }, 'received the correct arguments')
+ const out = JSON.parse(output[0])
+ t.match(out, [{
+ id: 1,
+ name: 'semver',
+ type: 'package',
+ endpoint: 'https://google.com',
+ }, {
+ id: 2,
+ name: 'npmcli',
+ type: 'scope',
+ endpoint: 'https://google.com',
+ }, {
+ id: 3,
+ name: 'npm',
+ type: 'owner',
+ endpoint: 'https://google.com',
+ }], 'prints the correct output')
+ t.end()
+ })
+})
+
+test('npm hook ls - parseable output', t => {
+ npm.flatOptions.parseable = true
+ t.teardown(() => {
+ npm.flatOptions.parseable = false
+ hookArgs = null
+ output.length = 0
+ })
+
+ return hook(['ls'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(hookArgs, {
+ ...npm.flatOptions,
+ package: undefined,
+ }, 'received the correct arguments')
+ t.strictSame(output.map(line => line.split(/\t/)), [
+ ['id', 'name', 'type', 'endpoint', 'last_delivery'],
+ ['1', 'semver', 'package', 'https://google.com', ''],
+ ['2', 'npmcli', 'scope', 'https://google.com', `${now}`],
+ ['3', 'npm', 'owner', 'https://google.com', ''],
+ ], 'prints the correct result')
+ t.end()
+ })
+})
+
+test('npm hook ls - silent output', t => {
+ npm.flatOptions.silent = true
+ t.teardown(() => {
+ npm.flatOptions.silent = false
+ hookArgs = null
+ output.length = 0
+ })
+
+ return hook(['ls'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(hookArgs, {
+ ...npm.flatOptions,
+ package: undefined,
+ }, 'received the correct arguments')
+ t.strictSame(output, [], 'printed no output')
+ t.end()
+ })
+})
+
+test('npm hook rm', t => {
+ t.teardown(() => {
+ hookArgs = null
+ output.length = 0
+ })
+
+ return hook(['rm', '1'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(hookArgs, {
+ id: '1',
+ opts: npm.flatOptions,
+ }, 'received the correct arguments')
+ t.strictSame(output, [
+ '- semver X https://google.com',
+ ], 'printed the correct output')
+ t.end()
+ })
+})
+
+test('npm hook rm - unicode output', t => {
+ npm.flatOptions.unicode = true
+ t.teardown(() => {
+ npm.flatOptions.unicode = false
+ hookArgs = null
+ output.length = 0
+ })
+
+ return hook(['rm', '1'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(hookArgs, {
+ id: '1',
+ opts: npm.flatOptions,
+ }, 'received the correct arguments')
+ t.strictSame(output, [
+ '- semver ✘ https://google.com',
+ ], 'printed the correct output')
+ t.end()
+ })
+})
+
+test('npm hook rm - silent output', t => {
+ npm.flatOptions.silent = true
+ t.teardown(() => {
+ npm.flatOptions.silent = false
+ hookArgs = null
+ output.length = 0
+ })
+
+ return hook(['rm', '1'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(hookArgs, {
+ id: '1',
+ opts: npm.flatOptions,
+ }, 'received the correct arguments')
+ t.strictSame(output, [], 'printed no output')
+ t.end()
+ })
+})
+
+test('npm hook rm - json output', t => {
+ npm.flatOptions.json = true
+ t.teardown(() => {
+ npm.flatOptions.json = false
+ hookArgs = null
+ output.length = 0
+ })
+
+ return hook(['rm', '1'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(hookArgs, {
+ id: '1',
+ opts: npm.flatOptions,
+ }, 'received the correct arguments')
+ t.strictSame(JSON.parse(output[0]), {
+ id: 1,
+ name: 'semver',
+ type: 'package',
+ endpoint: 'https://google.com',
+ }, 'printed correct output')
+ t.end()
+ })
+})
+
+test('npm hook rm - parseable output', t => {
+ npm.flatOptions.parseable = true
+ t.teardown(() => {
+ npm.flatOptions.parseable = false
+ hookArgs = null
+ output.length = 0
+ })
+
+ return hook(['rm', '1'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(hookArgs, {
+ id: '1',
+ opts: npm.flatOptions,
+ }, 'received the correct arguments')
+ t.strictSame(output.map(line => line.split(/\t/)), [
+ ['id', 'name', 'type', 'endpoint'],
+ ['1', 'semver', 'package', 'https://google.com'],
+ ], 'printed correct output')
+ t.end()
+ })
+})
+
+test('npm hook update', t => {
+ t.teardown(() => {
+ hookArgs = null
+ output.length = 0
+ })
+
+ return hook(['update', '1', 'https://google.com', 'some-secret'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(hookArgs, {
+ id: '1',
+ uri: 'https://google.com',
+ secret: 'some-secret',
+ opts: npm.flatOptions,
+ }, 'received the correct arguments')
+ t.strictSame(output, [
+ '+ semver -> https://google.com',
+ ], 'printed the correct output')
+ t.end()
+ })
+})
+
+test('npm hook update - unicode', t => {
+ npm.flatOptions.unicode = true
+ t.teardown(() => {
+ npm.flatOptions.unicode = false
+ hookArgs = null
+ output.length = 0
+ })
+
+ return hook(['update', '1', 'https://google.com', 'some-secret'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(hookArgs, {
+ id: '1',
+ uri: 'https://google.com',
+ secret: 'some-secret',
+ opts: npm.flatOptions,
+ }, 'received the correct arguments')
+ t.strictSame(output, [
+ '+ semver ➜ https://google.com',
+ ], 'printed the correct output')
+ t.end()
+ })
+})
+
+test('npm hook update - json output', t => {
+ npm.flatOptions.json = true
+ t.teardown(() => {
+ npm.flatOptions.json = false
+ hookArgs = null
+ output.length = 0
+ })
+
+ return hook(['update', '1', 'https://google.com', 'some-secret'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(hookArgs, {
+ id: '1',
+ uri: 'https://google.com',
+ secret: 'some-secret',
+ opts: npm.flatOptions,
+ }, 'received the correct arguments')
+ t.strictSame(JSON.parse(output[0]), {
+ id: '1',
+ name: 'semver',
+ type: 'package',
+ endpoint: 'https://google.com',
+ }, 'printed the correct output')
+ t.end()
+ })
+})
+
+test('npm hook update - parseable output', t => {
+ npm.flatOptions.parseable = true
+ t.teardown(() => {
+ npm.flatOptions.parseable = false
+ hookArgs = null
+ output.length = 0
+ })
+
+ return hook(['update', '1', 'https://google.com', 'some-secret'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(hookArgs, {
+ id: '1',
+ uri: 'https://google.com',
+ secret: 'some-secret',
+ opts: npm.flatOptions,
+ }, 'received the correct arguments')
+ t.strictSame(output.map(line => line.split(/\t/)), [
+ ['id', 'name', 'type', 'endpoint'],
+ ['1', 'semver', 'package', 'https://google.com'],
+ ], 'printed the correct output')
+ t.end()
+ })
+})
+
+test('npm hook update - silent output', t => {
+ npm.flatOptions.silent = true
+ t.teardown(() => {
+ npm.flatOptions.silent = false
+ hookArgs = null
+ output.length = 0
+ })
+
+ return hook(['update', '1', 'https://google.com', 'some-secret'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(hookArgs, {
+ id: '1',
+ uri: 'https://google.com',
+ secret: 'some-secret',
+ opts: npm.flatOptions,
+ }, 'received the correct arguments')
+ t.strictSame(output, [], 'printed no output')
+ t.end()
+ })
+})
diff --git a/deps/npm/test/lib/org.js b/deps/npm/test/lib/org.js
new file mode 100644
index 0000000000..68e3c9f0d6
--- /dev/null
+++ b/deps/npm/test/lib/org.js
@@ -0,0 +1,585 @@
+const { test } = require('tap')
+const requireInject = require('require-inject')
+const ansiTrim = require('../../lib/utils/ansi-trim.js')
+
+const npm = {
+ flatOptions: {
+ json: false,
+ parseable: false,
+ silent: false,
+ loglevel: 'info',
+ },
+}
+
+const output = []
+
+let orgSize = 1
+let orgSetArgs = null
+let orgRmArgs = null
+let orgLsArgs = null
+let orgList = {}
+const libnpmorg = {
+ set: async (org, user, role, opts) => {
+ orgSetArgs = { org, user, role, opts }
+ return {
+ org: {
+ name: org,
+ size: orgSize,
+ },
+ user,
+ role,
+ }
+ },
+ rm: async (org, user, opts) => {
+ orgRmArgs = { org, user, opts }
+ },
+ ls: async (org, opts) => {
+ orgLsArgs = { org, opts }
+ return orgList
+ },
+}
+
+const org = requireInject('../../lib/org.js', {
+ '../../lib/npm.js': npm,
+ '../../lib/utils/otplease.js': async (opts, fn) => fn(opts),
+ '../../lib/utils/output.js': (msg) => {
+ output.push(msg)
+ },
+ libnpmorg,
+})
+
+test('completion', async t => {
+ const completion = (argv) => new Promise((resolve, reject) => {
+ org.completion({ conf: { argv: { remain: argv } } }, (err, res) => {
+ if (err)
+ return reject(err)
+ return resolve(res)
+ })
+ })
+
+ const assertions = [
+ [['npm', 'org'], ['set', 'rm', 'ls']],
+ [['npm', 'org', 'ls'], []],
+ [['npm', 'org', 'add'], []],
+ [['npm', 'org', 'rm'], []],
+ [['npm', 'org', 'set'], []],
+ ]
+
+ for (const [argv, expected] of assertions)
+ t.strictSame(await completion(argv), expected, `completion for: ${argv.join(', ')}`)
+
+ t.rejects(completion(['npm', 'org', 'flurb']), /flurb not recognized/, 'errors for unknown subcommand')
+})
+
+test('npm org - invalid subcommand', t => {
+ return org(['foo'], (err) => {
+ t.match(err, /npm org set/, 'prints usage information')
+ t.end()
+ })
+})
+
+test('npm org add', t => {
+ t.teardown(() => {
+ orgSetArgs = null
+ output.length = 0
+ })
+
+ return org(['add', 'orgname', 'username'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(orgSetArgs, {
+ org: 'orgname',
+ user: 'username',
+ role: 'developer',
+ opts: npm.flatOptions,
+ }, 'received the correct arguments')
+ t.equal(output[0], 'Added username as developer to orgname. You now have 1 member in this org.', 'printed the correct output')
+ t.end()
+ })
+})
+
+test('npm org add - no org', t => {
+ t.teardown(() => {
+ orgSetArgs = null
+ output.length = 0
+ })
+
+ return org(['add', '', 'username'], (err) => {
+ t.match(err, /`orgname` is required/, 'returns the correct error')
+ t.end()
+ })
+})
+
+test('npm org add - no user', t => {
+ t.teardown(() => {
+ orgSetArgs = null
+ output.length = 0
+ })
+
+ return org(['add', 'orgname', ''], (err) => {
+ t.match(err, /`username` is required/, 'returns the correct error')
+ t.end()
+ })
+})
+
+test('npm org add - invalid role', t => {
+ t.teardown(() => {
+ orgSetArgs = null
+ output.length = 0
+ })
+
+ return org(['add', 'orgname', 'username', 'person'], (err) => {
+ t.match(err, /`role` must be one of/, 'returns the correct error')
+ t.end()
+ })
+})
+
+test('npm org add - more users', t => {
+ orgSize = 5
+ t.teardown(() => {
+ orgSize = 1
+ orgSetArgs = null
+ output.length = 0
+ })
+
+ return org(['add', 'orgname', 'username'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(orgSetArgs, {
+ org: 'orgname',
+ user: 'username',
+ role: 'developer',
+ opts: npm.flatOptions,
+ }, 'received the correct arguments')
+ t.equal(output[0], 'Added username as developer to orgname. You now have 5 members in this org.', 'printed the correct output')
+ t.end()
+ })
+})
+
+test('npm org add - json output', t => {
+ npm.flatOptions.json = true
+ t.teardown(() => {
+ npm.flatOptions.json = false
+ orgSetArgs = null
+ output.length = 0
+ })
+
+ return org(['add', 'orgname', 'username'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(orgSetArgs, {
+ org: 'orgname',
+ user: 'username',
+ role: 'developer',
+ opts: npm.flatOptions,
+ }, 'received the correct arguments')
+ t.strictSame(JSON.parse(output[0]), {
+ org: {
+ name: 'orgname',
+ size: 1,
+ },
+ user: 'username',
+ role: 'developer',
+ }, 'printed the correct output')
+ t.end()
+ })
+})
+
+test('npm org add - parseable output', t => {
+ npm.flatOptions.parseable = true
+ t.teardown(() => {
+ npm.flatOptions.parseable = false
+ orgSetArgs = null
+ output.length = 0
+ })
+
+ return org(['add', 'orgname', 'username'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(orgSetArgs, {
+ org: 'orgname',
+ user: 'username',
+ role: 'developer',
+ opts: npm.flatOptions,
+ }, 'received the correct arguments')
+ t.strictSame(output.map(line => line.split(/\t/)), [
+ ['org', 'orgsize', 'user', 'role'],
+ ['orgname', '1', 'username', 'developer'],
+ ], 'printed the correct output')
+ t.end()
+ })
+})
+
+test('npm org add - silent output', t => {
+ npm.flatOptions.silent = true
+ t.teardown(() => {
+ npm.flatOptions.silent = false
+ orgSetArgs = null
+ output.length = 0
+ })
+
+ return org(['add', 'orgname', 'username'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(orgSetArgs, {
+ org: 'orgname',
+ user: 'username',
+ role: 'developer',
+ opts: npm.flatOptions,
+ }, 'received the correct arguments')
+ t.strictSame(output, [], 'prints no output')
+ t.end()
+ })
+})
+
+test('npm org rm', t => {
+ t.teardown(() => {
+ orgRmArgs = null
+ orgLsArgs = null
+ output.length = 0
+ })
+
+ return org(['rm', 'orgname', 'username'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(orgRmArgs, {
+ org: 'orgname',
+ user: 'username',
+ opts: npm.flatOptions,
+ }, 'libnpmorg.rm received the correct args')
+ t.strictSame(orgLsArgs, {
+ org: 'orgname',
+ opts: npm.flatOptions,
+ }, 'libnpmorg.ls received the correct args')
+ t.equal(output[0], 'Successfully removed username from orgname. You now have 0 members in this org.', 'printed the correct output')
+ t.end()
+ })
+})
+
+test('npm org rm - no org', t => {
+ t.teardown(() => {
+ orgRmArgs = null
+ orgLsArgs = null
+ output.length = 0
+ })
+
+ return org(['rm', '', 'username'], (err) => {
+ t.match(err, /`orgname` is required/, 'threw the correct error')
+ t.end()
+ })
+})
+
+test('npm org rm - no user', t => {
+ t.teardown(() => {
+ orgRmArgs = null
+ orgLsArgs = null
+ output.length = 0
+ })
+
+ return org(['rm', 'orgname'], (err) => {
+ t.match(err, /`username` is required/, 'threw the correct error')
+ t.end()
+ })
+})
+
+test('npm org rm - one user left', t => {
+ orgList = {
+ one: 'developer',
+ }
+
+ t.teardown(() => {
+ orgList = {}
+ orgRmArgs = null
+ orgLsArgs = null
+ output.length = 0
+ })
+
+ return org(['rm', 'orgname', 'username'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(orgRmArgs, {
+ org: 'orgname',
+ user: 'username',
+ opts: npm.flatOptions,
+ }, 'libnpmorg.rm received the correct args')
+ t.strictSame(orgLsArgs, {
+ org: 'orgname',
+ opts: npm.flatOptions,
+ }, 'libnpmorg.ls received the correct args')
+ t.equal(output[0], 'Successfully removed username from orgname. You now have 1 member in this org.', 'printed the correct output')
+ t.end()
+ })
+})
+
+test('npm org rm - json output', t => {
+ npm.flatOptions.json = true
+ t.teardown(() => {
+ npm.flatOptions.json = false
+ orgRmArgs = null
+ orgLsArgs = null
+ output.length = 0
+ })
+
+ return org(['rm', 'orgname', 'username'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(orgRmArgs, {
+ org: 'orgname',
+ user: 'username',
+ opts: npm.flatOptions,
+ }, 'libnpmorg.rm received the correct args')
+ t.strictSame(orgLsArgs, {
+ org: 'orgname',
+ opts: npm.flatOptions,
+ }, 'libnpmorg.ls received the correct args')
+ t.strictSame(JSON.parse(output[0]), {
+ user: 'username',
+ org: 'orgname',
+ userCount: 0,
+ deleted: true,
+ }, 'printed the correct output')
+ t.end()
+ })
+})
+
+test('npm org rm - parseable output', t => {
+ npm.flatOptions.parseable = true
+ t.teardown(() => {
+ npm.flatOptions.parseable = false
+ orgRmArgs = null
+ orgLsArgs = null
+ output.length = 0
+ })
+
+ return org(['rm', 'orgname', 'username'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(orgRmArgs, {
+ org: 'orgname',
+ user: 'username',
+ opts: npm.flatOptions,
+ }, 'libnpmorg.rm received the correct args')
+ t.strictSame(orgLsArgs, {
+ org: 'orgname',
+ opts: npm.flatOptions,
+ }, 'libnpmorg.ls received the correct args')
+ t.strictSame(output.map(line => line.split(/\t/)), [
+ ['user', 'org', 'userCount', 'deleted'],
+ ['username', 'orgname', '0', 'true'],
+ ], 'printed the correct output')
+ t.end()
+ })
+})
+
+test('npm org rm - silent output', t => {
+ npm.flatOptions.silent = true
+ t.teardown(() => {
+ npm.flatOptions.silent = false
+ orgRmArgs = null
+ orgLsArgs = null
+ output.length = 0
+ })
+
+ return org(['rm', 'orgname', 'username'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(orgRmArgs, {
+ org: 'orgname',
+ user: 'username',
+ opts: npm.flatOptions,
+ }, 'libnpmorg.rm received the correct args')
+ t.strictSame(orgLsArgs, {
+ org: 'orgname',
+ opts: npm.flatOptions,
+ }, 'libnpmorg.ls received the correct args')
+ t.strictSame(output, [], 'printed no output')
+ t.end()
+ })
+})
+
+test('npm org ls', t => {
+ orgList = {
+ one: 'developer',
+ two: 'admin',
+ three: 'owner',
+ }
+ t.teardown(() => {
+ orgList = {}
+ orgLsArgs = null
+ output.length = 0
+ })
+
+ return org(['ls', 'orgname'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(orgLsArgs, {
+ org: 'orgname',
+ opts: npm.flatOptions,
+ }, 'receieved the correct args')
+ const out = ansiTrim(output[0])
+ t.match(out, /one.*developer/, 'contains the developer member')
+ t.match(out, /two.*admin/, 'contains the admin member')
+ t.match(out, /three.*owner/, 'contains the owner member')
+ t.end()
+ })
+})
+
+test('npm org ls - user filter', t => {
+ orgList = {
+ username: 'admin',
+ missing: 'admin',
+ }
+ t.teardown(() => {
+ orgList = {}
+ orgLsArgs = null
+ output.length = 0
+ })
+
+ return org(['ls', 'orgname', 'username'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(orgLsArgs, {
+ org: 'orgname',
+ opts: npm.flatOptions,
+ }, 'receieved the correct args')
+ const out = ansiTrim(output[0])
+ t.match(out, /username.*admin/, 'contains the filtered member')
+ t.notMatch(out, /missing.*admin/, 'does not contain other members')
+ t.end()
+ })
+})
+
+test('npm org ls - user filter, missing user', t => {
+ orgList = {
+ missing: 'admin',
+ }
+ t.teardown(() => {
+ orgList = {}
+ orgLsArgs = null
+ output.length = 0
+ })
+
+ return org(['ls', 'orgname', 'username'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(orgLsArgs, {
+ org: 'orgname',
+ opts: npm.flatOptions,
+ }, 'receieved the correct args')
+ const out = ansiTrim(output[0])
+ t.notMatch(out, /username/, 'does not contain the requested member')
+ t.notMatch(out, /missing.*admin/, 'does not contain other members')
+ t.end()
+ })
+})
+
+test('npm org ls - no org', t => {
+ t.teardown(() => {
+ orgLsArgs = null
+ output.length = 0
+ })
+
+ return org(['ls'], (err) => {
+ t.match(err, /`orgname` is required/, 'throws the correct error')
+ t.end()
+ })
+})
+
+test('npm org ls - json output', t => {
+ npm.flatOptions.json = true
+ orgList = {
+ one: 'developer',
+ two: 'admin',
+ three: 'owner',
+ }
+ t.teardown(() => {
+ npm.flatOptions.json = false
+ orgList = {}
+ orgLsArgs = null
+ output.length = 0
+ })
+
+ return org(['ls', 'orgname'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(orgLsArgs, {
+ org: 'orgname',
+ opts: npm.flatOptions,
+ }, 'receieved the correct args')
+ t.strictSame(JSON.parse(output[0]), orgList, 'prints the correct output')
+ t.end()
+ })
+})
+
+test('npm org ls - parseable output', t => {
+ npm.flatOptions.parseable = true
+ orgList = {
+ one: 'developer',
+ two: 'admin',
+ three: 'owner',
+ }
+ t.teardown(() => {
+ npm.flatOptions.parseable = false
+ orgList = {}
+ orgLsArgs = null
+ output.length = 0
+ })
+
+ return org(['ls', 'orgname'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(orgLsArgs, {
+ org: 'orgname',
+ opts: npm.flatOptions,
+ }, 'receieved the correct args')
+ t.strictSame(output.map(line => line.split(/\t/)), [
+ ['user', 'role'],
+ ['one', 'developer'],
+ ['two', 'admin'],
+ ['three', 'owner'],
+ ], 'printed the correct output')
+ t.end()
+ })
+})
+
+test('npm org ls - silent output', t => {
+ npm.flatOptions.silent = true
+ orgList = {
+ one: 'developer',
+ two: 'admin',
+ three: 'owner',
+ }
+ t.teardown(() => {
+ npm.flatOptions.silent = false
+ orgList = {}
+ orgLsArgs = null
+ output.length = 0
+ })
+
+ return org(['ls', 'orgname'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(orgLsArgs, {
+ org: 'orgname',
+ opts: npm.flatOptions,
+ }, 'receieved the correct args')
+ t.strictSame(output, [], 'printed no output')
+ t.end()
+ })
+})
diff --git a/deps/npm/test/lib/rebuild.js b/deps/npm/test/lib/rebuild.js
index dbc37d57af..d9df048d90 100644
--- a/deps/npm/test/lib/rebuild.js
+++ b/deps/npm/test/lib/rebuild.js
@@ -174,8 +174,48 @@ t.test('filter by pkg@<range>', t => {
})
})
-t.test('filter must be a semver version/range', t => {
- rebuild(['b:git+ssh://github.com/npm/arborist'], err => {
+t.test('filter by directory', t => {
+ const path = t.testdir({
+ node_modules: {
+ a: {
+ 'index.js': '',
+ 'package.json': JSON.stringify({
+ name: 'a',
+ version: '1.0.0',
+ bin: 'index.js',
+ }),
+ },
+ b: {
+ 'index.js': '',
+ 'package.json': JSON.stringify({
+ name: 'b',
+ version: '1.0.0',
+ bin: 'index.js',
+ }),
+ },
+ },
+ })
+
+ npm.prefix = path
+
+ const aBinFile = resolve(path, 'node_modules/.bin/a')
+ const bBinFile = resolve(path, 'node_modules/.bin/b')
+ t.throws(() => fs.statSync(aBinFile))
+ t.throws(() => fs.statSync(bBinFile))
+
+ rebuild(['file:node_modules/b'], err => {
+ if (err)
+ throw err
+
+ t.throws(() => fs.statSync(aBinFile), 'should not link a bin')
+ t.ok(() => fs.statSync(bBinFile), 'should link filtered pkg bin')
+
+ t.end()
+ })
+})
+
+t.test('filter must be a semver version/range, or directory', t => {
+ rebuild(['git+ssh://github.com/npm/arborist'], err => {
t.match(
err,
/Error: `npm rebuild` only supports SemVer version\/range specifiers/,
diff --git a/deps/npm/test/lib/set.js b/deps/npm/test/lib/set.js
new file mode 100644
index 0000000000..aeb239e9c4
--- /dev/null
+++ b/deps/npm/test/lib/set.js
@@ -0,0 +1,33 @@
+const { test } = require('tap')
+const requireInject = require('require-inject')
+
+let configArgs = null
+const npm = {
+ commands: {
+ config: (args, cb) => {
+ configArgs = args
+ return cb()
+ },
+ },
+}
+
+const set = requireInject('../../lib/set.js', {
+ '../../lib/npm.js': npm,
+})
+
+test('npm set - no args', t => {
+ return set([], (err) => {
+ t.match(err, /npm set/, 'prints usage')
+ t.end()
+ })
+})
+
+test('npm set', t => {
+ return set(['email', 'me@me.me'], (err) => {
+ if (err)
+ throw err
+
+ t.strictSame(configArgs, ['set', 'email', 'me@me.me'], 'passed the correct arguments to config')
+ t.end()
+ })
+})
diff --git a/deps/npm/test/lib/utils/split-package-names.js b/deps/npm/test/lib/utils/split-package-names.js
new file mode 100644
index 0000000000..c69bb2a3da
--- /dev/null
+++ b/deps/npm/test/lib/utils/split-package-names.js
@@ -0,0 +1,17 @@
+'use strict'
+
+const { test } = require('tap')
+const splitPackageNames = require('../../../lib/utils/split-package-names.js')
+
+test('splitPackageNames', t => {
+ const assertions = [
+ ['semver', 'semver'],
+ ['read-pkg/semver', 'read-pkg/node_modules/semver'],
+ ['@npmcli/one/@npmcli/two', '@npmcli/one/node_modules/@npmcli/two'],
+ ['@npmcli/one/semver', '@npmcli/one/node_modules/semver'],
+ ]
+
+ for (const [input, expected] of assertions)
+ t.equal(splitPackageNames(input), expected, `split ${input} correctly`)
+ t.end()
+})