diff options
86 files changed, 497 insertions, 809 deletions
diff --git a/lib/access.js b/lib/access.js index 8a372d90c..10b1e21e0 100644 --- a/lib/access.js +++ b/lib/access.js @@ -59,17 +59,17 @@ const access = async ([cmd, ...args], cb) => { return fn(args, { ...npm.flatOptions }) } -const completion = function (opts, cb) { - var argv = opts.conf.argv.remain +const completion = async (opts) => { + const argv = opts.conf.argv.remain if (argv.length === 2) - return cb(null, subcommands) + return subcommands switch (argv[2]) { case 'grant': if (argv.length === 3) - return cb(null, ['read-only', 'read-write']) + return ['read-only', 'read-write'] else - return cb(null, []) + return [] case 'public': case 'restricted': @@ -79,9 +79,9 @@ const completion = function (opts, cb) { case '2fa-required': case '2fa-not-required': case 'revoke': - return cb(null, []) + return [] default: - return cb(new Error(argv[2] + ' not recognized')) + throw new Error(argv[2] + ' not recognized') } } diff --git a/lib/adduser.js b/lib/adduser.js index b6c332174..c68c2b80f 100644 --- a/lib/adduser.js +++ b/lib/adduser.js @@ -15,8 +15,6 @@ const usage = usageUtil( 'npm adduser [--registry=url] [--scope=@orgname] [--always-auth]' ) -const completion = require('./utils/completion/none.js') - const cmd = (args, cb) => adduser(args).then(() => cb()).catch(cb) const getRegistry = ({ scope, registry }) => { @@ -74,4 +72,4 @@ const adduser = async (args) => { output(message) } -module.exports = Object.assign(cmd, { completion, usage }) +module.exports = Object.assign(cmd, { usage }) diff --git a/lib/audit.js b/lib/audit.js index cb8ab5b3a..1b31401b1 100644 --- a/lib/audit.js +++ b/lib/audit.js @@ -38,17 +38,17 @@ const usage = usageUtil( '[--force|--package-lock-only|--dry-run|--production|--only=(dev|prod)]' ) -const completion = (opts, cb) => { +const completion = async (opts) => { const argv = opts.conf.argv.remain if (argv.length === 2) - return cb(null, ['fix']) + return ['fix'] switch (argv[2]) { case 'fix': - return cb(null, []) + return [] default: - return cb(new Error(argv[2] + ' not recognized')) + throw new Error(argv[2] + ' not recognized') } } diff --git a/lib/bin.js b/lib/bin.js index 1d776365c..e627ce22f 100644 --- a/lib/bin.js +++ b/lib/bin.js @@ -1,7 +1,6 @@ const npm = require('./npm.js') const output = require('./utils/output.js') const usageUtil = require('./utils/usage.js') -const completion = require('./utils/completion/none.js') const PATH = require('./utils/path.js') const cmd = (args, cb) => bin(args).then(() => cb()).catch(cb) const usage = usageUtil('bin', 'npm bin [-g]') @@ -11,4 +10,4 @@ const bin = async (args, cb) => { if (npm.flatOptions.global && !PATH.includes(b)) console.error('(not in PATH env variable)') } -module.exports = Object.assign(cmd, { usage, completion }) +module.exports = Object.assign(cmd, { usage }) diff --git a/lib/bugs.js b/lib/bugs.js index 012f39efb..09856313c 100644 --- a/lib/bugs.js +++ b/lib/bugs.js @@ -7,7 +7,6 @@ const npm = require('./npm.js') const hostedFromMani = require('./utils/hosted-git-info-from-manifest.js') const usage = usageUtil('bugs', 'npm bugs [<pkgname>]') -const completion = require('./utils/completion/none.js') const cmd = (args, cb) => bugs(args).then(() => cb()).catch(cb) @@ -44,4 +43,4 @@ const getBugs = async pkg => { await openUrl(url, `${mani.name} bug list available at the following URL`) } -module.exports = Object.assign(cmd, { usage, completion }) +module.exports = Object.assign(cmd, { usage }) diff --git a/lib/cache.js b/lib/cache.js index 30d6aef86..7b84353b4 100644 --- a/lib/cache.js +++ b/lib/cache.js @@ -19,17 +19,17 @@ const usage = usageUtil('cache', '\nnpm cache verify' ) -const completion = (opts, cb) => { +const completion = async (opts) => { const argv = opts.conf.argv.remain if (argv.length === 2) - return cb(null, ['add', 'clean', 'verify']) + return ['add', 'clean', 'verify'] // TODO - eventually... switch (argv[2]) { case 'verify': case 'clean': case 'add': - return cb(null, []) + return [] } } @@ -11,7 +11,6 @@ const npm = require('./npm.js') const usageUtil = require('./utils/usage.js') const usage = usageUtil('ci', 'npm ci') -const completion = require('./utils/completion/none.js') const cmd = (args, cb) => ci().then(() => cb()).catch(cb) @@ -76,4 +75,4 @@ const ci = async () => { await reifyFinish(arb) } -module.exports = Object.assign(cmd, { completion, usage }) +module.exports = Object.assign(cmd, {usage}) diff --git a/lib/completion.js b/lib/completion.js index bdea338ff..b31867d98 100644 --- a/lib/completion.js +++ b/lib/completion.js @@ -28,8 +28,6 @@ // one per line for the shell completion method to consume in IFS=$'\n' mode // as an array. // -// TODO: make all the implementation completion methods promise-returning -// instead of callback-taking. const npm = require('./npm.js') const { types, shorthands } = require('./utils/config.js') @@ -52,9 +50,9 @@ const { promisify } = require('util') const cmd = (args, cb) => compl(args).then(() => cb()).catch(cb) // completion for the completion command -const completion = async (opts, cb) => { +const completion = async (opts) => { if (opts.w > 2) - return cb() + return const { resolve } = require('path') const [bashExists, zshExists] = await Promise.all([ @@ -68,7 +66,7 @@ const completion = async (opts, cb) => { if (bashExists) out.push(['>>', '~/.bashrc']) - cb(null, out) + return out } const compl = async args => { @@ -121,18 +119,16 @@ const compl = async args => { raw: args, } - const wrap = getWrap(opts) - if (partialWords.slice(0, -1).indexOf('--') === -1) { if (word.charAt(0) === '-') - return wrap(configCompl(opts)) + return wrap(opts, configCompl(opts)) if (words[w - 1] && words[w - 1].charAt(0) === '-' && !isFlag(words[w - 1])) { // awaiting a value for a non-bool config. // don't even try to do this for now - return wrap(configValueCompl(opts)) + return wrap(opts, configValueCompl(opts)) } } @@ -146,7 +142,7 @@ const compl = async args => { // check if there's a command already. const cmd = parsed.argv.remain[1] if (!cmd) - return wrap(cmdCompl(opts)) + return wrap(opts, cmdCompl(opts)) Object.keys(parsed).forEach(k => npm.config.set(k, parsed[k])) @@ -155,10 +151,8 @@ const compl = async args => { // otherwise, do nothing const impl = npm.commands[cmd] if (impl && impl.completion) { - // XXX promisify all the cmd.completion functions - return await new Promise((res, rej) => { - impl.completion(opts, (er, comps) => er ? rej(er) : res(wrap(comps))) - }) + const comps = await impl.completion(opts) + return wrap(opts, comps) } } @@ -215,7 +209,7 @@ const escape = w => !/\s+/.test(w) ? w // If any of the items are arrays, then join them with a space. // Ie, returning ['a', 'b c', ['d', 'e']] would allow it to expand // to: 'a', 'b c', or 'd' 'e' -const getWrap = opts => compls => { +const wrap = (opts, compls) => { if (!Array.isArray(compls)) compls = compls ? [compls] : [] diff --git a/lib/config.js b/lib/config.js index b32cf3359..e4da296de 100644 --- a/lib/config.js +++ b/lib/config.js @@ -26,7 +26,7 @@ const usage = usageUtil( const cmd = (args, cb) => config(args).then(() => cb()).catch(cb) -const completion = (opts, cb) => { +const completion = async (opts) => { const argv = opts.conf.argv.remain if (argv[1] !== 'config') argv.unshift('config') @@ -36,7 +36,7 @@ const completion = (opts, cb) => { if (opts.partialWord !== 'l') cmds.push('list') - return cb(null, cmds) + return cmds } const action = argv[2] @@ -44,19 +44,19 @@ const completion = (opts, cb) => { case 'set': // todo: complete with valid values, if possible. if (argv.length > 3) - return cb(null, []) + return [] // fallthrough /* eslint no-fallthrough:0 */ case 'get': case 'delete': case 'rm': - return cb(null, Object.keys(types)) + return Object.keys(types) case 'edit': case 'list': case 'ls': default: - return cb(null, []) + return [] } } diff --git a/lib/dedupe.js b/lib/dedupe.js index 5e455192b..2211fcac8 100644 --- a/lib/dedupe.js +++ b/lib/dedupe.js @@ -5,7 +5,6 @@ const usageUtil = require('./utils/usage.js') const reifyFinish = require('./utils/reify-finish.js') const usage = usageUtil('dedupe', 'npm dedupe') -const completion = require('./utils/completion/none.js') const cmd = (args, cb) => dedupe(args).then(() => cb()).catch(cb) @@ -27,4 +26,4 @@ const dedupe = async (args) => { await reifyFinish(arb) } -module.exports = Object.assign(cmd, { usage, completion }) +module.exports = Object.assign(cmd, { usage }) diff --git a/lib/deprecate.js b/lib/deprecate.js index e04998645..42d099b54 100644 --- a/lib/deprecate.js +++ b/lib/deprecate.js @@ -17,19 +17,17 @@ const usage = usageUtil( 'npm deprecate <pkg>[@<version>] <message>' ) -const completion = (opts, cb) => { +const completion = async (opts) => { if (opts.conf.argv.remain.length > 1) - return cb(null, []) + return [] - return getIdentity(npm.flatOptions).then((username) => { - return libaccess.lsPackages(username, npm.flatOptions).then((packages) => { - return Object.keys(packages) - .filter((name) => packages[name] === 'write' && - (opts.conf.argv.remain.length === 0 || - name.startsWith(opts.conf.argv.remain[0])) - ) - }) - }).then((list) => cb(null, list), (err) => cb(err)) + const username = await getIdentity(npm.flatOptions) + const packages = await libaccess.lsPackages(username, npm.flatOptions) + return Object.keys(packages) + .filter((name) => + packages[name] === 'write' && + (opts.conf.argv.remain.length === 0 || + name.startsWith(opts.conf.argv.remain[0]))) } const cmd = (args, cb) => diff --git a/lib/diff.js b/lib/diff.js index af6760106..9ef5a78a2 100644 --- a/lib/diff.js +++ b/lib/diff.js @@ -11,7 +11,6 @@ const pickManifest = require('npm-pick-manifest') const npm = require('./npm.js') const usageUtil = require('./utils/usage.js') const output = require('./utils/output.js') -const completion = require('./utils/completion/none.js') const readLocalPkg = require('./utils/read-local-package.js') const usage = usageUtil( @@ -263,4 +262,4 @@ const findVersionsByPackageName = async (specs) => { }) } -module.exports = Object.assign(cmd, { completion, usage }) +module.exports = Object.assign(cmd, { usage }) diff --git a/lib/dist-tag.js b/lib/dist-tag.js index ae4b33ce8..e958bb754 100644 --- a/lib/dist-tag.js +++ b/lib/dist-tag.js @@ -16,14 +16,14 @@ const usage = usageUtil( '\nnpm dist-tag ls [<pkg>]' ) -const completion = function (opts, cb) { +const completion = async (opts) => { const argv = opts.conf.argv.remain if (argv.length === 2) - return cb(null, ['add', 'rm', 'ls']) + return ['add', 'rm', 'ls'] switch (argv[2]) { default: - return cb() + return [] } } diff --git a/lib/docs.js b/lib/docs.js index b6a3df7f7..fa0adb3d3 100644 --- a/lib/docs.js +++ b/lib/docs.js @@ -7,7 +7,6 @@ const npm = require('./npm.js') const hostedFromMani = require('./utils/hosted-git-info-from-manifest.js') const usage = usageUtil('docs', 'npm docs [<pkgname> [<pkgname> ...]]') -const completion = require('./utils/completion/none.js') const cmd = (args, cb) => docs(args).then(() => cb()).catch(cb) @@ -37,4 +36,4 @@ const getDocs = async pkg => { await openUrl(url, `${mani.name} docs available at the following URL`) } -module.exports = Object.assign(cmd, { usage, completion }) +module.exports = Object.assign(cmd, { usage }) diff --git a/lib/doctor.js b/lib/doctor.js index f42b19fa6..e149aec12 100644 --- a/lib/doctor.js +++ b/lib/doctor.js @@ -4,7 +4,6 @@ const chalk = require('chalk') const ansiTrim = require('./utils/ansi-trim.js') const table = require('text-table') const output = require('./utils/output.js') -const completion = require('./utils/completion/none.js') const usageUtil = require('./utils/usage.js') const usage = usageUtil('doctor', 'npm doctor') const { resolve } = require('path') @@ -285,4 +284,4 @@ const doctor = async args => { throw 'Some problems found. See above for recommendations.' } -module.exports = Object.assign(cmd, { completion, usage }) +module.exports = Object.assign(cmd, { usage }) diff --git a/lib/exec.js b/lib/exec.js index e90ec0866..dab65c23a 100644 --- a/lib/exec.js +++ b/lib/exec.js @@ -21,8 +21,6 @@ const usage = usageUtil('exec', '-c <cmd> --call=<cmd> (may not be mixed with positional arguments)' ) -const completion = require('./utils/completion/installed-shallow.js') - const { promisify } = require('util') const read = promisify(require('read')) @@ -284,4 +282,4 @@ const getHash = packages => .digest('hex') .slice(0, 16) -module.exports = Object.assign(cmd, { completion, usage }) +module.exports = Object.assign(cmd, { usage }) diff --git a/lib/find-dupes.js b/lib/find-dupes.js index 957916378..19e7ea6a7 100644 --- a/lib/find-dupes.js +++ b/lib/find-dupes.js @@ -3,7 +3,6 @@ const dedupe = require('./dedupe.js') const usageUtil = require('./utils/usage.js') const usage = usageUtil('find-dupes', 'npm find-dupes') -const completion = require('./utils/completion/none.js') const cmd = (args, cb) => dedupe({ dryRun: true }, cb) -module.exports = Object.assign(cmd, { usage, completion }) +module.exports = Object.assign(cmd, { usage }) diff --git a/lib/get.js b/lib/get.js index ab2141e35..8a416027d 100644 --- a/lib/get.js +++ b/lib/get.js @@ -1,4 +1,5 @@ const npm = require('./npm.js') +const config = require('./config.js') const usageUtil = require('./utils/usage.js') const usage = usageUtil( @@ -6,7 +7,7 @@ const usage = usageUtil( 'npm get [<key> ...] (See `npm config`)' ) -const completion = npm.commands.config.completion +const completion = config.completion const cmd = (args, cb) => npm.commands.config(['get'].concat(args), cb) diff --git a/lib/help-search.js b/lib/help-search.js index d2a181806..b18473504 100644 --- a/lib/help-search.js +++ b/lib/help-search.js @@ -11,7 +11,6 @@ const didYouMean = require('./utils/did-you-mean.js') const { cmdList } = require('./utils/cmd-list.js') const usage = usageUtil('help-search', 'npm help-search <text>') -const completion = require('./utils/completion/none.js') const npmUsage = require('./utils/npm-usage.js') @@ -201,4 +200,4 @@ const formatResults = (args, results) => { return finalOut.trim() } -module.exports = Object.assign(cmd, { usage, completion }) +module.exports = Object.assign(cmd, { usage }) diff --git a/lib/help.js b/lib/help.js index f69961665..6f215c76c 100644 --- a/lib/help.js +++ b/lib/help.js @@ -1,10 +1,24 @@ module.exports = help -help.completion = function (opts, cb) { +help.completion = async (opts) => { if (opts.conf.argv.remain.length > 2) - return cb(null, []) - getSections(cb) + return [] + const g = path.resolve(__dirname, '../man/man[0-9]/*.[0-9]') + const files = await new Promise((resolve, reject) => { + glob(g, function (er, files) { + if (er) + return reject(er) + resolve(files) + }) + }) + + return Object.keys(files.reduce(function (acc, file) { + file = path.basename(file).replace(/\.[0-9]+$/, '') + file = file.replace(/^npm-/, '') + acc[file] = true + return acc + }, { help: true })) } const npmUsage = require('./utils/npm-usage.js') @@ -175,18 +189,3 @@ function htmlMan (man) { } return 'file://' + path.resolve(__dirname, '..', 'docs', 'output', sect, f + '.html') } - -function getSections (cb) { - const g = path.resolve(__dirname, '../man/man[0-9]/*.[0-9]') - glob(g, function (er, files) { - if (er) - return cb(er) - - cb(null, Object.keys(files.reduce(function (acc, file) { - file = path.basename(file).replace(/\.[0-9]+$/, '') - file = file.replace(/^npm-/, '') - acc[file] = true - return acc - }, { help: true }))) - }) -} diff --git a/lib/hook.js b/lib/hook.js index e0e15243e..7d69ccbf2 100644 --- a/lib/hook.js +++ b/lib/hook.js @@ -13,8 +13,6 @@ const usage = usageUtil('hook', [ 'npm hook update <id> <url> <secret>', ].join('\n')) -const completion = require('./utils/completion/none.js') - const cmd = (args, cb) => hook(args).then(() => cb()).catch(cb) const hook = async (args) => otplease(npm.flatOptions, opts => { @@ -127,4 +125,4 @@ const hookName = (hook) => { return target } -module.exports = Object.assign(cmd, { usage, completion }) +module.exports = Object.assign(cmd, { usage }) diff --git a/lib/init.js b/lib/init.js index 60ea52e16..a029779f8 100644 --- a/lib/init.js +++ b/lib/init.js @@ -3,7 +3,6 @@ const npa = require('npm-package-arg') const npm = require('./npm.js') const usageUtil = require('./utils/usage.js') -const completion = require('./utils/completion/none.js') const output = require('./utils/output.js') const usage = usageUtil( @@ -86,4 +85,4 @@ const init = async args => { }) } -module.exports = Object.assign(cmd, { completion, usage }) +module.exports = Object.assign(cmd, { usage }) diff --git a/lib/install.js b/lib/install.js index d4ee7047f..5f0137db1 100644 --- a/lib/install.js +++ b/lib/install.js @@ -81,14 +81,14 @@ const usage = usageUtil( '[--save-prod|--save-dev|--save-optional|--save-peer] [--save-exact] [--no-save]' ) -const completion = async (opts, cb) => { +const completion = async (opts) => { const { partialWord } = opts // install can complete to a folder with a package.json, or any package. // if it has a slash, then it's gotta be a folder // if it starts with https?://, then just give up, because it's a url if (/^https?:\/\//.test(partialWord)) { // do not complete to URLs - return cb(null, []) + return [] } if (/\//.test(partialWord)) { @@ -126,19 +126,18 @@ const completion = async (opts, cb) => { const match = matches.filter(el => !el || el.isPackage).pop() if (match) { // Success - only one match and it is a package dir - return cb(null, [match.fullPath]) + return [match.fullPath] } else { // no matches - return cb(null, []) + return [] } } catch (er) { - return cb(null, []) // invalid dir: no matching + return [] // invalid dir: no matching } } // Note: there used to be registry completion here, // but it stopped making sense somewhere around // 50,000 packages on the registry - cb() } module.exports = Object.assign(cmd, { usage, completion }) diff --git a/lib/link.js b/lib/link.js index 84f36ada6..0bb3d87b5 100644 --- a/lib/link.js +++ b/lib/link.js @@ -1,4 +1,6 @@ -const { readdir } = require('fs') +const fs = require('fs') +const util = require('util') +const readdir = util.promisify(fs.readdir) const { resolve } = require('path') const Arborist = require('@npmcli/arborist') @@ -10,9 +12,10 @@ const npm = require('./npm.js') const usageUtil = require('./utils/usage.js') const reifyFinish = require('./utils/reify-finish.js') -const completion = (opts, cb) => { +const completion = async (opts) => { const dir = npm.globalDir - readdir(dir, (er, files) => cb(er, files.filter(f => !/^[._-]/.test(f)))) + const files = await readdir(dir) + return files.filter(f => !/^[._-]/.test(f)) } const usage = usageUtil( @@ -1,6 +1,9 @@ const { usage, completion } = require('./ls.js') const npm = require('./npm.js') -module.exports = Object.assign((args, cb) => { + +const cmd = (args, cb) => { npm.config.set('long', true) return npm.commands.ls(args, cb) -}, { usage, completion }) +} + +module.exports = Object.assign(cmd, { usage, completion }) diff --git a/lib/logout.js b/lib/logout.js index ba2eb92fe..d2762c1ba 100644 --- a/lib/logout.js +++ b/lib/logout.js @@ -4,7 +4,6 @@ const getAuth = require('npm-registry-fetch/auth.js') const npmFetch = require('npm-registry-fetch') const npm = require('./npm.js') const usageUtil = require('./utils/usage.js') -const completion = require('./utils/completion/none.js') const usage = usageUtil( 'logout', @@ -42,4 +41,4 @@ const logout = async (args) => { await npm.config.save('user') } -module.exports = Object.assign(cmd, { completion, usage }) +module.exports = Object.assign(cmd, { usage }) diff --git a/lib/org.js b/lib/org.js index b7af3f3a3..aa9c97d49 100644 --- a/lib/org.js +++ b/lib/org.js @@ -13,19 +13,19 @@ org.usage = 'npm org rm orgname username\n' + 'npm org ls orgname [<username>]' -org.completion = function (opts, cb) { +org.completion = async (opts) => { var argv = opts.conf.argv.remain if (argv.length === 2) - return cb(null, org.subcommands) + return org.subcommands switch (argv[2]) { case 'ls': case 'add': case 'rm': case 'set': - return cb(null, []) + return [] default: - return cb(new Error(argv[2] + ' not recognized')) + throw new Error(argv[2] + ' not recognized') } } diff --git a/lib/outdated.js b/lib/outdated.js index f9a3fed8c..c10f63a12 100644 --- a/lib/outdated.js +++ b/lib/outdated.js @@ -17,7 +17,6 @@ const ansiTrim = require('./utils/ansi-trim.js') const usage = usageUtil('outdated', 'npm outdated [[<@scope>/]<pkg> ...]' ) -const completion = require('./utils/completion/none.js') function cmd (args, cb) { outdated(args) @@ -287,4 +286,4 @@ function makeJSON (list, opts) { return JSON.stringify(out, null, 2) } -module.exports = Object.assign(cmd, { completion, usage }) +module.exports = Object.assign(cmd, { usage }) diff --git a/lib/owner.js b/lib/owner.js index 0bfb0a6a5..6dce3ec70 100644 --- a/lib/owner.js +++ b/lib/owner.js @@ -16,18 +16,16 @@ const usage = usageUtil( '\nnpm owner ls [<@scope>/]<pkg>' ) -const completion = function (opts, cb) { +const completion = async (opts) => { const argv = opts.conf.argv.remain if (argv.length > 3) - return cb(null, []) + return [] if (argv[1] !== 'owner') argv.unshift('owner') - if (argv.length === 2) { - var subs = ['add', 'rm', 'ls'] - return cb(null, subs) - } + if (argv.length === 2) + return ['add', 'rm', 'ls'] // reaches registry in order to autocomplete rm if (argv[2] === 'rm') { @@ -35,25 +33,16 @@ const completion = function (opts, cb) { ...npm.flatOptions, fullMetadata: true, } - readLocalPkg() - .then(pkgName => { - if (!pkgName) - return null - - const spec = npa(pkgName) - return pacote.packument(spec, opts) - }) - .then(data => { - if (data && data.maintainers && data.maintainers.length) - return data.maintainers.map(m => m.name) - - return [] - }) - .then(owners => { - return cb(null, owners) - }) - } else - cb(null, []) + const pkgName = await readLocalPkg() + if (!pkgName) + return [] + + const spec = npa(pkgName) + const data = await pacote.packument(spec, opts) + if (data && data.maintainers && data.maintainers.length) + return data.maintainers.map(m => m.name) + } + return [] } const UsageError = () => diff --git a/lib/pack.js b/lib/pack.js index 7a5c2edab..ff906cc2b 100644 --- a/lib/pack.js +++ b/lib/pack.js @@ -10,7 +10,6 @@ const { getContents, logTar } = require('./utils/tar.js') const writeFile = util.promisify(require('fs').writeFile) const output = require('./utils/output.js') -const completion = require('./utils/completion/none.js') const usageUtil = require('./utils/usage.js') const usage = usageUtil('pack', 'npm pack [[<@scope>/]<pkg>...] [--dry-run]') @@ -47,4 +46,4 @@ const pack_ = async (arg, opts) => { return pkgContents } -module.exports = Object.assign(cmd, { usage, completion }) +module.exports = Object.assign(cmd, { usage }) diff --git a/lib/ping.js b/lib/ping.js index 7762be6d2..efa226310 100644 --- a/lib/ping.js +++ b/lib/ping.js @@ -4,7 +4,6 @@ const output = require('./utils/output.js') const usageUtil = require('./utils/usage.js') const usage = usageUtil('ping', 'npm ping\nping registry') -const completion = require('./utils/completion/none.js') const cmd = (args, cb) => ping(args).then(() => cb()).catch(cb) const pingUtil = require('./utils/ping.js') @@ -25,4 +24,4 @@ const ping = async args => { log.notice('PONG', `${JSON.stringify(details, null, 2)}`) } -module.exports = Object.assign(cmd, { completion, usage }) +module.exports = Object.assign(cmd, { usage }) diff --git a/lib/prefix.js b/lib/prefix.js index 0a9914473..d108b9d42 100644 --- a/lib/prefix.js +++ b/lib/prefix.js @@ -1,8 +1,7 @@ const npm = require('./npm.js') const output = require('./utils/output.js') const usageUtil = require('./utils/usage.js') -const completion = require('./utils/completion/none.js') const cmd = (args, cb) => prefix(args).then(() => cb()).catch(cb) const usage = usageUtil('prefix', 'npm prefix [-g]') const prefix = async (args, cb) => output(npm.prefix) -module.exports = Object.assign(cmd, { usage, completion }) +module.exports = Object.assign(cmd, { usage }) diff --git a/lib/profile.js b/lib/profile.js index 24f026ce8..3727ac0c8 100644 --- a/lib/profile.js +++ b/lib/profile.js @@ -20,25 +20,25 @@ const usage = usageUtil( 'npm profile set <key> <value>' ) -const completion = (opts, cb) => { +const completion = async (opts) => { var argv = opts.conf.argv.remain const subcommands = ['enable-2fa', 'disable-2fa', 'get', 'set'] if (!argv[2]) - return cb(null, subcommands) + return subcommands switch (argv[2]) { case 'enable-2fa': case 'enable-tfa': - return cb(null, ['auth-and-writes', 'auth-only']) + return ['auth-and-writes', 'auth-only'] case 'disable-2fa': case 'disable-tfa': case 'get': case 'set': - return cb(null, []) + return [] default: - return cb(new Error(argv[2] + ' not recognized')) + throw new Error(argv[2] + ' not recognized') } } diff --git a/lib/prune.js b/lib/prune.js index ea6ed4108..228fd3eeb 100644 --- a/lib/prune.js +++ b/lib/prune.js @@ -8,7 +8,6 @@ const reifyFinish = require('./utils/reify-finish.js') const usage = usageUtil('prune', 'npm prune [[<@scope>/]<pkg>...] [--production]' ) -const completion = require('./utils/completion/none.js') const cmd = (args, cb) => prune().then(() => cb()).catch(cb) @@ -22,4 +21,4 @@ const prune = async () => { await reifyFinish(arb) } -module.exports = Object.assign(cmd, { usage, completion }) +module.exports = Object.assign(cmd, { usage }) diff --git a/lib/publish.js b/lib/publish.js index 3e8df0076..5ec66d42f 100644 --- a/lib/publish.js +++ b/lib/publish.js @@ -18,7 +18,6 @@ const { getContents, logTar } = require('./utils/tar.js') // defaults and metadata, like git sha's and default scripts and all that. const readJson = util.promisify(require('read-package-json')) -const completion = require('./utils/completion/none.js') const usageUtil = require('./utils/usage.js') const usage = usageUtil('publish', 'npm publish [<folder>] [--tag <tag>] [--access <public|restricted>] [--dry-run]' + @@ -137,4 +136,4 @@ const publish_ = async (arg, opts) => { return pkgContents } -module.exports = Object.assign(cmd, { usage, completion }) +module.exports = Object.assign(cmd, { usage }) diff --git a/lib/repo.js b/lib/repo.js index 2dc3bcb1b..e9074dca6 100644 --- a/lib/repo.js +++ b/lib/repo.js @@ -8,7 +8,6 @@ const hostedFromMani = require('./utils/hosted-git-info-from-manifest.js') const { URL } = require('url') const usage = usageUtil('repo', 'npm repo [<pkgname> [<pkgname> ...]]') -const completion = require('./utils/completion/none.js') const cmd = (args, cb) => repo(args).then(() => cb()).catch(cb) @@ -69,4 +68,4 @@ const unknownHostedUrl = url => { } } -module.exports = Object.assign(cmd, { usage, completion }) +module.exports = Object.assign(cmd, { usage }) diff --git a/lib/root.js b/lib/root.js index 27e357655..631aef838 100644 --- a/lib/root.js +++ b/lib/root.js @@ -1,8 +1,7 @@ const npm = require('./npm.js') const output = require('./utils/output.js') const usageUtil = require('./utils/usage.js') -const completion = require('./utils/completion/none.js') const cmd = (args, cb) => root(args).then(() => cb()).catch(cb) const usage = usageUtil('root', 'npm root [-g]') const root = async (args, cb) => output(npm.dir) -module.exports = Object.assign(cmd, { usage, completion }) +module.exports = Object.assign(cmd, { usage }) diff --git a/lib/run-script.js b/lib/run-script.js index 8e24a8a44..4dfb854ca 100644 --- a/lib/run-script.js +++ b/lib/run-script.js @@ -14,16 +14,14 @@ const usage = usageUtil( 'npm run-script <command> [-- <args>]' ) -const completion = async (opts, cb) => { +const completion = async (opts) => { const argv = opts.conf.argv.remain if (argv.length === 2) { // find the script name const json = resolve(npm.localPrefix, 'package.json') const { scripts = {} } = await readJson(json).catch(er => ({})) - return cb(null, Object.keys(scripts)) + return Object.keys(scripts) } - // otherwise nothing to do, just let the system handle it - return cb() } const cmd = (args, cb) => { diff --git a/lib/search.js b/lib/search.js index a3d806d2f..3f8fd99fb 100644 --- a/lib/search.js +++ b/lib/search.js @@ -8,7 +8,6 @@ const packageFilter = require('./search/package-filter.js') const npm = require('./npm.js') const output = require('./utils/output.js') const usageUtil = require('./utils/usage.js') -const completion = require('./utils/completion/none.js') const usage = usageUtil( 'search', @@ -86,4 +85,4 @@ function prepareExcludes (searchexclude) { .filter(s => s) } -module.exports = Object.assign(cmd, { completion, usage }) +module.exports = Object.assign(cmd, { usage }) diff --git a/lib/set-script.js b/lib/set-script.js index f655c2210..7bac6eca5 100644 --- a/lib/set-script.js +++ b/lib/set-script.js @@ -3,7 +3,6 @@ const usageUtil = require('./utils/usage.js') const { localPrefix } = require('./npm.js') const fs = require('fs') const usage = usageUtil('set-script', 'npm set-script [<script>] [<command>]') -const completion = require('./utils/completion/none.js') const parseJSON = require('json-parse-even-better-errors') const rpj = require('read-package-json-fast') @@ -50,4 +49,4 @@ const set = async function (args) { log.warn('set-script', `Script "${args[0]}" was overwritten`) } -module.exports = Object.assign(cmd, { usage, completion }) +module.exports = Object.assign(cmd, { usage }) diff --git a/lib/set.js b/lib/set.js index fd6076293..3d61c1e93 100644 --- a/lib/set.js +++ b/lib/set.js @@ -1,14 +1,14 @@ +const npm = require('./npm.js') +const config = require('./config.js') -module.exports = set +const usage = 'npm set <key>=<value> [<key>=<value> ...] (See `npm config`)' -set.usage = 'npm set <key>=<value> [<key>=<value> ...] (See `npm config`)' +const completion = config.completion -var npm = require('./npm.js') - -set.completion = npm.commands.config.completion - -function set (args, cb) { +const cmd = (args, cb) => { if (!args.length) - return cb(set.usage) + return cb(usage) npm.commands.config(['set'].concat(args), cb) } + +module.exports = Object.assign(cmd, { usage, completion }) diff --git a/lib/shrinkwrap.js b/lib/shrinkwrap.js index f1146206d..8768f35b5 100644 --- a/lib/shrinkwrap.js +++ b/lib/shrinkwrap.js @@ -6,7 +6,6 @@ const Arborist = require('@npmcli/arborist') const log = require('npmlog') const npm = require('./npm.js') -const completion = require('./utils/completion/none.js') const usageUtil = require('./utils/usage.js') const usage = usageUtil('shrinkwrap', 'npm shrinkwrap') @@ -50,4 +49,4 @@ const shrinkwrap = async () => { log.notice('', 'npm-shrinkwrap.json up to date') } -module.exports = Object.assign(cmd, { usage, completion }) +module.exports = Object.assign(cmd, { usage }) diff --git a/lib/star.js b/lib/star.js index b3e72d7da..c02fdeed8 100644 --- a/lib/star.js +++ b/lib/star.js @@ -6,7 +6,6 @@ const npm = require('./npm.js') const output = require('./utils/output.js') const usageUtil = require('./utils/usage.js') const getIdentity = require('./utils/get-identity') -const completion = require('./utils/completion/none.js') const usage = usageUtil( 'star', @@ -72,4 +71,4 @@ const star = async args => { } } -module.exports = Object.assign(cmd, { completion, usage }) +module.exports = Object.assign(cmd, { usage }) diff --git a/lib/stars.js b/lib/stars.js index c09ca6003..d1c2b73fb 100644 --- a/lib/stars.js +++ b/lib/stars.js @@ -5,7 +5,6 @@ const npm = require('./npm.js') const output = require('./utils/output.js') const getIdentity = require('./utils/get-identity.js') const usageUtil = require('./utils/usage.js') -const completion = require('./utils/completion/none.js') const usage = usageUtil('stars', 'npm stars [<user>]') @@ -33,4 +32,4 @@ const stars_ = async ([user = getIdentity(npm.flatOptions)]) => { output(row.value) } -module.exports = Object.assign(cmd, { usage, completion }) +module.exports = Object.assign(cmd, { usage }) diff --git a/lib/team.js b/lib/team.js index 5e88011cf..24e8360b6 100644 --- a/lib/team.js +++ b/lib/team.js @@ -17,10 +17,10 @@ const usage = usageUtil( 'npm team ls <scope>|<scope:team>\n' ) -const completion = (opts, cb) => { +const completion = async (opts) => { const { conf: { argv: { remain: argv } } } = opts if (argv.length === 2) - return cb(null, subcommands) + return subcommands switch (argv[2]) { case 'ls': @@ -28,9 +28,9 @@ const completion = (opts, cb) => { case 'destroy': case 'add': case 'rm': - return cb(null, []) + return [] default: - return cb(new Error(argv[2] + ' not recognized')) + throw new Error(argv[2] + ' not recognized') } } diff --git a/lib/token.js b/lib/token.js index b737b5ffb..1e78584c7 100644 --- a/lib/token.js +++ b/lib/token.js @@ -30,18 +30,18 @@ const InvalidCIDRError = (msg) => token.subcommands = ['list', 'revoke', 'create'] -token.completion = function (opts, cb) { +token.completion = async (opts) => { var argv = opts.conf.argv.remain if (argv.length === 2) - return cb(null, token.subcommands) + return token.subcommands switch (argv[2]) { case 'list': case 'revoke': case 'create': - return cb(null, []) + return [] default: - return cb(new Error(argv[2] + ' not recognized')) + throw new Error(argv[2] + ' not recognized') } } diff --git a/lib/unpublish.js b/lib/unpublish.js index 528208c39..bb931682b 100644 --- a/lib/unpublish.js +++ b/lib/unpublish.js @@ -17,11 +17,7 @@ const usage = usageUtil('unpublish', 'npm unpublish [<@scope>/]<pkg>[@<version>] const cmd = (args, cb) => unpublish(args).then(() => cb()).catch(cb) -const completion = (args, cb) => completionFn(args) - .then((res) => cb(null, res)) - .catch(cb) - -const completionFn = async (args) => { +const completion = async (args) => { const { partialWord, conf } = args if (conf.argv.remain.length >= 3) diff --git a/lib/unstar.js b/lib/unstar.js index 5dea5bcab..554bd60bc 100644 --- a/lib/unstar.js +++ b/lib/unstar.js @@ -1,4 +1,4 @@ -const { usage, completion } = require('./star.js') +const { usage } = require('./star.js') const npm = require('./npm.js') const unstar = (args, cb) => { @@ -6,4 +6,4 @@ const unstar = (args, cb) => { return npm.commands.star(args, cb) } -module.exports = Object.assign(unstar, { usage, completion }) +module.exports = Object.assign(unstar, { usage }) diff --git a/lib/utils/completion/installed-deep.js b/lib/utils/completion/installed-deep.js index 793f3b3e9..f464bb9a9 100644 --- a/lib/utils/completion/installed-deep.js +++ b/lib/utils/completion/installed-deep.js @@ -2,7 +2,7 @@ const { resolve } = require('path') const Arborist = require('@npmcli/arborist') const npm = require('../../npm.js') -const readNames = async () => { +const installedDeep = async () => { const { depth, global, @@ -36,8 +36,4 @@ const readNames = async () => { return [...res] } -function installedDeep (opts, cb) { - return readNames().then(res => cb(null, res)).catch(cb) -} - module.exports = installedDeep diff --git a/lib/utils/completion/installed-shallow.js b/lib/utils/completion/installed-shallow.js index e2ff5a302..c9c680e7d 100644 --- a/lib/utils/completion/installed-shallow.js +++ b/lib/utils/completion/installed-shallow.js @@ -4,7 +4,7 @@ const readdir = promisify(require('readdir-scoped-modules')) const names = global => readdir(global ? npm.globalDir : npm.localDir) -const installedShallow = async opts => { +const installedShallow = async (opts) => { const { conf: { argv: { remain } } } = opts if (remain.length > 3) return null @@ -15,5 +15,4 @@ const installedShallow = async opts => { return [...locals, ...globals] } -module.exports = (opts, cb) => - installedShallow(opts).then(list => cb(null, list)).catch(cb) +module.exports = installedShallow diff --git a/lib/utils/completion/none.js b/lib/utils/completion/none.js deleted file mode 100644 index 752400da4..000000000 --- a/lib/utils/completion/none.js +++ /dev/null @@ -1,2 +0,0 @@ -// used for commands where no completion is relevant/possible -module.exports = (opts, cb) => cb(null, []) diff --git a/lib/utils/lifecycle-cmd.js b/lib/utils/lifecycle-cmd.js index 83a712cf4..94b109942 100644 --- a/lib/utils/lifecycle-cmd.js +++ b/lib/utils/lifecycle-cmd.js @@ -2,10 +2,9 @@ // test, start, stop, restart const usageUtil = require('./usage.js') -const completion = require('./completion/none.js') module.exports = (npm, stage) => { const cmd = (args, cb) => npm.commands['run-script']([stage, ...args], cb) const usage = usageUtil(stage, `npm ${stage} [-- <args>]`) - return Object.assign(cmd, { usage, completion }) + return Object.assign(cmd, { usage }) } diff --git a/lib/version.js b/lib/version.js index 3a46efae1..9d87b2f2c 100644 --- a/lib/version.js +++ b/lib/version.js @@ -3,13 +3,12 @@ const npm = require('./npm.js') const output = require('./utils/output.js') const usageUtil = require('./utils/usage.js') -const completion = (opts, cb) => { - const none = require('./utils/completion/none.js') +const completion = async (opts) => { const { conf: { argv: { remain } } } = opts if (remain.length > 2) - return none(opts, cb) + return [] - return cb(null, [ + return [ 'major', 'minor', 'patch', @@ -18,7 +17,7 @@ const completion = (opts, cb) => { 'prepatch', 'prerelease', 'from-git', - ]) + ] } const usage = usageUtil('version', diff --git a/lib/view.js b/lib/view.js index bc9a13d85..d6d79d35c 100644 --- a/lib/view.js +++ b/lib/view.js @@ -26,11 +26,11 @@ const usage = usageUtil( const cmd = (args, cb) => view(args).then(() => cb()).catch(cb) -const completion = async (opts, cb) => { +const completion = async (opts) => { if (opts.conf.argv.remain.length <= 2) { // There used to be registry completion here, but it stopped // making sense somewhere around 50,000 packages on the registry - return cb() + return } // have the package, get the fields const config = { ...npm.flatOptions, fullMetadata: true, preferOnline: true } @@ -39,8 +39,8 @@ const completion = async (opts, cb) => { const pckmnt = await packument(spec, config) const dv = pckmnt.versions[pckmnt['dist-tags'][defaultTag]] pckmnt.versions = Object.keys(pckmnt.versions).sort(semver.compareLoose) - const fields = getFields(pckmnt).concat(getFields(dv)) - return cb(null, fields) + + return getFields(pckmnt).concat(getFields(dv)) function getFields (d, f, pref) { f = f || [] diff --git a/lib/whoami.js b/lib/whoami.js index 8e1c1d052..bbbc39cce 100644 --- a/lib/whoami.js +++ b/lib/whoami.js @@ -2,7 +2,6 @@ const npm = require('./npm.js') const output = require('./utils/output.js') const getIdentity = require('./utils/get-identity.js') const usageUtil = require('./utils/usage.js') -const completion = require('./utils/completion/none.js') const cmd = (args, cb) => whoami(args).then(() => cb()).catch(cb) @@ -14,4 +13,4 @@ const whoami = async ([spec]) => { output(opts.json ? JSON.stringify(username) : username) } -module.exports = Object.assign(cmd, { completion, usage }) +module.exports = Object.assign(cmd, { usage }) diff --git a/test/lib/access.js b/test/lib/access.js index 3063b6c53..fb799f2df 100644 --- a/test/lib/access.js +++ b/test/lib/access.js @@ -1,35 +1,24 @@ const { test } = require('tap') const requireInject = require('require-inject') -const emptyMock = requireInject('../../lib/access.js', { +const access = requireInject('../../lib/access.js', { '../../lib/npm.js': { flatOptions: {}, }, }) test('completion', t => { - const { completion } = emptyMock + const { completion } = access const testComp = (argv, expect) => { - completion({conf: {argv: {remain: argv}}}, (er, res) => { - if (er) - throw er - t.strictSame(res, expect, argv.join(' ')) - }) + const res = completion({conf: {argv: {remain: argv}}}) + t.resolves(res, expect, argv.join(' ')) } testComp(['npm', 'access'], [ - 'public', - 'restricted', - 'grant', - 'revoke', - 'ls-packages', - 'ls-collaborators', - 'edit', - '2fa-required', - '2fa-not-required', + 'public', 'restricted', 'grant', 'revoke', 'ls-packages', + 'ls-collaborators', 'edit', '2fa-required', '2fa-not-required', ]) - testComp(['npm', 'access', 'grant'], ['read-only', 'read-write']) testComp(['npm', 'access', 'grant', 'read-only'], []) testComp(['npm', 'access', 'public'], []) @@ -42,15 +31,15 @@ test('completion', t => { testComp(['npm', 'access', '2fa-not-required'], []) testComp(['npm', 'access', 'revoke'], []) - completion({conf: {argv: {remain: ['npm', 'access', 'foobar']}}}, (er) => { - t.match(er, { message: 'foobar not recognized' }) - }) + t.rejects( + completion({conf: {argv: {remain: ['npm', 'access', 'foobar']}}}), + { message: 'foobar not recognized' } + ) t.end() }) test('subcommand required', t => { - const access = emptyMock access([], (err) => { t.equal(err, '\nUsage: Subcommand is required.\n\n' + access.usage) t.end() @@ -58,8 +47,6 @@ test('subcommand required', t => { }) test('unrecognized subcommand', (t) => { - const access = emptyMock - access(['blerg'], (err) => { t.match( err, @@ -71,8 +58,6 @@ test('unrecognized subcommand', (t) => { }) test('edit', (t) => { - const access = emptyMock - access([ 'edit', '@scoped/another', @@ -349,8 +334,6 @@ test('access grant current cwd', (t) => { }) test('access grant others', (t) => { - const access = emptyMock - access([ 'grant', 'rerere', @@ -367,8 +350,6 @@ test('access grant others', (t) => { }) test('access grant missing team args', (t) => { - const access = emptyMock - access([ 'grant', 'read-only', @@ -385,8 +366,6 @@ test('access grant missing team args', (t) => { }) test('access grant malformed team arg', (t) => { - const access = emptyMock - access([ 'grant', 'read-only', @@ -452,8 +431,6 @@ test('access revoke', (t) => { }) test('access revoke missing team args', (t) => { - const access = emptyMock - access([ 'revoke', undefined, @@ -469,8 +446,6 @@ test('access revoke missing team args', (t) => { }) test('access revoke malformed team arg', (t) => { - const access = emptyMock - access([ 'revoke', 'foo', diff --git a/test/lib/audit.js b/test/lib/audit.js index cc7379394..3d6296bac 100644 --- a/test/lib/audit.js +++ b/test/lib/audit.js @@ -168,35 +168,22 @@ t.test('report endpoint error', t => { }) t.test('completion', t => { - t.test('fix', t => { - audit.completion({ - conf: { argv: { remain: ['npm', 'audit'] } }, - }, (err, res) => { - if (err) - throw err - const subcmd = res.pop() - t.equals('fix', subcmd, 'completes to fix') - t.end() - }) + t.test('fix', async t => { + t.resolveMatch(audit.completion({ conf: { argv: { remain: ['npm', 'audit'] } } }), ['fix'], 'completes to fix') + t.end() }) t.test('subcommand fix', t => { - audit.completion({ - conf: { argv: { remain: ['npm', 'audit', 'fix'] } }, - }, (err) => { - if (err) - throw err - t.end() - }) + t.resolveMatch(audit.completion({ conf: { argv: { remain: ['npm', 'audit', 'fix'] } } }), [], 'resolves to ?') + t.end() }) t.test('subcommand not recognized', t => { - audit.completion({ - conf: { argv: { remain: ['npm', 'audit', 'repare'] } }, - }, (err) => { - t.ok(err, 'not recognized') - t.end() - }) + t.rejects( + audit.completion({ conf: { argv: { remain: ['npm', 'audit', 'repare'] } } }), + { message: 'repare not recognized' } + ) + t.end() }) t.end() diff --git a/test/lib/bugs.js b/test/lib/bugs.js index df6434987..992bd9f61 100644 --- a/test/lib/bugs.js +++ b/test/lib/bugs.js @@ -54,14 +54,6 @@ const bugs = requireInject('../../lib/bugs.js', { '../../lib/utils/open-url.js': openUrl, }) -t.test('completion', t => { - bugs.completion({}, (er, res) => { - t.equal(er, null) - t.same(res, []) - t.end() - }) -}) - t.test('open bugs urls', t => { const expect = { nobugs: 'https://www.npmjs.com/package/nobugs', diff --git a/test/lib/cache.js b/test/lib/cache.js index 2e9ad346b..05d269dd4 100644 --- a/test/lib/cache.js +++ b/test/lib/cache.js @@ -208,18 +208,10 @@ t.test('cache completion', t => { const { completion } = cache const testComp = (argv, expect) => { - completion({ conf: { argv: { remain: argv } } }, (err, res) => { - t.ifError(err) - t.strictSame(res, expect, argv.join(' ')) - }) + t.resolveMatch(completion({ conf: { argv: { remain: argv } } }), expect, argv.join(' ')) } - testComp(['npm', 'cache'], [ - 'add', - 'clean', - 'verify', - ]) - + testComp(['npm', 'cache'], ['add', 'clean', 'verify']) testComp(['npm', 'cache', 'add'], []) testComp(['npm', 'cache', 'clean'], []) testComp(['npm', 'cache', 'verify'], []) diff --git a/test/lib/completion.js b/test/lib/completion.js index 367a1c03a..19f70df20 100644 --- a/test/lib/completion.js +++ b/test/lib/completion.js @@ -21,28 +21,28 @@ const npm = { }, commands: { completion: { - completion: (opts, cb) => { - return cb(null, [['>>', '~/.bashrc']]) - }, + completion: () => [['>>', '~/.bashrc']], }, adduser: {}, access: { - completion: (opts, cb) => { + completion: () => { if (accessCompletionError) - return cb(new Error('access completion failed')) + throw new Error('access completion failed') - return cb(null, ['public', 'restricted']) + return ['public', 'restricted'] }, }, + promise: { + completion: () => Promise.resolve(['resolved_completion_promise']), + }, donothing: { - completion: (opts, cb) => { - return cb(null, null) + completion: () => { + return null }, }, driveaboat: { - completion: (opts, cb) => { - // the leading space here is to exercise the escape method - return cb(null, ' fast') + completion: () => { + return ' fast' }, }, }, @@ -86,7 +86,7 @@ const completion = requireInject('../../lib/completion.js', { }, }) -test('completion completion', t => { +test('completion completion', async t => { const home = process.env.HOME t.teardown(() => { process.env.HOME = home @@ -97,19 +97,15 @@ test('completion completion', t => { '.zshrc': '', }) - completion.completion({ w: 2 }, (err, res) => { - if (err) - throw err - - t.strictSame(res, [ - ['>>', '~/.zshrc'], - ['>>', '~/.bashrc'], - ], 'identifies both shells') - t.end() - }) + const res = await completion.completion({ w: 2 }) + t.strictSame(res, [ + ['>>', '~/.zshrc'], + ['>>', '~/.bashrc'], + ], 'identifies both shells') + t.end() }) -test('completion completion no known shells', t => { +test('completion completion no known shells', async t => { const home = process.env.HOME t.teardown(() => { process.env.HOME = home @@ -117,23 +113,15 @@ test('completion completion no known shells', t => { process.env.HOME = t.testdir() - completion.completion({ w: 2 }, (err, res) => { - if (err) - throw err - - t.strictSame(res, [], 'no responses') - t.end() - }) + const res = await completion.completion({ w: 2 }) + t.strictSame(res, [], 'no responses') + t.end() }) -test('completion completion wrong word count', t => { - completion.completion({ w: 3 }, (err, res) => { - if (err) - throw err - - t.strictSame(res, undefined, 'no responses') - t.end() - }) +test('completion completion wrong word count', async t => { + const res = await completion.completion({ w: 3 }) + t.strictSame(res, undefined, 'no responses') + t.end() }) test('completion errors in windows without bash', t => { @@ -313,6 +301,35 @@ test('completion of invalid command name does nothing', t => { }) }) +test('handles async completion function', t => { + process.env.COMP_CWORD = 2 + process.env.COMP_LINE = 'npm promise' + process.env.COMP_POINT = process.env.COMP_LINE.length + + t.teardown(() => { + delete process.env.COMP_CWORD + delete process.env.COMP_LINE + delete process.env.COMP_POINT + npm.config.clear() + output.length = 0 + }) + + completion(['npm', 'promise', ''], (err, res) => { + if (err) + throw err + + t.strictSame(npmConfig, { + argv: { + remain: ['npm', 'promise'], + cooked: ['npm', 'promise'], + original: ['npm', 'promise'], + }, + }, 'applies command config appropriately') + t.strictSame(output, ['resolved_completion_promise'], 'resolves async completion results') + t.end() + }) +}) + test('completion triggers command completions', t => { process.env.COMP_CWORD = 2 process.env.COMP_LINE = 'npm access ' diff --git a/test/lib/config.js b/test/lib/config.js index 5d2f54249..edaa6486c 100644 --- a/test/lib/config.js +++ b/test/lib/config.js @@ -610,23 +610,13 @@ t.test('completion', t => { const { completion } = config const testComp = (argv, expect) => { - completion({ conf: { argv: { remain: argv } } }, (er, res) => { - t.ifError(er) - t.strictSame(res, expect, argv.join(' ')) - }) + t.resolveMatch(completion({ conf: { argv: { remain: argv } } }), expect, argv.join(' ')) } testComp(['npm', 'foo'], []) - testComp(['npm', 'config'], [ - 'get', - 'set', - 'delete', - 'ls', - 'rm', - 'edit', - 'list', - ]) + testComp(['npm', 'config'], ['get', 'set', 'delete', 'ls', 'rm', 'edit', 'list']) testComp(['npm', 'config', 'set', 'foo'], []) + const possibleConfigKeys = [...Object.keys(types)] testComp(['npm', 'config', 'get'], possibleConfigKeys) testComp(['npm', 'config', 'set'], possibleConfigKeys) @@ -636,24 +626,8 @@ t.test('completion', t => { testComp(['npm', 'config', 'list'], []) testComp(['npm', 'config', 'ls'], []) - completion({ - conf: { - argv: { - remain: ['npm', 'config'], - }, - }, - partialWord: 'l', - }, (er, res) => { - t.ifError(er) - t.strictSame(res, [ - 'get', - 'set', - 'delete', - 'ls', - 'rm', - 'edit', - ], 'npm config') - }) + const partial = completion({conf: { argv: { remain: ['npm', 'config'] } }, partialWord: 'l'}) + t.resolveMatch(partial, ['get', 'set', 'delete', 'ls', 'rm', 'edit'], 'npm config') t.end() }) diff --git a/test/lib/deprecate.js b/test/lib/deprecate.js index 229cb9137..fd563de12 100644 --- a/test/lib/deprecate.js +++ b/test/lib/deprecate.js @@ -38,29 +38,24 @@ test('completion', async t => { const { completion } = deprecate - const testComp = (argv, expect) => { - return new Promise((resolve, reject) => { - completion({ conf: { argv: { remain: argv } } }, (err, res) => { - if (err) - return reject(err) - - t.strictSame(res, expect, `completion: ${argv}`) - resolve() - }) - }) + const testComp = async (argv, expect) => { + const res = await completion({ conf: { argv: { remain: argv } } }) + t.strictSame(res, expect, `completion: ${argv}`) } - await testComp([], ['foo', 'bar', 'baz']) - await testComp(['b'], ['bar', 'baz']) - await testComp(['fo'], ['foo']) - await testComp(['g'], []) - await testComp(['foo', 'something'], []) + await Promise.all([ + testComp([], ['foo', 'bar', 'baz']), + testComp(['b'], ['bar', 'baz']), + testComp(['fo'], ['foo']), + testComp(['g'], []), + testComp(['foo', 'something'], []), + ]) getIdentityImpl = () => { - throw new Error('unknown failure') + throw new Error('deprecate test failure') } - t.rejects(testComp([], []), /unknown failure/) + t.rejects(testComp([], []), { message: 'deprecate test failure' }) }) test('no args', t => { diff --git a/test/lib/dist-tag.js b/test/lib/dist-tag.js index 8b1106fa3..c18935230 100644 --- a/test/lib/dist-tag.js +++ b/test/lib/dist-tag.js @@ -294,35 +294,13 @@ test('remove missing pkg name', (t) => { test('completion', t => { const { completion } = distTag - t.plan(3) + t.plan(2) - completion({ - conf: { - argv: { - remain: ['npm', 'dist-tag'], - }, - }, - }, (err, res) => { - t.ifError(err, 'npm dist-tags completion') - - t.strictSame( - res, - [ - 'add', - 'rm', - 'ls', - ], - 'should list npm dist-tag commands for completion' - ) - }) + const match = completion({ conf: { argv: { remain: ['npm', 'dist-tag'] } } }) + t.resolveMatch(match, ['add', 'rm', 'ls'], + 'should list npm dist-tag commands for completion') - completion({ - conf: { - argv: { - remain: ['npm', 'dist-tag', 'foobar'], - }, - }, - }, (err) => { - t.notOk(err, 'should ignore any unknown name') - }) + const noMatch = completion({ conf: { argv: { remain: ['npm', 'dist-tag', 'foobar'] } } }) + t.resolveMatch(noMatch, []) + t.end() }) diff --git a/test/lib/docs.js b/test/lib/docs.js index b4ede8731..8a59ed7cc 100644 --- a/test/lib/docs.js +++ b/test/lib/docs.js @@ -44,14 +44,6 @@ const docs = requireInject('../../lib/docs.js', { '../../lib/utils/open-url.js': openUrl, }) -t.test('completion', t => { - docs.completion({}, (er, res) => { - t.equal(er, null) - t.same(res, []) - t.end() - }) -}) - t.test('open docs urls', t => { const expect = { nodocs: 'https://www.npmjs.com/package/nodocs', diff --git a/test/lib/help.js b/test/lib/help.js index 40a035421..fc4a32e07 100644 --- a/test/lib/help.js +++ b/test/lib/help.js @@ -101,20 +101,13 @@ 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: [] } } }) + const noArgs = await help.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'] } } }) + const threeArgs = await help.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') + t.rejects(help.completion({ conf: { argv: { remain: [] } } }), /glob failed/, 'glob errors propagate') }) test('npm help -h', t => { diff --git a/test/lib/install.js b/test/lib/install.js index 177952b9e..859a4bdaa 100644 --- a/test/lib/install.js +++ b/test/lib/install.js @@ -130,7 +130,7 @@ test('should install globally using Arborist', (t) => { }) }) -test('completion to folder', (t) => { +test('completion to folder', async t => { const install = requireInject('../../lib/install.js', { '../../lib/utils/reify-finish.js': async () => {}, util: { @@ -145,17 +145,13 @@ test('completion to folder', (t) => { }, }, }) - install.completion({ - partialWord: '/ar', - }, (er, res) => { - t.equal(er, null) - const expect = process.platform === 'win32' ? '\\arborist' : '/arborist' - t.strictSame(res, [expect], 'package dir match') - t.end() - }) + const res = await install.completion({ partialWord: '/ar' }) + const expect = process.platform === 'win32' ? '\\arborist' : '/arborist' + t.strictSame(res, [expect], 'package dir match') + t.end() }) -test('completion to folder - invalid dir', (t) => { +test('completion to folder - invalid dir', async t => { const install = requireInject('../../lib/install.js', { '../../lib/utils/reify-finish.js': async () => {}, util: { @@ -167,16 +163,12 @@ test('completion to folder - invalid dir', (t) => { }, }, }) - install.completion({ - partialWord: 'path/to/folder', - }, (er, res) => { - t.equal(er, null) - t.strictSame(res, [], 'invalid dir: no matching') - t.end() - }) + const res = await install.completion({ partialWord: 'path/to/folder' }) + t.strictSame(res, [], 'invalid dir: no matching') + t.end() }) -test('completion to folder - no matches', (t) => { +test('completion to folder - no matches', async t => { const install = requireInject('../../lib/install.js', { '../../lib/utils/reify-finish.js': async () => {}, util: { @@ -188,16 +180,12 @@ test('completion to folder - no matches', (t) => { }, }, }) - install.completion({ - partialWord: '/pa', - }, (er, res) => { - t.equal(er, null) - t.strictSame(res, [], 'no name match') - t.end() - }) + const res = await install.completion({ partialWord: '/pa' }) + t.strictSame(res, [], 'no name match') + t.end() }) -test('completion to folder - match is not a package', (t) => { +test('completion to folder - match is not a package', async t => { const install = requireInject('../../lib/install.js', { '../../lib/utils/reify-finish.js': async () => {}, util: { @@ -212,31 +200,19 @@ test('completion to folder - match is not a package', (t) => { }, }, }) - install.completion({ - partialWord: '/ar', - }, (er, res) => { - t.equal(er, null) - t.strictSame(res, [], 'no name match') - t.end() - }) + const res = await install.completion({ partialWord: '/ar' }) + t.strictSame(res, [], 'no name match') + t.end() }) -test('completion to url', (t) => { - install.completion({ - partialWord: 'http://path/to/url', - }, (er, res) => { - t.equal(er, null) - t.strictSame(res, []) - t.end() - }) +test('completion to url', async t => { + const res = await install.completion({ partialWord: 'http://path/to/url' }) + t.strictSame(res, []) + t.end() }) -test('completion', (t) => { - install.completion({ - partialWord: 'toto', - }, (er, res) => { - t.notOk(er) - t.notOk(res) - t.end() - }) +test('completion', async t => { + const res = await install.completion({ partialWord: 'toto' }) + t.notOk(res) + t.end() }) diff --git a/test/lib/link.js b/test/lib/link.js index c39026a49..b1048427d 100644 --- a/test/lib/link.js +++ b/test/lib/link.js @@ -317,7 +317,7 @@ t.test('link pkg already in global space when prefix is a symlink', (t) => { }) }) -t.test('completion', (t) => { +t.test('completion', async t => { const testdir = t.testdir({ 'global-prefix': { lib: { @@ -332,31 +332,30 @@ t.test('completion', (t) => { }) npm.globalDir = resolve(testdir, 'global-prefix', 'lib', 'node_modules') - link.completion({}, (err, words) => { - t.ifError(err, 'should not error out') - t.deepEqual( - words, - ['bar', 'foo', 'ipsum', 'lorem'], - 'should list all package names available in globalDir' - ) - t.end() - }) + const words = await link.completion({}) + t.deepEqual( + words, + ['bar', 'foo', 'ipsum', 'lorem'], + 'should list all package names available in globalDir' + ) + t.end() }) -t.test('--global option', (t) => { +t.test('--global option', async t => { const _config = npm.config npm.config = { get () { return true } } - link([], (err) => { + try { + await link([]) + t.fail('should not get here') + } catch (err) { npm.config = _config - t.match( err.message, /link should never be --global/, 'should throw an useful error' ) - - t.end() - }) + } + t.end() }) diff --git a/test/lib/load-all-commands.js b/test/lib/load-all-commands.js index fa73b8a78..02cb0be65 100644 --- a/test/lib/load-all-commands.js +++ b/test/lib/load-all-commands.js @@ -12,11 +12,14 @@ t.test('load each command', t => { t.plan(cmdList.length) for (const cmd of cmdList.sort((a, b) => a.localeCompare(b))) { t.test(cmd, t => { - t.plan(3) const impl = npm.commands[cmd] + if (impl.completion) { + t.plan(3) + t.isa(impl.completion, 'function', 'completion, if present, is a function') + } else + t.plan(2) t.isa(impl, 'function', 'implementation is a function') t.isa(impl.usage, 'string', 'usage is a string') - t.isa(impl.completion, 'function', 'completion is a function') }) } }) diff --git a/test/lib/org.js b/test/lib/org.js index 68e3c9f0d..1e8aabc1d 100644 --- a/test/lib/org.js +++ b/test/lib/org.js @@ -49,13 +49,8 @@ const org = requireInject('../../lib/org.js', { }) 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 completion = (argv) => + org.completion({ conf: { argv: { remain: argv } } }) const assertions = [ [['npm', 'org'], ['set', 'rm', 'ls']], @@ -66,7 +61,7 @@ test('completion', async t => { ] for (const [argv, expected] of assertions) - t.strictSame(await completion(argv), expected, `completion for: ${argv.join(', ')}`) + t.resolveMatch(completion(argv), expected, `completion for: ${argv.join(', ')}`) t.rejects(completion(['npm', 'org', 'flurb']), /flurb not recognized/, 'errors for unknown subcommand') }) diff --git a/test/lib/owner.js b/test/lib/owner.js index c5f9d646c..aa5e3ee63 100644 --- a/test/lib/owner.js +++ b/test/lib/owner.js @@ -699,29 +699,25 @@ t.test('owner rm <user> no cwd package', t => { }) }) -t.test('completion', t => { +t.test('completion', async t => { const { completion } = owner - const testComp = (argv, expect) => { - completion({ conf: { argv: { remain: argv } } }, (err, res) => { - t.ifError(err) - t.strictSame(res, expect, argv.join(' ')) - }) + const testComp = async (argv, expect) => { + const res = await completion({ conf: { argv: { remain: argv } } }) + t.strictSame(res, expect, argv.join(' ')) } - testComp(['npm', 'foo'], []) - testComp(['npm', 'owner'], [ - 'add', - 'rm', - 'ls', + await Promise.all([ + testComp(['npm', 'foo'], []), + testComp(['npm', 'owner'], ['add', 'rm', 'ls']), + testComp(['npm', 'owner', 'add'], []), + testComp(['npm', 'owner', 'ls'], []), + testComp(['npm', 'owner', 'rm', 'foo'], []), ]) - testComp(['npm', 'owner', 'add'], []) - testComp(['npm', 'owner', 'ls'], []) - testComp(['npm', 'owner', 'rm', 'foo'], []) // npm owner rm completion is async - t.test('completion npm owner rm', t => { - t.plan(3) + t.test('completion npm owner rm', async t => { + t.plan(2) readLocalPkgResponse = '@npmcli/map-workspaces' pacote.packument = async spec => { t.equal(spec.name, readLocalPkgResponse, 'should use package spec') @@ -734,31 +730,21 @@ t.test('completion', t => { pacote.packument = noop }) - completion({ conf: { argv: { remain: ['npm', 'owner', 'rm'] } } }, (err, res) => { - t.ifError(err, 'npm owner rm completion') - t.strictSame( - res, - [ - 'nlf', - 'ruyadorno', - 'darcyclarke', - 'isaacs', - ], - 'should return list of current owners' - ) - }) + const res = await completion({ conf: { argv: { remain: ['npm', 'owner', 'rm'] } } }) + t.strictSame(res, + ['nlf', 'ruyadorno', 'darcyclarke', 'isaacs'], + 'should return list of current owners' + ) }) - t.test('completion npm owner rm no cwd package', t => { - completion({ conf: { argv: { remain: ['npm', 'owner', 'rm'] } } }, (err, res) => { - t.ifError(err, 'npm owner rm completion') - t.strictSame(res, [], 'should have no owners to autocomplete if not cwd package') - t.end() - }) + t.test('completion npm owner rm no cwd package', async t => { + const res = await completion({ conf: { argv: { remain: ['npm', 'owner', 'rm'] } } }) + t.strictSame(res, [], 'should have no owners to autocomplete if not cwd package') + t.end() }) - t.test('completion npm owner rm no owners found', t => { - t.plan(3) + t.test('completion npm owner rm no owners found', async t => { + t.plan(2) readLocalPkgResponse = '@npmcli/map-workspaces' pacote.packument = async spec => { t.equal(spec.name, readLocalPkgResponse, 'should use package spec') @@ -771,10 +757,8 @@ t.test('completion', t => { pacote.packument = noop }) - completion({ conf: { argv: { remain: ['npm', 'owner', 'rm'] } } }, (err, res) => { - t.ifError(err, 'npm owner rm completion') - t.strictSame(res, [], 'should return no owners if not found') - }) + const res = await completion({ conf: { argv: { remain: ['npm', 'owner', 'rm'] } } }) + t.strictSame(res, [], 'should return no owners if not found') }) t.end() diff --git a/test/lib/profile.js b/test/lib/profile.js index 48a558cac..3b2e14003 100644 --- a/test/lib/profile.js +++ b/test/lib/profile.js @@ -1398,17 +1398,16 @@ t.test('unknown subcommand', t => { t.test('completion', t => { const { completion } = profile - const testComp = ({ t, argv, expect, title }) => { - completion({ conf: { argv: { remain: argv } } }, (err, res) => { - if (err) - throw err - - t.strictSame(res, expect, title) - }) + const testComp = async ({ t, argv, expect, title }) => { + t.resolveMatch( + completion({ conf: { argv: { remain: argv } } }), + expect, + title + ) } - t.test('npm profile autocomplete', t => { - testComp({ + t.test('npm profile autocomplete', async t => { + await testComp({ t, argv: ['npm', 'profile'], expect: ['enable-2fa', 'disable-2fa', 'get', 'set'], @@ -1418,8 +1417,8 @@ t.test('completion', t => { t.end() }) - t.test('npm profile enable autocomplete', t => { - testComp({ + t.test('npm profile enable autocomplete', async t => { + await testComp({ t, argv: ['npm', 'profile', 'enable-2fa'], expect: ['auth-and-writes', 'auth-only'], @@ -1429,10 +1428,10 @@ t.test('completion', t => { t.end() }) - t.test('npm profile <subcmd> no autocomplete', t => { + t.test('npm profile <subcmd> no autocomplete', async t => { const noAutocompleteCmds = ['disable-2fa', 'disable-tfa', 'get', 'set'] for (const subcmd of noAutocompleteCmds) { - testComp({ + await testComp({ t, argv: ['npm', 'profile', subcmd], expect: [], @@ -1443,22 +1442,12 @@ t.test('completion', t => { t.end() }) - t.test('npm profile unknown subcommand autocomplete', t => { - completion({ - conf: { - argv: { - remain: ['npm', 'profile', 'asdf'], - }, - }, - }, (err, res) => { - t.match( - err, - /asdf not recognized/, - 'should throw unknown cmd error' - ) - - t.end() - }) + t.test('npm profile unknown subcommand autocomplete', async t => { + t.rejects( + completion({ conf: { argv: { remain: ['npm', 'profile', 'asdf'] } } }), + { message: 'asdf not recognized' }, 'should throw unknown cmd error' + ) + t.end() }) t.end() diff --git a/test/lib/repo.js b/test/lib/repo.js index c4b1b46e7..3367f7c88 100644 --- a/test/lib/repo.js +++ b/test/lib/repo.js @@ -119,14 +119,6 @@ const repo = requireInject('../../lib/repo.js', { '../../lib/utils/open-url.js': openUrl, }) -t.test('completion', t => { - repo.completion({}, (er, res) => { - t.equal(er, null) - t.same(res, []) - t.end() - }) -}) - t.test('open repo urls', t => { const expect = { hostedgit: 'https://github.com/foo/hostedgit', diff --git a/test/lib/restart.js b/test/lib/restart.js index fde798888..a19bfd0d4 100644 --- a/test/lib/restart.js +++ b/test/lib/restart.js @@ -1,5 +1,4 @@ const t = require('tap') const restart = require('../../lib/restart.js') t.isa(restart, Function) -t.equal(restart.completion, require('../../lib/utils/completion/none.js'), 'empty completion') t.equal(restart.usage, 'npm restart [-- <args>]') diff --git a/test/lib/run-script.js b/test/lib/run-script.js index 070f766b4..974202aa8 100644 --- a/test/lib/run-script.js +++ b/test/lib/run-script.js @@ -42,45 +42,29 @@ const { writeFileSync } = require('fs') t.test('completion', t => { const dir = t.testdir() npm.localPrefix = dir - t.test('already have a script name', t => { - runScript.completion({conf: {argv: {remain: ['npm', 'run', 'x']}}}, (er, results) => { - if (er) - throw er - - t.equal(results, undefined) - t.end() - }) + t.test('already have a script name', async t => { + const res = await runScript.completion({conf: {argv: {remain: ['npm', 'run', 'x']}}}) + t.equal(res, undefined) + t.end() }) - t.test('no package.json', t => { - runScript.completion({conf: {argv: {remain: ['npm', 'run']}}}, (er, results) => { - if (er) - throw er - - t.strictSame(results, []) - t.end() - }) + t.test('no package.json', async t => { + const res = await runScript.completion({conf: {argv: {remain: ['npm', 'run']}}}) + t.strictSame(res, []) + t.end() }) - t.test('has package.json, no scripts', t => { + t.test('has package.json, no scripts', async t => { writeFileSync(`${dir}/package.json`, JSON.stringify({})) - runScript.completion({conf: {argv: {remain: ['npm', 'run']}}}, (er, results) => { - if (er) - throw er - - t.strictSame(results, []) - t.end() - }) + const res = await runScript.completion({conf: {argv: {remain: ['npm', 'run']}}}) + t.strictSame(res, []) + t.end() }) - t.test('has package.json, with scripts', t => { + t.test('has package.json, with scripts', async t => { writeFileSync(`${dir}/package.json`, JSON.stringify({ scripts: { hello: 'echo hello', world: 'echo world' }, })) - runScript.completion({conf: {argv: {remain: ['npm', 'run']}}}, (er, results) => { - if (er) - throw er - - t.strictSame(results, ['hello', 'world']) - t.end() - }) + const res = await runScript.completion({conf: {argv: {remain: ['npm', 'run']}}}) + t.strictSame(res, ['hello', 'world']) + t.end() }) t.end() }) diff --git a/test/lib/set-script.js b/test/lib/set-script.js index ab25ba968..196fd3d3e 100644 --- a/test/lib/set-script.js +++ b/test/lib/set-script.js @@ -4,7 +4,6 @@ const setScriptDefault = require('../../lib/set-script.js') const parseJSON = require('json-parse-even-better-errors') test.type(setScriptDefault, 'function', 'command is function') -test.equal(setScriptDefault.completion, require('../../lib/utils/completion/none.js'), 'empty completion') test.equal(setScriptDefault.usage, 'npm set-script [<script>] [<command>]', 'usage matches') test.test('fails on invalid arguments', (t) => { const setScript = requireInject('../../lib/set-script.js', { diff --git a/test/lib/start.js b/test/lib/start.js index 127741275..4f599223d 100644 --- a/test/lib/start.js +++ b/test/lib/start.js @@ -1,5 +1,4 @@ const t = require('tap') const start = require('../../lib/start.js') t.isa(start, Function) -t.equal(start.completion, require('../../lib/utils/completion/none.js'), 'empty completion') t.equal(start.usage, 'npm start [-- <args>]') diff --git a/test/lib/stop.js b/test/lib/stop.js index d015161d2..4e26703c9 100644 --- a/test/lib/stop.js +++ b/test/lib/stop.js @@ -1,5 +1,4 @@ const t = require('tap') const stop = require('../../lib/stop.js') t.isa(stop, Function) -t.equal(stop.completion, require('../../lib/utils/completion/none.js'), 'empty completion') t.equal(stop.usage, 'npm stop [-- <args>]') diff --git a/test/lib/team.js b/test/lib/team.js index c534cc832..9edaf58ee 100644 --- a/test/lib/team.js +++ b/test/lib/team.js @@ -506,66 +506,45 @@ t.test('team rm <scope:team> <user>', t => { t.test('completion', t => { const { completion } = team - t.test('npm team autocomplete', t => { - completion({ + t.test('npm team autocomplete', async t => { + const res = await completion({ conf: { argv: { remain: ['npm', 'team'], }, }, - }, (err, res) => { - if (err) - throw err - - t.strictSame( - res, - ['create', 'destroy', 'add', 'rm', 'ls'], - 'should auto complete with subcommands' - ) - - t.end() }) + t.strictSame( + res, + ['create', 'destroy', 'add', 'rm', 'ls'], + 'should auto complete with subcommands' + ) + t.end() }) t.test('npm team <subcommand> autocomplete', async t => { - const check = (subcmd) => new Promise((res, rej) => - completion({ + for (const subcmd of ['create', 'destroy', 'add', 'rm', 'ls']) { + const res = await completion({ conf: { argv: { remain: ['npm', 'team', subcmd], }, }, - }, (err, response) => { - if (err) - rej(err) - - t.strictSame( - response, - [], - `should not autocomplete ${subcmd} subcommand` - ) - res() - })) - - await ['create', 'destroy', 'add', 'rm', 'ls'].map(check) + }) + t.strictSame( + res, + [], + `should not autocomplete ${subcmd} subcommand` + ) + } }) - t.test('npm team unknown subcommand autocomplete', t => { - completion({ - conf: { - argv: { - remain: ['npm', 'team', 'missing-subcommand'], - }, - }, - }, (err, res) => { - t.match( - err, - /missing-subcommand not recognized/, - 'should throw a a not recognized error' - ) + t.test('npm team unknown subcommand autocomplete', async t => { + t.rejects(completion({conf: {argv: {remain: ['npm', 'team', 'missing-subcommand'] } } }), + {message: 'missing-subcommand not recognized'}, 'should throw a a not recognized error' + ) - t.end() - }) + t.end() }) t.end() diff --git a/test/lib/token.js b/test/lib/token.js index f98881072..6ab841f49 100644 --- a/test/lib/token.js +++ b/test/lib/token.js @@ -48,27 +48,18 @@ test('completion', (t) => { t.plan(5) const testComp = (argv, expect) => { - tokenMock.completion({ conf: { argv: { remain: argv } } }, (err, res) => { - if (err) - throw err - - t.strictSame(res, expect, argv.join(' ')) - }) + t.resolveMatch(tokenMock.completion({ conf: { argv: { remain: argv } } }), expect, argv.join(' ')) } - testComp(['npm', 'token'], [ - 'list', - 'revoke', - 'create', - ]) - + testComp(['npm', 'token'], ['list', 'revoke', 'create']) testComp(['npm', 'token', 'list'], []) testComp(['npm', 'token', 'revoke'], []) testComp(['npm', 'token', 'create'], []) - tokenMock.completion({ conf: { argv: { remain: ['npm', 'token', 'foobar'] } } }, (err) => { - t.match(err, { message: 'foobar not recognized' }) - }) + t.rejects( + tokenMock.completion({ conf: { argv: { remain: ['npm', 'token', 'foobar'] } } }), + { message: 'foobar not recognize' } + ) }) test('token foobar', (t) => { diff --git a/test/lib/unpublish.js b/test/lib/unpublish.js index 11e24714d..c1fbed57e 100644 --- a/test/lib/unpublish.js +++ b/test/lib/unpublish.js @@ -310,16 +310,12 @@ t.test('silent', t => { }) }) -t.test('completion', t => { - const testComp = (t, { completion, argv, partialWord, expect, title }) => - new Promise((resolve, rej) => { - completion({conf: {argv: {remain: argv}}, partialWord}, (er, res) => { - if (er) - rej(er) - t.strictSame(res, expect, title || argv.join(' ')) - resolve() - }) - }) +t.test('completion', async t => { + const testComp = + async (t, { completion, argv, partialWord, expect, title }) => { + const res = await completion({conf: {argv: {remain: argv}}, partialWord}) + t.strictSame(res, expect, title || argv.join(' ')) + } t.test('completing with multiple versions from the registry', async t => { const { completion } = requireInject('../../lib/unpublish.js', { diff --git a/test/lib/utils/completion/installed-deep.js b/test/lib/utils/completion/installed-deep.js index a2a375610..bd61ab428 100644 --- a/test/lib/utils/completion/installed-deep.js +++ b/test/lib/utils/completion/installed-deep.js @@ -11,7 +11,8 @@ const _flatOptions = { return prefix }, } -const installedDeep = requireInject('../../../../lib/utils/completion/installed-deep.js', { +const p = '../../../../lib/utils/completion/installed-deep.js' +const installedDeep = requireInject(p, { '../../../../lib/npm.js': { flatOptions: _flatOptions, get prefix () { @@ -144,7 +145,7 @@ const globalFixture = { }, } -test('get list of package names', (t) => { +test('get list of package names', async t => { const fix = t.testdir({ local: fixture, global: globalFixture, @@ -153,25 +154,23 @@ test('get list of package names', (t) => { prefix = resolve(fix, 'local') globalDir = resolve(fix, 'global/node_modules') - installedDeep(null, (err, res) => { - t.ifError(err, 'should not error out') - t.deepEqual( - res, - [ - ['bar', '-g'], - ['foo', '-g'], - ['a-bar', '-g'], - 'a', 'b', 'c', - 'd', 'e', 'f', - 'g', 'bb', - ], - 'should return list of package names and global flag' - ) - t.end() - }) + const res = await installedDeep(null) + t.deepEqual( + res, + [ + ['bar', '-g'], + ['foo', '-g'], + ['a-bar', '-g'], + 'a', 'b', 'c', + 'd', 'e', 'f', + 'g', 'bb', + ], + 'should return list of package names and global flag' + ) + t.end() }) -test('get list of package names as global', (t) => { +test('get list of package names as global', async t => { const fix = t.testdir({ local: fixture, global: globalFixture, @@ -182,23 +181,21 @@ test('get list of package names as global', (t) => { _flatOptions.global = true - installedDeep(null, (err, res) => { - t.ifError(err, 'should not error out') - t.deepEqual( - res, - [ - 'bar', - 'foo', - 'a-bar', - ], - 'should return list of global packages with no extra flags' - ) - _flatOptions.global = false - t.end() - }) + const res = await installedDeep(null) + t.deepEqual( + res, + [ + 'bar', + 'foo', + 'a-bar', + ], + 'should return list of global packages with no extra flags' + ) + _flatOptions.global = false + t.end() }) -test('limit depth', (t) => { +test('limit depth', async t => { const fix = t.testdir({ local: fixture, global: globalFixture, @@ -209,26 +206,24 @@ test('limit depth', (t) => { _flatOptions.depth = 0 - installedDeep(null, (err, res) => { - t.ifError(err, 'should not error out') - t.deepEqual( - res, - [ - ['bar', '-g'], - ['foo', '-g'], - 'a', 'b', - 'c', 'd', - 'e', 'f', - 'g', - ], - 'should print only packages up to the specified depth' - ) - _flatOptions.depth = 0 - t.end() - }) + const res = await installedDeep(null) + t.deepEqual( + res, + [ + ['bar', '-g'], + ['foo', '-g'], + 'a', 'b', + 'c', 'd', + 'e', 'f', + 'g', + ], + 'should print only packages up to the specified depth' + ) + _flatOptions.depth = 0 + t.end() }) -test('limit depth as global', (t) => { +test('limit depth as global', async t => { const fix = t.testdir({ local: fixture, global: globalFixture, @@ -240,18 +235,16 @@ test('limit depth as global', (t) => { _flatOptions.global = true _flatOptions.depth = 0 - installedDeep(null, (err, res) => { - t.ifError(err, 'should not error out') - t.deepEqual( - res, - [ - 'bar', - 'foo', - ], - 'should reorder so that packages above that level depth goes last' - ) - _flatOptions.global = false - _flatOptions.depth = 0 - t.end() - }) + const res = await installedDeep(null) + t.deepEqual( + res, + [ + 'bar', + 'foo', + ], + 'should reorder so that packages above that level depth goes last' + ) + _flatOptions.global = false + _flatOptions.depth = 0 + t.end() }) diff --git a/test/lib/utils/completion/installed-shallow.js b/test/lib/utils/completion/installed-shallow.js index 1d6369bc7..1da68810b 100644 --- a/test/lib/utils/completion/installed-shallow.js +++ b/test/lib/utils/completion/installed-shallow.js @@ -9,7 +9,7 @@ const installed = requireInject(p, { '../../../../lib/npm.js': npm, }) -t.test('global not set, include globals with -g', t => { +t.test('global not set, include globals with -g', async t => { const dir = t.testdir({ global: { node_modules: { @@ -32,21 +32,17 @@ t.test('global not set, include globals with -g', t => { npm.localDir = resolve(dir, 'local/node_modules') flatOptions.global = false const opt = { conf: { argv: { remain: [] } } } - installed(opt, (er, res) => { - if (er) - throw er - - t.strictSame(res.sort(), [ - '@scope/y -g', - 'x -g', - 'a', - '@scope/b', - ].sort()) - t.end() - }) + const res = await installed(opt) + t.strictSame(res.sort(), [ + '@scope/y -g', + 'x -g', + 'a', + '@scope/b', + ].sort()) + t.end() }) -t.test('global set, include globals and not locals', t => { +t.test('global set, include globals and not locals', async t => { const dir = t.testdir({ global: { node_modules: { @@ -69,16 +65,15 @@ t.test('global set, include globals and not locals', t => { npm.localDir = resolve(dir, 'local/node_modules') flatOptions.global = true const opt = { conf: { argv: { remain: [] } } } - installed(opt, (er, res) => { - t.strictSame(res.sort(), [ - '@scope/y', - 'x', - ].sort()) - t.end() - }) + const res = await installed(opt) + t.strictSame(res.sort(), [ + '@scope/y', + 'x', + ].sort()) + t.end() }) -t.test('more than 3 items in argv, skip it', t => { +t.test('more than 3 items in argv, skip it', async t => { const dir = t.testdir({ global: { node_modules: { @@ -101,11 +96,7 @@ t.test('more than 3 items in argv, skip it', t => { npm.localDir = resolve(dir, 'local/node_modules') flatOptions.global = false const opt = { conf: { argv: { remain: [1, 2, 3, 4, 5, 6] } } } - installed(opt, (er, res) => { - if (er) - throw er - - t.strictSame(res, null) - t.end() - }) + const res = await installed(opt) + t.strictSame(res, null) + t.end() }) diff --git a/test/lib/utils/completion/none.js b/test/lib/utils/completion/none.js deleted file mode 100644 index 70488be07..000000000 --- a/test/lib/utils/completion/none.js +++ /dev/null @@ -1,6 +0,0 @@ -const t = require('tap') -const none = require('../../../../lib/utils/completion/none.js') -none({any: 'thing'}, (er, res) => { - t.equal(er, null) - t.strictSame(res, []) -}) diff --git a/test/lib/utils/lifecycle-cmd.js b/test/lib/utils/lifecycle-cmd.js index 9e45b15e4..3928c1b26 100644 --- a/test/lib/utils/lifecycle-cmd.js +++ b/test/lib/utils/lifecycle-cmd.js @@ -7,7 +7,6 @@ const npm = { } t.test('create a lifecycle command', t => { const cmd = lifecycleCmd(npm, 'asdf') - t.equal(cmd.completion, require('../../../lib/utils/completion/none.js'), 'empty completion') cmd(['some', 'args'], (er, result) => { t.strictSame(result, 'called npm.commands.run') t.end() diff --git a/test/lib/version.js b/test/lib/version.js index 943e14370..a69953bb8 100644 --- a/test/lib/version.js +++ b/test/lib/version.js @@ -73,17 +73,15 @@ t.test('too many args', t => { }) }) -t.test('completion', t => { +t.test('completion', async t => { const { completion } = version - const testComp = (argv, expect) => { - completion({ conf: { argv: { remain: argv } } }, (err, res) => { - t.ifError(err) - t.strictSame(res, expect, argv.join(' ')) - }) + const testComp = async (argv, expect) => { + const res = await completion({ conf: { argv: { remain: argv } } }) + t.strictSame(res, expect, argv.join(' ')) } - testComp(['npm', 'version'], [ + await testComp(['npm', 'version'], [ 'major', 'minor', 'patch', @@ -93,7 +91,7 @@ t.test('completion', t => { 'prerelease', 'from-git', ]) - testComp(['npm', 'version', 'major'], []) + await testComp(['npm', 'version', 'major'], []) t.end() }) diff --git a/test/lib/view.js b/test/lib/view.js index f3e5d97f3..9419ab7ec 100644 --- a/test/lib/view.js +++ b/test/lib/view.js @@ -553,7 +553,7 @@ t.test('throws when unpublished', (t) => { }) }) -t.test('completion', (t) => { +t.test('completion', async t => { const view = requireInject('../../lib/view.js', { '../../lib/npm.js': { flatOptions: { @@ -565,17 +565,14 @@ t.test('completion', (t) => { packument, }, }) - view.completion({ + const res = await view.completion({ conf: { argv: { remain: ['npm', 'view', 'green@1.0.0'] } }, - }, (err, res) => { - if (err) - throw err - t.ok(res, 'returns back fields') - t.end() }) + t.ok(res, 'returns back fields') + t.end() }) -t.test('no registry completion', (t) => { +t.test('no registry completion', async t => { const view = requireInject('../../lib/view.js', { '../../lib/npm.js': { flatOptions: { @@ -583,10 +580,7 @@ t.test('no registry completion', (t) => { }, }, }) - view.completion({ - conf: { argv: { remain: ['npm', 'view'] } }, - }, (err) => { - t.notOk(err, 'there is no package completion') - t.end() - }) + const res = await view.completion({conf: { argv: { remain: ['npm', 'view'] } } }) + t.notOk(res, 'there is no package completion') + t.end() }) |