From 85a8694dd9b4a924a474ba75261914511a216868 Mon Sep 17 00:00:00 2001 From: Gar Date: Sun, 28 Feb 2021 19:00:58 -0800 Subject: [PATCH] fix(npm.output): make output go through npm.output All output that anything wants to make now goes through `npm.output()`. This is an incremental change getting us closer to where we want to be with testing. PR-URL: https://github.com/npm/cli/pull/2795 Credit: @wraithgar Close: #2795 Reviewed-by: @ruyadorno, @isaacs --- lib/access.js | 5 +- lib/adduser.js | 3 +- lib/audit.js | 3 +- lib/bin.js | 3 +- lib/cache.js | 15 +- lib/completion.js | 49 +++-- lib/config.js | 7 +- lib/diff.js | 3 +- lib/dist-tag.js | 7 +- lib/doctor.js | 3 +- lib/exec.js | 3 +- lib/explain.js | 5 +- lib/explore.js | 3 +- lib/fund.js | 7 +- lib/help-search.js | 5 +- lib/help.js | 3 +- lib/hook.js | 39 ++-- lib/init.js | 3 +- lib/ls.js | 3 +- lib/npm.js | 7 + lib/org.js | 25 ++- lib/outdated.js | 7 +- lib/owner.js | 194 +++++++++--------- lib/pack.js | 3 +- lib/ping.js | 3 +- lib/prefix.js | 3 +- lib/profile.js | 37 ++-- lib/publish.js | 5 +- lib/rebuild.js | 3 +- lib/root.js | 3 +- lib/run-script.js | 15 +- lib/search.js | 5 +- lib/star.js | 3 +- lib/stars.js | 3 +- lib/team.js | 41 ++-- lib/token.js | 21 +- lib/unpublish.js | 3 +- lib/utils/audit-error.js | 5 +- lib/utils/npm-usage.js | 5 +- lib/utils/open-url.js | 3 +- lib/utils/output.js | 7 - lib/utils/reify-output.js | 17 +- lib/version.js | 7 +- lib/whoami.js | 3 +- tap-snapshots/test-lib-profile.js-TAP.test.js | 18 +- test/lib/access.js | 16 +- test/lib/adduser.js | 6 +- test/lib/audit.js | 14 +- test/lib/bin.js | 35 ++-- test/lib/cache.js | 11 +- test/lib/completion.js | 6 +- test/lib/config.js | 6 +- test/lib/diff.js | 2 +- test/lib/dist-tag.js | 6 +- test/lib/doctor.js | 12 +- test/lib/exec.js | 2 +- test/lib/explain.js | 6 +- test/lib/explore.js | 6 +- test/lib/fund.js | 6 +- test/lib/help-search.js | 2 +- test/lib/help.js | 10 +- test/lib/hook.js | 8 +- test/lib/init.js | 6 +- test/lib/ls.js | 13 +- test/lib/org.js | 9 +- test/lib/outdated.js | 19 +- test/lib/owner.js | 10 +- test/lib/pack.js | 8 +- test/lib/ping.js | 16 +- test/lib/prefix.js | 12 +- test/lib/profile.js | 11 +- test/lib/publish.js | 21 +- test/lib/rebuild.js | 9 +- test/lib/root.js | 12 +- test/lib/run-script.js | 2 +- test/lib/search.js | 10 +- test/lib/star.js | 11 +- test/lib/stars.js | 11 +- test/lib/team.js | 10 +- test/lib/token.js | 13 +- test/lib/unpublish.js | 6 +- test/lib/utils/audit-error.js | 12 +- test/lib/utils/npm-usage.js | 6 +- test/lib/utils/open-url.js | 7 +- test/lib/utils/output.js | 8 - test/lib/utils/reify-output.js | 92 ++++----- test/lib/version.js | 11 +- test/lib/whoami.js | 12 +- 88 files changed, 541 insertions(+), 585 deletions(-) delete mode 100644 lib/utils/output.js delete mode 100644 test/lib/utils/output.js diff --git a/lib/access.js b/lib/access.js index e11934af43ebc..3bc21119033f5 100644 --- a/lib/access.js +++ b/lib/access.js @@ -3,7 +3,6 @@ const path = require('path') const libaccess = require('libnpmaccess') const readPackageJson = require('read-package-json-fast') -const output = require('./utils/output.js') const otplease = require('./utils/otplease.js') const usageUtil = require('./utils/usage.js') const getIdentity = require('./utils/get-identity.js') @@ -157,7 +156,7 @@ class Access { const pkgs = await libaccess.lsPackages(owner, opts) // TODO - print these out nicely (breaking change) - output(JSON.stringify(pkgs, null, 2)) + this.npm.output(JSON.stringify(pkgs, null, 2)) } get ['ls-collaborators'] () { @@ -169,7 +168,7 @@ class Access { const collabs = await libaccess.lsCollaborators(pkgName, usr, opts) // TODO - print these out nicely (breaking change) - output(JSON.stringify(collabs, null, 2)) + this.npm.output(JSON.stringify(collabs, null, 2)) } async edit () { diff --git a/lib/adduser.js b/lib/adduser.js index dac0f5a46840d..45d602fd2c844 100644 --- a/lib/adduser.js +++ b/lib/adduser.js @@ -1,5 +1,4 @@ const log = require('npmlog') -const output = require('./utils/output.js') const usageUtil = require('./utils/usage.js') const replaceInfo = require('./utils/replace-info.js') const authTypes = { @@ -49,7 +48,7 @@ class AddUser { scope, }) - output(message) + this.npm.output(message) } getRegistry ({ scope, registry }) { diff --git a/lib/audit.js b/lib/audit.js index dfa01cb2709fa..b8c85605dba43 100644 --- a/lib/audit.js +++ b/lib/audit.js @@ -1,6 +1,5 @@ const Arborist = require('@npmcli/arborist') const auditReport = require('npm-audit-report') -const output = require('./utils/output.js') const reifyFinish = require('./utils/reify-finish.js') const auditError = require('./utils/audit-error.js') const usageUtil = require('./utils/usage.js') @@ -57,7 +56,7 @@ class Audit { reporter, }) process.exitCode = process.exitCode || result.exitCode - output(result.report) + this.npm.output(result.report) } } } diff --git a/lib/bin.js b/lib/bin.js index 11490c41cbcc5..f540cc57c8cd7 100644 --- a/lib/bin.js +++ b/lib/bin.js @@ -1,4 +1,3 @@ -const output = require('./utils/output.js') const envPath = require('./utils/path.js') const usageUtil = require('./utils/usage.js') @@ -18,7 +17,7 @@ class Bin { async bin (args) { const b = this.npm.bin - output(b) + this.npm.output(b) if (this.npm.flatOptions.global && !envPath.includes(b)) console.error('(not in PATH env variable)') } diff --git a/lib/cache.js b/lib/cache.js index 8469559764fb3..3ca99fd2562e3 100644 --- a/lib/cache.js +++ b/lib/cache.js @@ -1,7 +1,6 @@ const cacache = require('cacache') const { promisify } = require('util') const log = require('npmlog') -const output = require('./utils/output.js') const pacote = require('pacote') const path = require('path') const rimraf = promisify(require('rimraf')) @@ -116,13 +115,13 @@ with --force.`) ? `~${cache.substr(process.env.HOME.length)}` : cache const stats = await cacache.verify(cache) - output(`Cache verified and compressed (${prefix})`) - output(`Content verified: ${stats.verifiedContent} (${stats.keptSize} bytes)`) - stats.badContentCount && output(`Corrupted content removed: ${stats.badContentCount}`) - stats.reclaimedCount && output(`Content garbage-collected: ${stats.reclaimedCount} (${stats.reclaimedSize} bytes)`) - stats.missingContent && output(`Missing content: ${stats.missingContent}`) - output(`Index entries: ${stats.totalEntries}`) - output(`Finished in ${stats.runTime.total / 1000}s`) + this.npm.output(`Cache verified and compressed (${prefix})`) + this.npm.output(`Content verified: ${stats.verifiedContent} (${stats.keptSize} bytes)`) + stats.badContentCount && this.npm.output(`Corrupted content removed: ${stats.badContentCount}`) + stats.reclaimedCount && this.npm.output(`Content garbage-collected: ${stats.reclaimedCount} (${stats.reclaimedSize} bytes)`) + stats.missingContent && this.npm.output(`Missing content: ${stats.missingContent}`) + this.npm.output(`Index entries: ${stats.totalEntries}`) + this.npm.output(`Finished in ${stats.runTime.total / 1000}s`) } } diff --git a/lib/completion.js b/lib/completion.js index 4c37e6ef354ef..5baf17665800d 100644 --- a/lib/completion.js +++ b/lib/completion.js @@ -39,7 +39,6 @@ const configNames = Object.keys(types) const shorthandNames = Object.keys(shorthands) const allConfs = configNames.concat(shorthandNames) const isWindowsShell = require('./utils/is-windows-shell.js') -const output = require('./utils/output.js') const fileExists = require('./utils/file-exists.js') const usageUtil = require('./utils/usage.js') @@ -131,14 +130,14 @@ class Completion { if (partialWords.slice(0, -1).indexOf('--') === -1) { if (word.charAt(0) === '-') - return wrap(opts, configCompl(opts)) + return this.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(opts, configValueCompl(opts)) + return this.wrap(opts, configValueCompl(opts)) } } @@ -152,7 +151,7 @@ class Completion { // check if there's a command already. const cmd = parsed.argv.remain[1] if (!cmd) - return wrap(opts, cmdCompl(opts)) + return this.wrap(opts, cmdCompl(opts)) Object.keys(parsed).forEach(k => this.npm.config.set(k, parsed[k])) @@ -162,9 +161,29 @@ class Completion { const impl = this.npm.commands[cmd] if (impl && impl.completion) { const comps = await impl.completion(opts) - return wrap(opts, comps) + return this.wrap(opts, comps) } } + + // The command should respond with an array. Loop over that, + // wrapping quotes around any that have spaces, and writing + // them to stdout. + // 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' + wrap (opts, compls) { + if (!Array.isArray(compls)) + compls = compls ? [compls] : [] + + compls = compls.map(c => + Array.isArray(c) ? c.map(escape).join(' ') : escape(c)) + + if (opts.partialWord) + compls = compls.filter(c => c.startsWith(opts.partialWord)) + + if (compls.length > 0) + this.npm.output(compls.join('\n')) + } } const dumpScript = async () => { @@ -214,26 +233,6 @@ const unescape = w => w.charAt(0) === '\'' ? w.replace(/^'|'$/g, '') const escape = w => !/\s+/.test(w) ? w : '\'' + w + '\'' -// The command should respond with an array. Loop over that, -// wrapping quotes around any that have spaces, and writing -// them to stdout. -// 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 wrap = (opts, compls) => { - if (!Array.isArray(compls)) - compls = compls ? [compls] : [] - - compls = compls.map(c => - Array.isArray(c) ? c.map(escape).join(' ') : escape(c)) - - if (opts.partialWord) - compls = compls.filter(c => c.startsWith(opts.partialWord)) - - if (compls.length > 0) - output(compls.join('\n')) -} - // the current word has a dash. Return the config names, // with the same number of dashes as the current word has. const configCompl = opts => { diff --git a/lib/config.js b/lib/config.js index 2805db9b80ec7..7009f46016d23 100644 --- a/lib/config.js +++ b/lib/config.js @@ -1,6 +1,5 @@ const { defaults, types } = require('./utils/config.js') const usageUtil = require('./utils/usage.js') -const output = require('./utils/output.js') const mkdirp = require('mkdirp-infer-owner') const { dirname } = require('path') @@ -142,7 +141,7 @@ class Config { const pref = keys.length > 1 ? `${key}=` : '' out.push(pref + this.npm.config.get(key)) } - output(out.join('\n')) + this.npm.output(out.join('\n')) } async del (keys) { @@ -241,7 +240,7 @@ ${defData} ) } - output(msg.join('\n').trim()) + this.npm.output(msg.join('\n').trim()) } async listJson () { @@ -252,7 +251,7 @@ ${defData} publicConf[key] = this.npm.config.get(key) } - output(JSON.stringify(publicConf, null, 2)) + this.npm.output(JSON.stringify(publicConf, null, 2)) } usageError () { diff --git a/lib/diff.js b/lib/diff.js index 859e6f76feeef..ed36a30673c43 100644 --- a/lib/diff.js +++ b/lib/diff.js @@ -9,7 +9,6 @@ const pacote = require('pacote') const pickManifest = require('npm-pick-manifest') const usageUtil = require('./utils/usage.js') -const output = require('./utils/output.js') const readLocalPkg = require('./utils/read-local-package.js') class Diff { @@ -55,7 +54,7 @@ class Diff { diffFiles: args, where: this.where, }) - return output(res) + return this.npm.output(res) } async retrieveSpecs ([a, b]) { diff --git a/lib/dist-tag.js b/lib/dist-tag.js index 171a88c527e5d..4b7e2602043be 100644 --- a/lib/dist-tag.js +++ b/lib/dist-tag.js @@ -3,7 +3,6 @@ const npa = require('npm-package-arg') const regFetch = require('npm-registry-fetch') const semver = require('semver') -const output = require('./utils/output.js') const otplease = require('./utils/otplease.js') const readLocalPkgName = require('./utils/read-local-package.js') const usageUtil = require('./utils/usage.js') @@ -91,7 +90,7 @@ class DistTag { spec, } await otplease(reqOpts, reqOpts => regFetch(url, reqOpts)) - output(`+${t}: ${spec.name}@${version}`) + this.npm.output(`+${t}: ${spec.name}@${version}`) } async remove (spec, tag, opts) { @@ -116,7 +115,7 @@ class DistTag { spec, } await otplease(reqOpts, reqOpts => regFetch(url, reqOpts)) - output(`-${tag}: ${spec.name}@${version}`) + this.npm.output(`-${tag}: ${spec.name}@${version}`) } async list (spec, opts) { @@ -133,7 +132,7 @@ class DistTag { const tags = await this.fetchTags(spec, opts) const msg = Object.keys(tags).map(k => `${k}: ${tags[k]}`).sort().join('\n') - output(msg) + this.npm.output(msg) return tags } catch (err) { log.error('dist-tag ls', "Couldn't get dist-tag data for", spec) diff --git a/lib/doctor.js b/lib/doctor.js index 81860004e344e..63619d0cf5377 100644 --- a/lib/doctor.js +++ b/lib/doctor.js @@ -10,7 +10,6 @@ const semver = require('semver') const { promisify } = require('util') const ansiTrim = require('./utils/ansi-trim.js') const isWindows = require('./utils/is-windows.js') -const output = require('./utils/output.js') const ping = require('./utils/ping.js') const usageUtil = require('./utils/usage.js') const { defaults: { registry: defaultRegistry } } = require('./utils/config.js') @@ -111,7 +110,7 @@ class Doctor { const silent = this.npm.log.levels[this.npm.log.level] > this.npm.log.levels.error if (!silent) { - output(table(outTable, tableOpts)) + this.npm.output(table(outTable, tableOpts)) if (!allOk) console.error('') } diff --git a/lib/exec.js b/lib/exec.js index d1db49128587e..69c3cfe75c2cc 100644 --- a/lib/exec.js +++ b/lib/exec.js @@ -1,4 +1,3 @@ -const output = require('./utils/output.js') const usageUtil = require('./utils/usage.js') const { promisify } = require('util') const read = promisify(require('read')) @@ -224,7 +223,7 @@ class Exec { if (process.stdin.isTTY) { if (ciDetect()) return this.npm.log.warn('exec', 'Interactive mode disabled in CI environment') - output(`\nEntering npm script environment\nType 'exit' or ^D when finished\n`) + this.npm.output(`\nEntering npm script environment\nType 'exit' or ^D when finished\n`) } } return await runScript({ diff --git a/lib/explain.js b/lib/explain.js index 01541040ef649..f46d3b5072637 100644 --- a/lib/explain.js +++ b/lib/explain.js @@ -1,7 +1,6 @@ const usageUtil = require('./utils/usage.js') const { explainNode } = require('./utils/explain-dep.js') const completion = require('./utils/completion/installed-deep.js') -const output = require('./utils/output.js') const Arborist = require('@npmcli/arborist') const npa = require('npm-package-arg') const semver = require('semver') @@ -59,9 +58,9 @@ class Explain { } if (this.npm.flatOptions.json) - output(JSON.stringify(expls, null, 2)) + this.npm.output(JSON.stringify(expls, null, 2)) else { - output(expls.map(expl => { + this.npm.output(expls.map(expl => { return explainNode(expl, Infinity, this.npm.color) }).join('\n\n')) } diff --git a/lib/explore.js b/lib/explore.js index fdfe6e1bcf7c8..e09e867406e1d 100644 --- a/lib/explore.js +++ b/lib/explore.js @@ -5,7 +5,6 @@ const rpj = require('read-package-json-fast') const runScript = require('@npmcli/run-script') const { join, resolve, relative } = require('path') const completion = require('./utils/completion/installed-shallow.js') -const output = require('./utils/output.js') const usageUtil = require('./utils/usage.js') class Explore { @@ -54,7 +53,7 @@ class Explore { } if (!args.length) - output(`\nExploring ${path}\nType 'exit' or ^D when finished\n`) + this.npm.output(`\nExploring ${path}\nType 'exit' or ^D when finished\n`) this.npm.log.disableProgress() try { return await runScript({ diff --git a/lib/fund.js b/lib/fund.js index 1e9724266401f..826c3170e7e8a 100644 --- a/lib/fund.js +++ b/lib/fund.js @@ -12,7 +12,6 @@ const { } = require('libnpmfund') const completion = require('./utils/completion/installed-deep.js') -const output = require('./utils/output.js') const openUrl = require('./utils/open-url.js') const usageUtil = require('./utils/usage.js') @@ -85,7 +84,7 @@ class Fund { ? this.printJSON : this.printHuman - output( + this.npm.output( print( getFundingInfo(tree), opts @@ -206,9 +205,9 @@ class Fund { validSources.forEach(({ type, url }, i) => { const typePrefix = type ? `${type} funding` : 'Funding' const msg = `${typePrefix} available at the following URL` - output(`${i + 1}: ${msg}: ${url}`) + this.npm.output(`${i + 1}: ${msg}: ${url}`) }) - output('Run `npm fund [<@scope>/] --which=1`, for example, to open the first funding URL listed in that package') + this.npm.output('Run `npm fund [<@scope>/] --which=1`, for example, to open the first funding URL listed in that package') } else { const noFundingError = new Error(`No valid funding method available for: ${spec}`) noFundingError.code = 'ENOFUND' diff --git a/lib/help-search.js b/lib/help-search.js index ed2bc23b9109d..9648e3b1478d5 100644 --- a/lib/help-search.js +++ b/lib/help-search.js @@ -1,7 +1,6 @@ const fs = require('fs') const path = require('path') const color = require('ansicolors') -const output = require('./utils/output.js') const usageUtil = require('./utils/usage.js') const npmUsage = require('./utils/npm-usage.js') const { promisify } = require('util') @@ -44,8 +43,8 @@ class HelpSearch { if (!formatted.trim()) npmUsage(this.npm, false) else { - output(formatted) - output(didYouMean(args[0], cmdList)) + this.npm.output(formatted) + this.npm.output(didYouMean(args[0], cmdList)) } } diff --git a/lib/help.js b/lib/help.js index d7897326f3118..ef7e3bfd03214 100644 --- a/lib/help.js +++ b/lib/help.js @@ -4,7 +4,6 @@ const path = require('path') const log = require('npmlog') const openUrl = require('./utils/open-url.js') const glob = require('glob') -const output = require('./utils/output.js') const usage = require('./utils/usage.js') @@ -70,7 +69,7 @@ class Help { this.npm.commands[section].usage) { this.npm.config.set('loglevel', 'silent') log.level = 'silent' - output(this.npm.commands[section].usage) + this.npm.output(this.npm.commands[section].usage) return } diff --git a/lib/hook.js b/lib/hook.js index 312f542d7cff6..a6f04d6532e50 100644 --- a/lib/hook.js +++ b/lib/hook.js @@ -1,5 +1,4 @@ const hookApi = require('libnpmhook') -const output = require('./utils/output.js') const otplease = require('./utils/otplease.js') const relativeDate = require('tiny-relative-date') const Table = require('cli-table3') @@ -44,12 +43,12 @@ class Hook { async add (pkg, uri, secret, opts) { const hook = await hookApi.add(pkg, uri, secret, opts) if (opts.json) - output(JSON.stringify(hook, null, 2)) + this.npm.output(JSON.stringify(hook, null, 2)) else if (opts.parseable) { - output(Object.keys(hook).join('\t')) - output(Object.keys(hook).map(k => hook[k]).join('\t')) + this.npm.output(Object.keys(hook).join('\t')) + this.npm.output(Object.keys(hook).map(k => hook[k]).join('\t')) } else if (!opts.silent && opts.loglevel !== 'silent') { - output(`+ ${this.hookName(hook)} ${ + this.npm.output(`+ ${this.hookName(hook)} ${ opts.unicode ? ' ➜ ' : ' -> ' } ${hook.endpoint}`) } @@ -58,19 +57,19 @@ class Hook { async ls (pkg, opts) { const hooks = await hookApi.ls({ ...opts, package: pkg }) if (opts.json) - output(JSON.stringify(hooks, null, 2)) + this.npm.output(JSON.stringify(hooks, null, 2)) else if (opts.parseable) { - output(Object.keys(hooks[0]).join('\t')) + this.npm.output(Object.keys(hooks[0]).join('\t')) hooks.forEach(hook => { - output(Object.keys(hook).map(k => hook[k]).join('\t')) + this.npm.output(Object.keys(hook).map(k => hook[k]).join('\t')) }) } else if (!hooks.length) - output("You don't have any hooks configured yet.") + this.npm.output("You don't have any hooks configured yet.") else if (!opts.silent && opts.loglevel !== 'silent') { if (hooks.length === 1) - output('You have one hook configured.') + this.npm.output('You have one hook configured.') else - output(`You have ${hooks.length} hooks configured.`) + this.npm.output(`You have ${hooks.length} hooks configured.`) const table = new Table({ head: ['id', 'target', 'endpoint'] }) hooks.forEach((hook) => { @@ -90,19 +89,19 @@ class Hook { } else table.push([{ colSpan: 2, content: 'never triggered' }]) }) - output(table.toString()) + this.npm.output(table.toString()) } } async rm (id, opts) { const hook = await hookApi.rm(id, opts) if (opts.json) - output(JSON.stringify(hook, null, 2)) + this.npm.output(JSON.stringify(hook, null, 2)) else if (opts.parseable) { - output(Object.keys(hook).join('\t')) - output(Object.keys(hook).map(k => hook[k]).join('\t')) + this.npm.output(Object.keys(hook).join('\t')) + this.npm.output(Object.keys(hook).map(k => hook[k]).join('\t')) } else if (!opts.silent && opts.loglevel !== 'silent') { - output(`- ${this.hookName(hook)} ${ + this.npm.output(`- ${this.hookName(hook)} ${ opts.unicode ? ' ✘ ' : ' X ' } ${hook.endpoint}`) } @@ -111,12 +110,12 @@ class Hook { async update (id, uri, secret, opts) { const hook = await hookApi.update(id, uri, secret, opts) if (opts.json) - output(JSON.stringify(hook, null, 2)) + this.npm.output(JSON.stringify(hook, null, 2)) else if (opts.parseable) { - output(Object.keys(hook).join('\t')) - output(Object.keys(hook).map(k => hook[k]).join('\t')) + this.npm.output(Object.keys(hook).join('\t')) + this.npm.output(Object.keys(hook).map(k => hook[k]).join('\t')) } else if (!opts.silent && opts.loglevel !== 'silent') { - output(`+ ${this.hookName(hook)} ${ + this.npm.output(`+ ${this.hookName(hook)} ${ opts.unicode ? ' ➜ ' : ' -> ' } ${hook.endpoint}`) } diff --git a/lib/init.js b/lib/init.js index af97a9614e368..3f9abbcdd354d 100644 --- a/lib/init.js +++ b/lib/init.js @@ -2,7 +2,6 @@ const initJson = require('init-package-json') const npa = require('npm-package-arg') const usageUtil = require('./utils/usage.js') -const output = require('./utils/output.js') class Init { constructor (npm) { @@ -61,7 +60,7 @@ class Init { this.npm.log.disableProgress() const initFile = this.npm.config.get('init-module') if (!this.npm.flatOptions.yes && !this.npm.flatOptions.force) { - output([ + this.npm.output([ 'This utility will walk you through creating a package.json file.', 'It only covers the most common items, and tries to guess sensible defaults.', '', diff --git a/lib/ls.js b/lib/ls.js index 359fe21e6f8cc..b94684401e6f6 100644 --- a/lib/ls.js +++ b/lib/ls.js @@ -9,7 +9,6 @@ const npa = require('npm-package-arg') const usageUtil = require('./utils/usage.js') const completion = require('./utils/completion/installed-deep.js') -const output = require('./utils/output.js') const _depth = Symbol('depth') const _dedupe = Symbol('dedupe') @@ -147,7 +146,7 @@ class LS { const [rootError] = tree.errors.filter(e => e.code === 'EJSONPARSE' && e.path === resolve(path, 'package.json')) - output( + this.npm.output( json ? jsonOutput({ path, problems, result, rootError, seenItems }) : parseable diff --git a/lib/npm.js b/lib/npm.js index 1f8c785e755c4..0534e630606e4 100644 --- a/lib/npm.js +++ b/lib/npm.js @@ -282,6 +282,13 @@ const npm = module.exports = new class extends EventEmitter { } return resolve(this.config.get('tmp'), this[_tmpFolder]) } + + // output to stdout in a progress bar compatible way + output (...msg) { + this.log.clearProgress() + console.log(...msg) + this.log.showProgress() + } }() // now load everything required by the class methods diff --git a/lib/org.js b/lib/org.js index 054e1833dba4b..2a08941a83f3a 100644 --- a/lib/org.js +++ b/lib/org.js @@ -1,6 +1,5 @@ const liborg = require('libnpmorg') const usageUtil = require('./utils/usage.js') -const output = require('./utils/output.js') const otplease = require('./utils/otplease.js') const Table = require('cli-table3') @@ -72,17 +71,17 @@ class Org { return liborg.set(org, user, role, opts).then(memDeets => { if (opts.json) - output(JSON.stringify(memDeets, null, 2)) + this.npm.output(JSON.stringify(memDeets, null, 2)) else if (opts.parseable) { - output(['org', 'orgsize', 'user', 'role'].join('\t')) - output([ + this.npm.output(['org', 'orgsize', 'user', 'role'].join('\t')) + this.npm.output([ memDeets.org.name, 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 have ${memDeets.org.size} member${memDeets.org.size === 1 ? '' : 's'} in this org.`) + this.npm.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 }) @@ -102,17 +101,17 @@ class Org { org = org.replace(/^[~@]?/, '') const userCount = Object.keys(roster).length if (opts.json) { - output(JSON.stringify({ + this.npm.output(JSON.stringify({ user, org, userCount, deleted: true, })) } else if (opts.parseable) { - output(['user', 'org', 'userCount', 'deleted'].join('\t')) - output([user, org, userCount, true].join('\t')) + this.npm.output(['user', 'org', 'userCount', 'deleted'].join('\t')) + this.npm.output([user, org, userCount, true].join('\t')) } else if (!opts.silent && opts.loglevel !== 'silent') - output(`Successfully removed ${user} from ${org}. You now have ${userCount} member${userCount === 1 ? '' : 's'} in this org.`) + this.npm.output(`Successfully removed ${user} from ${org}. You now have ${userCount} member${userCount === 1 ? '' : 's'} in this org.`) }) } @@ -129,18 +128,18 @@ class Org { roster = newRoster } if (opts.json) - output(JSON.stringify(roster, null, 2)) + this.npm.output(JSON.stringify(roster, null, 2)) else if (opts.parseable) { - output(['user', 'role'].join('\t')) + this.npm.output(['user', 'role'].join('\t')) Object.keys(roster).forEach(user => { - output([user, roster[user]].join('\t')) + this.npm.output([user, roster[user]].join('\t')) }) } else if (!opts.silent && opts.loglevel !== 'silent') { const table = new Table({ head: ['user', 'role'] }) Object.keys(roster).sort().forEach(user => { table.push([user, roster[user]]) }) - output(table.toString()) + this.npm.output(table.toString()) } }) } diff --git a/lib/outdated.js b/lib/outdated.js index fc6967faf60fe..be5820870411c 100644 --- a/lib/outdated.js +++ b/lib/outdated.js @@ -9,7 +9,6 @@ const pickManifest = require('npm-pick-manifest') const Arborist = require('@npmcli/arborist') -const output = require('./utils/output.js') const usageUtil = require('./utils/usage.js') const ansiTrim = require('./utils/ansi-trim.js') @@ -75,9 +74,9 @@ class Outdated { // display results if (this.opts.json) - output(this.makeJSON(outdated)) + this.npm.output(this.makeJSON(outdated)) else if (this.opts.parseable) - output(this.makeParseable(outdated)) + this.npm.output(this.makeParseable(outdated)) else { const outList = outdated.map(x => this.makePretty(x)) const outHead = ['Package', @@ -99,7 +98,7 @@ class Outdated { align: ['l', 'r', 'r', 'r', 'l'], stringLength: s => ansiTrim(s).length, } - output(table(outTable, tableOpts)) + this.npm.output(table(outTable, tableOpts)) } } diff --git a/lib/owner.js b/lib/owner.js index 6cb9904880dc2..cd387e94d9eaf 100644 --- a/lib/owner.js +++ b/lib/owner.js @@ -3,7 +3,6 @@ const npa = require('npm-package-arg') const npmFetch = require('npm-registry-fetch') const pacote = require('pacote') -const output = require('./utils/output.js') const otplease = require('./utils/otplease.js') const readLocalPkg = require('./utils/read-local-package.js') const usageUtil = require('./utils/usage.js') @@ -89,9 +88,9 @@ class Owner { const packumentOpts = { ...opts, fullMetadata: true } const { maintainers } = await pacote.packument(spec, packumentOpts) if (!maintainers || !maintainers.length) - output('no admin found') + this.npm.output('no admin found') else - output(maintainers.map(o => `${o.name} <${o.email}>`).join('\n')) + this.npm.output(maintainers.map(o => `${o.name} <${o.email}>`).join('\n')) return maintainers } catch (err) { @@ -114,7 +113,8 @@ class Owner { log.verbose('owner add', '%s to %s', user, pkg) const spec = npa(pkg) - return putOwners(spec, user, opts, validateAddOwner) + return this.putOwners(spec, user, opts, + (newOwner, owners) => this.validateAddOwner(newOwner, owners)) } async rm (user, pkg, opts) { @@ -131,109 +131,111 @@ class Owner { log.verbose('owner rm', '%s from %s', user, pkg) const spec = npa(pkg) - return putOwners(spec, user, opts, validateRmOwner) + return this.putOwners(spec, user, opts, + (rmOwner, owners) => this.validateRmOwner(rmOwner, owners)) } -} -module.exports = Owner -const validateAddOwner = (newOwner, owners) => { - owners = owners || [] - for (const o of owners) { - if (o.name === newOwner.name) { - log.info( - 'owner add', - 'Already a package owner: ' + o.name + ' <' + o.email + '>' - ) - return false - } - } - return [ - ...owners, - newOwner, - ] -} - -const validateRmOwner = (rmOwner, owners) => { - let found = false - const m = owners.filter(function (o) { - var match = (o.name === rmOwner.name) - found = found || match - return !match - }) - - if (!found) { - log.info('owner rm', 'Not a package owner: ' + rmOwner.name) - return false - } + async putOwners (spec, user, opts, validation) { + const uri = `/-/user/org.couchdb.user:${encodeURIComponent(user)}` + let u = '' - if (!m.length) { - throw Object.assign( - new Error( - 'Cannot remove all owners of a package. Add someone else first.' - ), - { code: 'EOWNERRM' } - ) - } + try { + u = await npmFetch.json(uri, opts) + } catch (err) { + log.error('owner mutate', `Error getting user data for ${user}`) + throw err + } - return m -} + if (user && (!u || !u.name || u.error)) { + throw Object.assign( + new Error( + "Couldn't get user data for " + user + ': ' + JSON.stringify(u) + ), + { code: 'EOWNERUSER' } + ) + } -const putOwners = async (spec, user, opts, validation) => { - const uri = `/-/user/org.couchdb.user:${encodeURIComponent(user)}` - let u = '' + // normalize user data + u = { name: u.name, email: u.email } - try { - u = await npmFetch.json(uri, opts) - } catch (err) { - log.error('owner mutate', `Error getting user data for ${user}`) - throw err - } + const data = await pacote.packument(spec, { ...opts, fullMetadata: true }) - if (user && (!u || !u.name || u.error)) { - throw Object.assign( - new Error( - "Couldn't get user data for " + user + ': ' + JSON.stringify(u) - ), - { code: 'EOWNERUSER' } - ) - } + // save the number of maintainers before validation for comparison + const before = data.maintainers ? data.maintainers.length : 0 - // normalize user data - u = { name: u.name, email: u.email } + const m = validation(u, data.maintainers) + if (!m) + return // invalid owners - const data = await pacote.packument(spec, { ...opts, fullMetadata: true }) + const body = { + _id: data._id, + _rev: data._rev, + maintainers: m, + } + const dataPath = `/${spec.escapedName}/-rev/${encodeURIComponent(data._rev)}` + const res = await otplease(opts, opts => { + return npmFetch.json(dataPath, { + ...opts, + method: 'PUT', + body, + spec, + }) + }) - // save the number of maintainers before validation for comparison - const before = data.maintainers ? data.maintainers.length : 0 + if (!res.error) { + if (m.length < before) + this.npm.output(`- ${user} (${spec.name})`) + else + this.npm.output(`+ ${user} (${spec.name})`) + } else { + throw Object.assign( + new Error('Failed to update package: ' + JSON.stringify(res)), + { code: 'EOWNERMUTATE' } + ) + } + return res + } + + validateAddOwner (newOwner, owners) { + owners = owners || [] + for (const o of owners) { + if (o.name === newOwner.name) { + log.info( + 'owner add', + 'Already a package owner: ' + o.name + ' <' + o.email + '>' + ) + return false + } + } + return [ + ...owners, + newOwner, + ] + } + + validateRmOwner (rmOwner, owners) { + let found = false + const m = owners.filter(function (o) { + var match = (o.name === rmOwner.name) + found = found || match + return !match + }) + + if (!found) { + log.info('owner rm', 'Not a package owner: ' + rmOwner.name) + return false + } - const m = validation(u, data.maintainers) - if (!m) - return // invalid owners + if (!m.length) { + throw Object.assign( + new Error( + 'Cannot remove all owners of a package. Add someone else first.' + ), + { code: 'EOWNERRM' } + ) + } - const body = { - _id: data._id, - _rev: data._rev, - maintainers: m, - } - const dataPath = `/${spec.escapedName}/-rev/${encodeURIComponent(data._rev)}` - const res = await otplease(opts, opts => - npmFetch.json(dataPath, { - ...opts, - method: 'PUT', - body, - spec, - })) - - if (!res.error) { - if (m.length < before) - output(`- ${user} (${spec.name})`) - else - output(`+ ${user} (${spec.name})`) - } else { - throw Object.assign( - new Error('Failed to update package: ' + JSON.stringify(res)), - { code: 'EOWNERMUTATE' } - ) + return m } - return res } +module.exports = Owner diff --git a/lib/pack.js b/lib/pack.js index cf1e77f48ee69..7ffe3138ed55f 100644 --- a/lib/pack.js +++ b/lib/pack.js @@ -7,7 +7,6 @@ const npa = require('npm-package-arg') const { getContents, logTar } = require('./utils/tar.js') const writeFile = util.promisify(require('fs').writeFile) -const output = require('./utils/output.js') const usageUtil = require('./utils/usage.js') @@ -49,7 +48,7 @@ class Pack { for (const tar of tarballs) { logTar(tar, { log, unicode }) - output(tar.filename.replace(/^@/, '').replace(/\//, '-')) + this.npm.output(tar.filename.replace(/^@/, '').replace(/\//, '-')) } } } diff --git a/lib/ping.js b/lib/ping.js index e43f0640f212b..3643fe3b621aa 100644 --- a/lib/ping.js +++ b/lib/ping.js @@ -1,5 +1,4 @@ const log = require('npmlog') -const output = require('./utils/output.js') const usageUtil = require('./utils/usage.js') const pingUtil = require('./utils/ping.js') @@ -24,7 +23,7 @@ class Ping { const time = Date.now() - start log.notice('PONG', `${time / 1000}ms`) if (this.npm.flatOptions.json) { - output(JSON.stringify({ + this.npm.output(JSON.stringify({ registry: this.npm.flatOptions.registry, time, details, diff --git a/lib/prefix.js b/lib/prefix.js index e46f9c4cdd94a..8ec5ab9efcf78 100644 --- a/lib/prefix.js +++ b/lib/prefix.js @@ -1,4 +1,3 @@ -const output = require('./utils/output.js') const usageUtil = require('./utils/usage.js') class Prefix { @@ -16,7 +15,7 @@ class Prefix { } async prefix (args) { - return output(this.npm.prefix) + return this.npm.output(this.npm.prefix) } } module.exports = Prefix diff --git a/lib/profile.js b/lib/profile.js index dab99092b0a0f..a0a8606014da4 100644 --- a/lib/profile.js +++ b/lib/profile.js @@ -7,7 +7,6 @@ const qrcodeTerminal = require('qrcode-terminal') const Table = require('cli-table3') const otplease = require('./utils/otplease.js') -const output = require('./utils/output.js') const pulseTillDone = require('./utils/pulse-till-done.js') const readUserInfo = require('./utils/read-user-info.js') const usageUtil = require('./utils/usage.js') @@ -116,7 +115,7 @@ class Profile { delete info.cidr_whitelist if (conf.json) { - output(JSON.stringify(info, null, 2)) + this.npm.output(JSON.stringify(info, null, 2)) return } @@ -145,21 +144,21 @@ class Profile { .filter((arg) => arg.trim() !== '') .map((arg) => cleaned[arg]) .join('\t') - output(values) + this.npm.output(values) } else { if (conf.parseable) { for (const key of Object.keys(info)) { if (key === 'tfa') - output(`${key}\t${cleaned[tfa]}`) + this.npm.output(`${key}\t${cleaned[tfa]}`) else - output(`${key}\t${info[key]}`) + this.npm.output(`${key}\t${info[key]}`) } } else { const table = new Table() for (const key of Object.keys(cleaned)) table.push({ [ansistyles.bright(key)]: cleaned[key] }) - output(table.toString()) + this.npm.output(table.toString()) } } } @@ -215,13 +214,13 @@ class Profile { const result = await otplease(conf, conf => npmProfile.set(newUser, conf)) if (conf.json) - output(JSON.stringify({ [prop]: result[prop] }, null, 2)) + this.npm.output(JSON.stringify({ [prop]: result[prop] }, null, 2)) else if (conf.parseable) - output(prop + '\t' + result[prop]) + this.npm.output(prop + '\t' + result[prop]) else if (result[prop] != null) - output('Set', prop, 'to', result[prop]) + this.npm.output('Set', prop, 'to', result[prop]) else - output('Set', prop) + this.npm.output('Set', prop) } async enable2fa (args) { @@ -327,7 +326,7 @@ class Profile { ) if (challenge.tfa === null) { - output('Two factor authentication mode changed to: ' + mode) + this.npm.output('Two factor authentication mode changed to: ' + mode) return } @@ -344,7 +343,7 @@ class Profile { const secret = otpauth.searchParams.get('secret') const code = await qrcode(challenge.tfa) - output( + this.npm.output( 'Scan into your authenticator app:\n' + code + '\n Or enter code:', secret ) @@ -355,17 +354,17 @@ class Profile { const result = await npmProfile.set({ tfa: [interactiveOTP] }, conf) - output( + this.npm.output( '2FA successfully enabled. Below are your recovery codes, ' + 'please print these out.' ) - output( + this.npm.output( 'You will need these to recover access to your account ' + 'if you lose your authentication device.' ) for (const tfaCode of result.tfa) - output('\t' + tfaCode) + this.npm.output('\t' + tfaCode) } async disable2fa (args) { @@ -373,7 +372,7 @@ class Profile { const info = await pulseTillDone.withPromise(npmProfile.get(conf)) if (!info.tfa || info.tfa.pending) { - output('Two factor authentication not enabled.') + this.npm.output('Two factor authentication not enabled.') return } @@ -391,11 +390,11 @@ class Profile { }, conf)) if (conf.json) - output(JSON.stringify({ tfa: false }, null, 2)) + this.npm.output(JSON.stringify({ tfa: false }, null, 2)) else if (conf.parseable) - output('tfa\tfalse') + this.npm.output('tfa\tfalse') else - output('Two factor authentication disabled.') + this.npm.output('Two factor authentication disabled.') } } module.exports = Profile diff --git a/lib/publish.js b/lib/publish.js index c8e82c44c5a3c..b0bf922138ce3 100644 --- a/lib/publish.js +++ b/lib/publish.js @@ -9,7 +9,6 @@ const npa = require('npm-package-arg') const npmFetch = require('npm-registry-fetch') const { flatten } = require('./utils/flat-options.js') -const output = require('./utils/output.js') const otplease = require('./utils/otplease.js') const usageUtil = require('./utils/usage.js') const { getContents, logTar } = require('./utils/tar.js') @@ -115,9 +114,9 @@ class Publish { const silent = log.level === 'silent' if (!silent && json) - output(JSON.stringify(pkgContents, null, 2)) + this.npm.output(JSON.stringify(pkgContents, null, 2)) else if (!silent) - output(`+ ${pkgContents.id}`) + this.npm.output(`+ ${pkgContents.id}`) return pkgContents } diff --git a/lib/rebuild.js b/lib/rebuild.js index 1091b01589389..ffbdebc21fa27 100644 --- a/lib/rebuild.js +++ b/lib/rebuild.js @@ -3,7 +3,6 @@ const Arborist = require('@npmcli/arborist') const npa = require('npm-package-arg') const semver = require('semver') const usageUtil = require('./utils/usage.js') -const output = require('./utils/output.js') const completion = require('./utils/completion/installed-deep.js') class Rebuild { @@ -52,7 +51,7 @@ class Rebuild { } else await arb.rebuild() - output('rebuilt dependencies successfully') + this.npm.output('rebuilt dependencies successfully') } isNode (specs, node) { diff --git a/lib/root.js b/lib/root.js index 8e5ac63d7b9b8..7c3fa2bbb3544 100644 --- a/lib/root.js +++ b/lib/root.js @@ -1,4 +1,3 @@ -const output = require('./utils/output.js') const usageUtil = require('./utils/usage.js') class Root { @@ -16,7 +15,7 @@ class Root { } async root () { - output(this.npm.dir) + this.npm.output(this.npm.dir) } } module.exports = Root diff --git a/lib/run-script.js b/lib/run-script.js index cdfd88f10f7b8..dc822668d0318 100644 --- a/lib/run-script.js +++ b/lib/run-script.js @@ -2,7 +2,6 @@ const runScript = require('@npmcli/run-script') const { isServerPackage } = runScript const readJson = require('read-package-json-fast') const { resolve } = require('path') -const output = require('./utils/output.js') const log = require('npmlog') const usageUtil = require('./utils/usage.js') const didYouMean = require('./utils/did-you-mean.js') @@ -117,13 +116,13 @@ class RunScript { return allScripts if (this.npm.flatOptions.json) { - output(JSON.stringify(scripts, null, 2)) + this.npm.output(JSON.stringify(scripts, null, 2)) return allScripts } if (this.npm.flatOptions.parseable) { for (const [script, cmd] of Object.entries(scripts)) - output(`${script}:${cmd}`) + this.npm.output(`${script}:${cmd}`) return allScripts } @@ -138,18 +137,18 @@ class RunScript { } if (cmds.length) - output(`Lifecycle scripts included in ${name}:`) + this.npm.output(`Lifecycle scripts included in ${name}:`) for (const script of cmds) - output(prefix + script + indent + scripts[script]) + this.npm.output(prefix + script + indent + scripts[script]) if (!cmds.length && runScripts.length) - output(`Scripts available in ${name} via \`npm run-script\`:`) + this.npm.output(`Scripts available in ${name} via \`npm run-script\`:`) else if (runScripts.length) - output('\navailable via `npm run-script`:') + this.npm.output('\navailable via `npm run-script`:') for (const script of runScripts) - output(prefix + script + indent + scripts[script]) + this.npm.output(prefix + script + indent + scripts[script]) return allScripts } diff --git a/lib/search.js b/lib/search.js index e0922b9846cdb..35e3eeb0e552c 100644 --- a/lib/search.js +++ b/lib/search.js @@ -5,7 +5,6 @@ const log = require('npmlog') const formatPackageStream = require('./search/format-package-stream.js') const packageFilter = require('./search/package-filter.js') -const output = require('./utils/output.js') const usageUtil = require('./utils/usage.js') function prepareIncludes (args) { @@ -83,12 +82,12 @@ class Search { p.on('data', chunk => { if (!anyOutput) anyOutput = true - output(chunk.toString('utf8')) + this.npm.output(chunk.toString('utf8')) }) await p.promise() if (!anyOutput && !opts.json && !opts.parseable) - output('No matches found for ' + (args.map(JSON.stringify).join(' '))) + this.npm.output('No matches found for ' + (args.map(JSON.stringify).join(' '))) log.silly('search', 'search completed') log.clearProgress() diff --git a/lib/star.js b/lib/star.js index b39d23b2c1170..073c93a898eaf 100644 --- a/lib/star.js +++ b/lib/star.js @@ -2,7 +2,6 @@ const fetch = require('npm-registry-fetch') const log = require('npmlog') const npa = require('npm-package-arg') -const output = require('./utils/output.js') const usageUtil = require('./utils/usage.js') const getIdentity = require('./utils/get-identity') @@ -73,7 +72,7 @@ class Star { body, }) - output(show + ' ' + pkg.name) + this.npm.output(show + ' ' + pkg.name) log.verbose('star', data) return data } diff --git a/lib/stars.js b/lib/stars.js index fe280705b4b5c..e0a6a0003ecc3 100644 --- a/lib/stars.js +++ b/lib/stars.js @@ -1,7 +1,6 @@ const log = require('npmlog') const fetch = require('npm-registry-fetch') -const output = require('./utils/output.js') const getIdentity = require('./utils/get-identity.js') const usageUtil = require('./utils/usage.js') @@ -36,7 +35,7 @@ class Stars { log.warn('stars', 'user has not starred any packages') for (const row of rows) - output(row.value) + this.npm.output(row.value) } } module.exports = Stars diff --git a/lib/team.js b/lib/team.js index 4947739a045c4..3ba2c023dbaef 100644 --- a/lib/team.js +++ b/lib/team.js @@ -1,7 +1,6 @@ const columns = require('cli-columns') const libteam = require('libnpmteam') -const output = require('./utils/output.js') const otplease = require('./utils/otplease.js') const usageUtil = require('./utils/usage.js') @@ -66,82 +65,82 @@ class Team { async create (entity, opts) { await libteam.create(entity, opts) if (opts.json) { - output(JSON.stringify({ + this.npm.output(JSON.stringify({ created: true, team: entity, })) } else if (opts.parseable) - output(`${entity}\tcreated`) + this.npm.output(`${entity}\tcreated`) else if (!opts.silent && opts.loglevel !== 'silent') - output(`+@${entity}`) + this.npm.output(`+@${entity}`) } async destroy (entity, opts) { await libteam.destroy(entity, opts) if (opts.json) { - output(JSON.stringify({ + this.npm.output(JSON.stringify({ deleted: true, team: entity, })) } else if (opts.parseable) - output(`${entity}\tdeleted`) + this.npm.output(`${entity}\tdeleted`) else if (!opts.silent && opts.loglevel !== 'silent') - output(`-@${entity}`) + this.npm.output(`-@${entity}`) } async add (entity, user, opts) { await libteam.add(user, entity, opts) if (opts.json) { - output(JSON.stringify({ + this.npm.output(JSON.stringify({ added: true, team: entity, user, })) } else if (opts.parseable) - output(`${user}\t${entity}\tadded`) + this.npm.output(`${user}\t${entity}\tadded`) else if (!opts.silent && opts.loglevel !== 'silent') - output(`${user} added to @${entity}`) + this.npm.output(`${user} added to @${entity}`) } async rm (entity, user, opts) { await libteam.rm(user, entity, opts) if (opts.json) { - output(JSON.stringify({ + this.npm.output(JSON.stringify({ removed: true, team: entity, user, })) } else if (opts.parseable) - output(`${user}\t${entity}\tremoved`) + this.npm.output(`${user}\t${entity}\tremoved`) else if (!opts.silent && opts.loglevel !== 'silent') - output(`${user} removed from @${entity}`) + this.npm.output(`${user} removed from @${entity}`) } async listUsers (entity, opts) { const users = (await libteam.lsUsers(entity, opts)).sort() if (opts.json) - output(JSON.stringify(users, null, 2)) + this.npm.output(JSON.stringify(users, null, 2)) else if (opts.parseable) - output(users.join('\n')) + this.npm.output(users.join('\n')) else if (!opts.silent && opts.loglevel !== 'silent') { const plural = users.length === 1 ? '' : 's' const more = users.length === 0 ? '' : ':\n' - output(`\n@${entity} has ${users.length} user${plural}${more}`) - output(columns(users, { padding: 1 })) + this.npm.output(`\n@${entity} has ${users.length} user${plural}${more}`) + this.npm.output(columns(users, { padding: 1 })) } } async listTeams (entity, opts) { const teams = (await libteam.lsTeams(entity, opts)).sort() if (opts.json) - output(JSON.stringify(teams, null, 2)) + this.npm.output(JSON.stringify(teams, null, 2)) else if (opts.parseable) - output(teams.join('\n')) + this.npm.output(teams.join('\n')) else if (!opts.silent && opts.loglevel !== 'silent') { const plural = teams.length === 1 ? '' : 's' const more = teams.length === 0 ? '' : ':\n' - output(`\n@${entity} has ${teams.length} team${plural}${more}`) - output(columns(teams.map(t => `@${t}`), { padding: 1 })) + this.npm.output(`\n@${entity} has ${teams.length} team${plural}${more}`) + this.npm.output(columns(teams.map(t => `@${t}`), { padding: 1 })) } } } diff --git a/lib/token.js b/lib/token.js index ad6d5c6fcb82c..ad634c0b00772 100644 --- a/lib/token.js +++ b/lib/token.js @@ -5,7 +5,6 @@ const log = require('npmlog') const profile = require('npm-profile') const otplease = require('./utils/otplease.js') -const output = require('./utils/output.js') const pulseTillDone = require('./utils/pulse-till-done.js') const readUserInfo = require('./utils/read-user-info.js') const usageUtil = require('./utils/usage.js') @@ -64,12 +63,12 @@ class Token { log.info('token', 'getting list') const tokens = await pulseTillDone.withPromise(profile.listTokens(conf)) if (conf.json) { - output(JSON.stringify(tokens, null, 2)) + this.npm.output(JSON.stringify(tokens, null, 2)) return } else if (conf.parseable) { - output(['key', 'token', 'created', 'readonly', 'CIDR whitelist'].join('\t')) + this.npm.output(['key', 'token', 'created', 'readonly', 'CIDR whitelist'].join('\t')) tokens.forEach((token) => { - output([ + this.npm.output([ token.key, token.token, token.created, @@ -95,7 +94,7 @@ class Token { token.cidr_whitelist ? token.cidr_whitelist.join(', ') : '', ]) }) - output(table.toString()) + this.npm.output(table.toString()) } async rm (args) { @@ -127,11 +126,11 @@ class Token { }) })) if (conf.json) - output(JSON.stringify(toRemove)) + this.npm.output(JSON.stringify(toRemove)) else if (conf.parseable) - output(toRemove.join('\t')) + this.npm.output(toRemove.join('\t')) else - output('Removed ' + toRemove.length + ' token' + (toRemove.length !== 1 ? 's' : '')) + this.npm.output('Removed ' + toRemove.length + ' token' + (toRemove.length !== 1 ? 's' : '')) } async create (args) { @@ -149,14 +148,14 @@ class Token { delete result.key delete result.updated if (conf.json) - output(JSON.stringify(result)) + this.npm.output(JSON.stringify(result)) else if (conf.parseable) - Object.keys(result).forEach((k) => output(k + '\t' + result[k])) + Object.keys(result).forEach((k) => this.npm.output(k + '\t' + result[k])) else { const table = new Table() for (const k of Object.keys(result)) table.push({ [ansistyles.bright(k)]: String(result[k]) }) - output(table.toString()) + this.npm.output(table.toString()) } }) } diff --git a/lib/unpublish.js b/lib/unpublish.js index 34751da4a5909..acba6ea521191 100644 --- a/lib/unpublish.js +++ b/lib/unpublish.js @@ -8,7 +8,6 @@ const libunpub = require('libnpmpublish').unpublish const readJson = util.promisify(require('read-package-json')) const usageUtil = require('./utils/usage.js') -const output = require('./utils/output.js') const otplease = require('./utils/otplease.js') const getIdentity = require('./utils/get-identity.js') @@ -107,7 +106,7 @@ class Unpublish { } if (!silent && loglevel !== 'silent') - output(`- ${pkgName}${pkgVersion}`) + this.npm.output(`- ${pkgName}${pkgVersion}`) } } module.exports = Unpublish diff --git a/lib/utils/audit-error.js b/lib/utils/audit-error.js index ae0749ff6f0be..c58c1d16e6885 100644 --- a/lib/utils/audit-error.js +++ b/lib/utils/audit-error.js @@ -3,7 +3,6 @@ // prints a JSON version of the error if it's --json // returns 'true' if there was an error, false otherwise -const output = require('./output.js') const auditError = (npm, report) => { if (!report || !report.error) return false @@ -18,7 +17,7 @@ const auditError = (npm, report) => { const { body: errBody } = error const body = Buffer.isBuffer(errBody) ? errBody.toString() : errBody if (npm.flatOptions.json) { - output(JSON.stringify({ + npm.output(JSON.stringify({ message: error.message, method: error.method, uri: error.uri, @@ -27,7 +26,7 @@ const auditError = (npm, report) => { body, }, null, 2)) } else - output(body) + npm.output(body) throw 'audit endpoint returned an error' } diff --git a/lib/utils/npm-usage.js b/lib/utils/npm-usage.js index 220f8037f164d..b77bca7bec1a8 100644 --- a/lib/utils/npm-usage.js +++ b/lib/utils/npm-usage.js @@ -1,6 +1,5 @@ const didYouMean = require('./did-you-mean.js') const { dirname } = require('path') -const output = require('./output.js') const { cmdList } = require('./cmd-list') module.exports = (npm, valid = true) => { @@ -8,7 +7,7 @@ module.exports = (npm, valid = true) => { const usesBrowser = npm.config.get('viewer') === 'browser' ? ' (in a browser)' : '' npm.log.level = 'silent' - output(` + npm.output(` Usage: npm npm install install all the dependencies in your project @@ -34,7 +33,7 @@ npm@${npm.version} ${dirname(dirname(__dirname))} `) if (npm.argv.length >= 1) - output(didYouMean(npm.argv[0], cmdList)) + npm.output(didYouMean(npm.argv[0], cmdList)) if (!valid) process.exitCode = 1 diff --git a/lib/utils/open-url.js b/lib/utils/open-url.js index 1fe456bd050be..41fac33ec66e9 100644 --- a/lib/utils/open-url.js +++ b/lib/utils/open-url.js @@ -1,4 +1,3 @@ -const output = require('./output.js') const opener = require('opener') const { URL } = require('url') @@ -16,7 +15,7 @@ const open = async (npm, url, errMsg) => { }, null, 2) : `${errMsg}:\n ${url}\n` - output(alternateMsg) + npm.output(alternateMsg) } if (browser === false) { diff --git a/lib/utils/output.js b/lib/utils/output.js deleted file mode 100644 index 2d1549859ac0d..0000000000000 --- a/lib/utils/output.js +++ /dev/null @@ -1,7 +0,0 @@ -const log = require('npmlog') -// output to stdout in a progress bar compatible way -module.exports = (...msg) => { - log.clearProgress() - console.log(...msg) - log.showProgress() -} diff --git a/lib/utils/reify-output.js b/lib/utils/reify-output.js index 216f0e902e90a..ddad32121e8b4 100644 --- a/lib/utils/reify-output.js +++ b/lib/utils/reify-output.js @@ -10,7 +10,6 @@ // run `npm audit fix` to fix them, or `npm audit` for details const log = require('npmlog') -const output = require('./output.js') const { depth } = require('treeverse') const ms = require('ms') const auditReport = require('npm-audit-report') @@ -72,10 +71,10 @@ const reifyOutput = (npm, arb) => { summary.audit = npm.command === 'audit' ? auditReport : auditReport.toJSON().metadata } - output(JSON.stringify(summary, 0, 2)) + npm.output(JSON.stringify(summary, 0, 2)) } else { packagesChangedMessage(npm, summary) - packagesFundingMessage(summary) + packagesFundingMessage(npm, summary) printAuditReport(npm, auditReport) } } @@ -98,7 +97,7 @@ const printAuditReport = (npm, report) => { auditLevel, }) process.exitCode = process.exitCode || res.exitCode - output('\n' + res.report) + npm.output('\n' + res.report) } const packagesChangedMessage = (npm, { added, removed, changed, audited }) => { @@ -136,18 +135,18 @@ const packagesChangedMessage = (npm, { added, removed, changed, audited }) => { msg.push(`audited ${audited} package${audited === 1 ? '' : 's'}`) msg.push(` in ${ms(Date.now() - npm.started)}`) - output(msg.join('')) + npm.output(msg.join('')) } -const packagesFundingMessage = ({ funding }) => { +const packagesFundingMessage = (npm, { funding }) => { if (!funding) return - output('') + npm.output('') const pkg = funding === 1 ? 'package' : 'packages' const is = funding === 1 ? 'is' : 'are' - output(`${funding} ${pkg} ${is} looking for funding`) - output(' run `npm fund` for details') + npm.output(`${funding} ${pkg} ${is} looking for funding`) + npm.output(' run `npm fund` for details') } module.exports = reifyOutput diff --git a/lib/version.js b/lib/version.js index 1ba834f5d711b..a7c0c1955d536 100644 --- a/lib/version.js +++ b/lib/version.js @@ -1,5 +1,4 @@ const libversion = require('libnpmversion') -const output = require('./utils/output.js') const usageUtil = require('./utils/usage.js') class Version { @@ -56,7 +55,7 @@ class Version { ...this.npm.flatOptions, path: this.npm.prefix, }) - return output(`${prefix}${version}`) + return this.npm.output(`${prefix}${version}`) } async list () { @@ -78,9 +77,9 @@ class Version { results[key] = version if (this.npm.flatOptions.json) - output(JSON.stringify(results, null, 2)) + this.npm.output(JSON.stringify(results, null, 2)) else - output(results) + this.npm.output(results) } } module.exports = Version diff --git a/lib/whoami.js b/lib/whoami.js index 39184ed9c581c..7ce877104c185 100644 --- a/lib/whoami.js +++ b/lib/whoami.js @@ -1,4 +1,3 @@ -const output = require('./utils/output.js') const getIdentity = require('./utils/get-identity.js') const usageUtil = require('./utils/usage.js') @@ -23,7 +22,7 @@ class Whoami { async whoami (args) { const opts = this.npm.flatOptions const username = await getIdentity(this.npm, opts) - output(opts.json ? JSON.stringify(username) : username) + this.npm.output(opts.json ? JSON.stringify(username) : username) } } module.exports = Whoami diff --git a/tap-snapshots/test-lib-profile.js-TAP.test.js b/tap-snapshots/test-lib-profile.js-TAP.test.js index bb838ad92c97d..58975515162f6 100644 --- a/tap-snapshots/test-lib-profile.js-TAP.test.js +++ b/tap-snapshots/test-lib-profile.js-TAP.test.js @@ -9,7 +9,11 @@ exports[`test/lib/profile.js TAP enable-2fa from token and set otp, retries on p Scan into your authenticator app: qrcode Or enter code: -12342FA successfully enabled. Below are your recovery codes, please print these out.You will need these to recover access to your account if you lose your authentication device. 123456 789101 +1234 +2FA successfully enabled. Below are your recovery codes, please print these out. +You will need these to recover access to your account if you lose your authentication device. + 123456 + 789101 ` exports[`test/lib/profile.js TAP profile get --parseable > should output parseable result value 1`] = ` @@ -29,7 +33,17 @@ foo foo@github.com (verified) https://github.com/npm ` exports[`test/lib/profile.js TAP profile get no args --parseable > should output all profile info as parseable result 1`] = ` -tfa auth-and-writesname fooemail foo@github.comemail_verified truecreated 2015-02-26T01:26:37.384Zupdated 2020-08-12T16:19:35.326Zfullname Foo Barhomepage https://github.comfreenode foobartwitter https://twitter.com/npmjsgithub https://github.com/npm +tfa auth-and-writes +name foo +email foo@github.com +email_verified true +created 2015-02-26T01:26:37.384Z +updated 2020-08-12T16:19:35.326Z +fullname Foo Bar +homepage https://github.com +freenode foobar +twitter https://twitter.com/npmjs +github https://github.com/npm ` exports[`test/lib/profile.js TAP profile get no args default output > should output table with contents 1`] = ` diff --git a/test/lib/access.js b/test/lib/access.js index 3a732ad0aac37..8134c1d9116d2 100644 --- a/test/lib/access.js +++ b/test/lib/access.js @@ -3,6 +3,10 @@ const requireInject = require('require-inject') const Access = require('../../lib/access.js') +const npm = { + output: () => null, +} + test('completion', t => { const access = new Access({ flatOptions: {} }) const testComp = (argv, expect) => { @@ -457,9 +461,8 @@ test('npm access ls-packages with no team', (t) => { }, }, '../../lib/utils/get-identity.js': () => Promise.resolve('foo'), - '../../lib/utils/output.js': () => null, }) - const access = new Access({}) + const access = new Access(npm) access.exec([ 'ls-packages', ], (err) => { @@ -477,9 +480,8 @@ test('access ls-packages on team', (t) => { return {} }, }, - '../../lib/utils/output.js': () => null, }) - const access = new Access({}) + const access = new Access(npm) access.exec([ 'ls-packages', 'myorg:myteam', @@ -503,9 +505,8 @@ test('access ls-collaborators on current', (t) => { return {} }, }, - '../../lib/utils/output.js': () => null, }) - const access = new Access({ prefix }) + const access = new Access({ prefix, ...npm }) access.exec([ 'ls-collaborators', ], (err) => { @@ -523,9 +524,8 @@ test('access ls-collaborators on spec', (t) => { return {} }, }, - '../../lib/utils/output.js': () => null, }) - const access = new Access({}) + const access = new Access(npm) access.exec([ 'ls-collaborators', 'yargs', diff --git a/test/lib/adduser.js b/test/lib/adduser.js index 32fd97c1bd46d..106cd429e37a6 100644 --- a/test/lib/adduser.js +++ b/test/lib/adduser.js @@ -61,6 +61,9 @@ const npm = { }, setCredentialsByURI, }, + output: msg => { + result = msg + }, } const AddUser = requireInject('../../lib/adduser.js', { @@ -70,9 +73,6 @@ const AddUser = requireInject('../../lib/adduser.js', { registryOutput = msg }, }, - '../../lib/utils/output.js': msg => { - result = msg - }, '../../lib/auth/legacy.js': authDummy, }) diff --git a/test/lib/audit.js b/test/lib/audit.js index 6fd9c8a2c9b8f..d291ef87948c9 100644 --- a/test/lib/audit.js +++ b/test/lib/audit.js @@ -14,6 +14,9 @@ t.test('should audit using Arborist', t => { flatOptions: { json: false, }, + output: () => { + OUTPUT_CALLED = true + }, } const Audit = requireInject('../../lib/audit.js', { 'npm-audit-report': () => { @@ -37,9 +40,6 @@ t.test('should audit using Arborist', t => { REIFY_FINISH_CALLED = true }, - '../../lib/utils/output.js': () => { - OUTPUT_CALLED = true - }, }) const audit = new Audit(npm) @@ -70,6 +70,7 @@ t.test('should audit - json', t => { flatOptions: { json: true, }, + output: () => {}, } const Audit = requireInject('../../lib/audit.js', { @@ -83,7 +84,6 @@ t.test('should audit - json', t => { } }, '../../lib/utils/reify-output.js': () => {}, - '../../lib/utils/output.js': () => {}, }) const audit = new Audit(npm) @@ -107,6 +107,9 @@ t.test('report endpoint error', t => { log: { warn: (...warning) => LOGS.push(warning), }, + output: (...msg) => { + OUTPUT.push(msg) + }, } const Audit = requireInject('../../lib/audit.js', { 'npm-audit-report': () => { @@ -130,9 +133,6 @@ t.test('report endpoint error', t => { } }, '../../lib/utils/reify-output.js': () => {}, - '../../lib/utils/output.js': (...msg) => { - OUTPUT.push(msg) - }, }) const audit = new Audit(npm) diff --git a/test/lib/bin.js b/test/lib/bin.js index e96eb91af9708..512fa8d0267b9 100644 --- a/test/lib/bin.js +++ b/test/lib/bin.js @@ -5,13 +5,16 @@ test('bin', (t) => { t.plan(3) const dir = '/bin/dir' - const Bin = requireInject('../../lib/bin.js', { - '../../lib/utils/output.js': (output) => { + const Bin = require('../../lib/bin.js') + + const npm = { + bin: dir, + flatOptions: { global: false }, + output: (output) => { t.equal(output, dir, 'prints the correct directory') }, - }) - - const bin = new Bin({ bin: dir, flatOptions: { global: false } }) + } + const bin = new Bin(npm) bin.exec([], (err) => { t.ifError(err, 'npm bin') @@ -33,12 +36,16 @@ test('bin -g', (t) => { const Bin = requireInject('../../lib/bin.js', { '../../lib/utils/path.js': [dir], - '../../lib/utils/output.js': (output) => { - t.equal(output, dir, 'prints the correct directory') - }, }) - const bin = new Bin({ bin: dir, flatOptions: { global: true } }) + const npm = { + bin: dir, + flatOptions: { global: true }, + output: (output) => { + t.equal(output, dir, 'prints the correct directory') + }, + } + const bin = new Bin(npm) bin.exec([], (err) => { t.ifError(err, 'npm bin') @@ -60,11 +67,15 @@ test('bin -g (not in path)', (t) => { const Bin = requireInject('../../lib/bin.js', { '../../lib/utils/path.js': ['/not/my/dir'], - '../../lib/utils/output.js': (output) => { + }) + const npm = { + bin: dir, + flatOptions: { global: true }, + output: (output) => { t.equal(output, dir, 'prints the correct directory') }, - }) - const bin = new Bin({ bin: dir, flatOptions: { global: true } }) + } + const bin = new Bin(npm) bin.exec([], (err) => { t.ifError(err, 'npm bin') diff --git a/test/lib/cache.js b/test/lib/cache.js index 67499f37e9f30..5c2588f34ecba 100644 --- a/test/lib/cache.js +++ b/test/lib/cache.js @@ -8,9 +8,14 @@ const flatOptions = { force: false, } +let outputOutput = [] + const npm = { flatOptions, cache: '/fake/path', + output: (msg) => { + outputOutput.push(msg) + }, } let rimrafPath = '' @@ -41,11 +46,6 @@ const pacote = { }, } -let outputOutput = [] -const output = (msg) => { - outputOutput.push(msg) -} - const cacacheVerifyStats = { keptSize: 100, verifiedContent: 1, @@ -63,7 +63,6 @@ const Cache = requireInject('../../lib/cache.js', { npmlog, pacote, rimraf, - '../../lib/utils/output.js': output, '../../lib/utils/usage.js': usageUtil, }) diff --git a/test/lib/completion.js b/test/lib/completion.js index 89e8134ebb303..708f138251d19 100644 --- a/test/lib/completion.js +++ b/test/lib/completion.js @@ -46,6 +46,9 @@ const npm = { }, }, }, + output: (line) => { + output.push(line) + }, } const cmdList = { @@ -80,9 +83,6 @@ const Completion = requireInject('../../lib/completion.js', { '../../lib/utils/config.js': config, '../../lib/utils/deref-command.js': deref, '../../lib/utils/is-windows-shell.js': false, - '../../lib/utils/output.js': (line) => { - output.push(line) - }, }) const completion = new Completion(npm) diff --git a/test/lib/config.js b/test/lib/config.js index c2420aefb4a00..48934ba4e74d2 100644 --- a/test/lib/config.js +++ b/test/lib/config.js @@ -62,15 +62,15 @@ const npm = { return true }, }, + output: msg => { + result = msg + }, } const usageUtil = () => 'usage instructions' const mocks = { '../../lib/utils/config.js': { defaults, types }, - '../../lib/utils/output.js': msg => { - result = msg - }, '../../lib/utils/usage.js': usageUtil, } diff --git a/test/lib/diff.js b/test/lib/diff.js index 2af3bd69bc2e5..9f58505dca6ad 100644 --- a/test/lib/diff.js +++ b/test/lib/diff.js @@ -23,12 +23,12 @@ const npm = { get prefix () { return this.flatOptions.prefix }, + output: noop, } const mocks = { npmlog: { info: noop, verbose: noop }, libnpmdiff: (...args) => libnpmdiff(...args), 'npm-registry-fetch': async () => ({}), - '../../lib/utils/output.js': noop, '../../lib/utils/read-local-package.js': async () => rlp(), '../../lib/utils/usage.js': () => 'usage instructions', } diff --git a/test/lib/dist-tag.js b/test/lib/dist-tag.js index b761fb103cda8..a3c05bb2b3a15 100644 --- a/test/lib/dist-tag.js +++ b/test/lib/dist-tag.js @@ -58,9 +58,6 @@ const DistTag = requireInject('../../lib/dist-tag.js', { get 'npm-registry-fetch' () { return npmRegistryFetchMock }, - '../../lib/utils/output.js': msg => { - result = msg - }, }) const distTag = new DistTag({ @@ -70,6 +67,9 @@ const distTag = new DistTag({ return _flatOptions[key] }, }, + output: msg => { + result = msg + }, }) test('ls in current package', (t) => { diff --git a/test/lib/doctor.js b/test/lib/doctor.js index eaa7ad72df8a5..56bbdf974491d 100644 --- a/test/lib/doctor.js +++ b/test/lib/doctor.js @@ -104,6 +104,9 @@ const npm = { }, }, version: '7.1.0', + output: (data) => { + output.push(data) + }, } let latestNpm = npm.version @@ -123,9 +126,6 @@ const cacache = { const Doctor = requireInject('../../lib/doctor.js', { '../../lib/utils/is-windows.js': false, '../../lib/utils/ping.js': ping, - '../../lib/utils/output.js': (data) => { - output.push(data) - }, cacache, pacote, 'make-fetch-happen': fetch, @@ -285,9 +285,6 @@ test('node versions', t => { const WinDoctor = requireInject('../../lib/doctor.js', { '../../lib/utils/is-windows.js': true, '../../lib/utils/ping.js': ping, - '../../lib/utils/output.js': (data) => { - output.push(data) - }, cacache, pacote, 'make-fetch-happen': fetch, @@ -566,9 +563,6 @@ test('node versions', t => { const Doctor = requireInject('../../lib/doctor.js', { '../../lib/utils/is-windows.js': false, '../../lib/utils/ping.js': ping, - '../../lib/utils/output.js': (data) => { - output.push(data) - }, cacache, pacote, 'make-fetch-happen': fetch, diff --git a/test/lib/exec.js b/test/lib/exec.js index 4dc7f31cc31f4..eb9fef6a61da2 100644 --- a/test/lib/exec.js +++ b/test/lib/exec.js @@ -55,6 +55,7 @@ const npm = { LOG_WARN.push(args) }, }, + output, } const RUN_SCRIPTS = [] @@ -93,7 +94,6 @@ const mocks = { pacote, read, 'mkdirp-infer-owner': mkdirp, - '../../lib/utils/output.js': output, } const Exec = requireInject('../../lib/exec.js', mocks) const exec = new Exec(npm) diff --git a/test/lib/explain.js b/test/lib/explain.js index 22bfb8639ecff..2e82928d89d19 100644 --- a/test/lib/explain.js +++ b/test/lib/explain.js @@ -4,15 +4,15 @@ const npm = { prefix: null, color: true, flatOptions: {}, + output: (...args) => { + OUTPUT.push(args) + }, } const { resolve } = require('path') const OUTPUT = [] const Explain = requireInject('../../lib/explain.js', { - '../../lib/utils/output.js': (...args) => { - OUTPUT.push(args) - }, // keep the snapshots pared down a bit, since this has its own tests. '../../lib/utils/explain-dep.js': { diff --git a/test/lib/explore.js b/test/lib/explore.js index 6f1f3bb47f240..af16444ca8f71 100644 --- a/test/lib/explore.js +++ b/test/lib/explore.js @@ -55,9 +55,6 @@ const getExplore = (windows) => { }, 'read-package-json-fast': mockRPJ, '@npmcli/run-script': mockRunScript, - '../../lib/utils/output.js': out => { - output.push(out) - }, }) const npm = { dir: windows ? 'c:\\npm\\dir' : '/npm/dir', @@ -69,6 +66,9 @@ const getExplore = (windows) => { flatOptions: { shell: 'shell-command', }, + output: out => { + output.push(out) + }, } return new Explore(npm) } diff --git a/test/lib/fund.js b/test/lib/fund.js index 831d76f151bb7..2ae604a653632 100644 --- a/test/lib/fund.js +++ b/test/lib/fund.js @@ -202,9 +202,6 @@ const openUrl = async (npm, url, msg) => { } const Fund = requireInject('../../lib/fund.js', { '../../lib/utils/open-url.js': openUrl, - '../../lib/utils/output.js': msg => { - result += msg + '\n' - }, pacote: { manifest: (arg) => arg.name === 'ntl' ? Promise.resolve({ @@ -218,6 +215,9 @@ const fund = new Fund({ get prefix () { return _flatOptions.prefix }, + output: msg => { + result += msg + '\n' + }, }) test('fund with no package containing funding', t => { diff --git a/test/lib/help-search.js b/test/lib/help-search.js index 8b1ecd46eb774..6228f5ca97b3b 100644 --- a/test/lib/help-search.js +++ b/test/lib/help-search.js @@ -21,6 +21,7 @@ const npm = { return cb(npmHelpErr) }, }, + output, } let npmUsageArg = null @@ -45,7 +46,6 @@ const glob = (p, cb) => const HelpSearch = requireInject('../../lib/help-search.js', { '../../lib/utils/npm-usage.js': npmUsage, - '../../lib/utils/output.js': output, glob, }) const helpSearch = new HelpSearch(npm) diff --git a/test/lib/help.js b/test/lib/help.js index addbe4dcc1f9b..ae2f7e99dafa8 100644 --- a/test/lib/help.js +++ b/test/lib/help.js @@ -14,6 +14,7 @@ const npmConfig = { } let helpSearchArgs = null +const OUTPUT = [] const npm = { config: { get: (key) => npmConfig[key], @@ -34,11 +35,9 @@ const npm = { }, }, deref: (cmd) => {}, -} - -const OUTPUT = [] -const output = (msg) => { - OUTPUT.push(msg) + output: msg => { + OUTPUT.push(msg) + }, } const globDefaults = [ @@ -74,7 +73,6 @@ const openUrl = async (npm, url, msg) => { const Help = requireInject('../../lib/help.js', { '../../lib/utils/npm-usage.js': npmUsage, '../../lib/utils/open-url.js': openUrl, - '../../lib/utils/output.js': output, child_process: { spawn, }, diff --git a/test/lib/hook.js b/test/lib/hook.js index 923f86e81ddf3..3e012d94ee74f 100644 --- a/test/lib/hook.js +++ b/test/lib/hook.js @@ -1,6 +1,7 @@ const { test } = require('tap') const requireInject = require('require-inject') +const output = [] const npm = { flatOptions: { json: false, @@ -9,6 +10,9 @@ const npm = { loglevel: 'info', unicode: false, }, + output: (msg) => { + output.push(msg) + }, } const pkgTypes = { @@ -51,12 +55,8 @@ const libnpmhook = { }, } -const output = [] const Hook = requireInject('../../lib/hook.js', { '../../lib/utils/otplease.js': async (opts, fn) => fn(opts), - '../../lib/utils/output.js': (msg) => { - output.push(msg) - }, libnpmhook, }) const hook = new Hook(npm) diff --git a/test/lib/init.js b/test/lib/init.js index db5411ba76bf8..8b9f32e156e3d 100644 --- a/test/lib/init.js +++ b/test/lib/init.js @@ -14,13 +14,13 @@ const npm = { config: { set () {} }, flatOptions: {}, log: npmLog, + output: (...msg) => { + result += msg.join('\n') + }, } const mocks = { 'init-package-json': (dir, initFile, config, cb) => cb(null, 'data'), '../../lib/utils/usage.js': () => 'usage instructions', - '../../lib/utils/output.js': (...msg) => { - result += msg.join('\n') - }, } const Init = requireInject('../../lib/init.js', mocks) const init = new Init(npm) diff --git a/test/lib/ls.js b/test/lib/ls.js index bd81776d5f3df..bcbd3413563dd 100644 --- a/test/lib/ls.js +++ b/test/lib/ls.js @@ -1,8 +1,6 @@ -const { resolve } = require('path') - const t = require('tap') -const requireInject = require('require-inject') +const { resolve } = require('path') const { utimesSync } = require('fs') const touchHiddenPackageLock = prefix => { const later = new Date(Date.now() + 10000) @@ -106,11 +104,7 @@ const _flatOptions = { }, production: false, } -const LS = requireInject('../../lib/ls.js', { - '../../lib/utils/output.js': msg => { - result = msg - }, -}) +const LS = require('../../lib/ls.js') const ls = new LS({ flatOptions: _flatOptions, limit: { @@ -127,6 +121,9 @@ const ls = new LS({ return _flatOptions[key] }, }, + output: msg => { + result = msg + }, }) const redactCwd = res => diff --git a/test/lib/org.js b/test/lib/org.js index d21df85d64312..4ffbf0af411a6 100644 --- a/test/lib/org.js +++ b/test/lib/org.js @@ -2,6 +2,7 @@ const { test } = require('tap') const requireInject = require('require-inject') const ansiTrim = require('../../lib/utils/ansi-trim.js') +const output = [] const npm = { flatOptions: { json: false, @@ -9,10 +10,11 @@ const npm = { silent: false, loglevel: 'info', }, + output: (msg) => { + output.push(msg) + }, } -const output = [] - let orgSize = 1 let orgSetArgs = null let orgRmArgs = null @@ -41,9 +43,6 @@ const libnpmorg = { const Org = requireInject('../../lib/org.js', { '../../lib/utils/otplease.js': async (opts, fn) => fn(opts), - '../../lib/utils/output.js': (msg) => { - output.push(msg) - }, libnpmorg, }) const org = new Org(npm) diff --git a/test/lib/outdated.js b/test/lib/outdated.js index aa8a1bcb6b3a5..02952971b69f9 100644 --- a/test/lib/outdated.js +++ b/test/lib/outdated.js @@ -68,17 +68,8 @@ const packument = spec => { } let logs -const cleanLogs = (done) => { - logs = '' - const fn = (...args) => { - logs += '\n' - args.map(el => { - logs += el - return logs - }) - } - console.log = fn - done() +const output = (msg) => { + logs = `${logs}\n${msg}` } const globalDir = t.testdir({ @@ -102,10 +93,14 @@ const outdated = (dir, opts) => { prefix: dir, globalDir: `${globalDir}/node_modules`, flatOptions: opts, + output, }) } -t.beforeEach(cleanLogs) +t.beforeEach((done) => { + logs = '' + done() +}) const redactCwd = (path) => { const normalizePath = p => p diff --git a/test/lib/owner.js b/test/lib/owner.js index 4f8f430886b7e..14753689f9384 100644 --- a/test/lib/owner.js +++ b/test/lib/owner.js @@ -6,7 +6,12 @@ let readLocalPkgResponse = null const noop = () => null -const npm = { flatOptions: {} } +const npm = { + flatOptions: {}, + output: (msg) => { + result = result ? `${result}\n${msg}` : msg + }, +} const npmFetch = { json: noop } const npmlog = { error: noop, info: noop, verbose: noop } const pacote = { packument: noop } @@ -15,9 +20,6 @@ const mocks = { npmlog, 'npm-registry-fetch': npmFetch, pacote, - '../../lib/utils/output.js': (...msg) => { - result += msg.join('\n') - }, '../../lib/utils/otplease.js': async (opts, fn) => fn({ otp: '123456', opts }), '../../lib/utils/read-local-package.js': async () => readLocalPkgResponse, '../../lib/utils/usage.js': () => 'usage instructions', diff --git a/test/lib/pack.js b/test/lib/pack.js index 73a19baa3ef73..ce319be76ba3f 100644 --- a/test/lib/pack.js +++ b/test/lib/pack.js @@ -18,7 +18,6 @@ t.afterEach(cb => { t.test('should pack current directory with no arguments', (t) => { const Pack = requireInject('../../lib/pack.js', { - '../../lib/utils/output.js': output, libnpmpack, npmlog: { notice: () => {}, @@ -32,6 +31,7 @@ t.test('should pack current directory with no arguments', (t) => { json: false, dryRun: false, }, + output, }) pack.exec([], er => { @@ -53,7 +53,6 @@ t.test('should pack given directory', (t) => { }) const Pack = requireInject('../../lib/pack.js', { - '../../lib/utils/output.js': output, libnpmpack, npmlog: { notice: () => {}, @@ -67,6 +66,7 @@ t.test('should pack given directory', (t) => { json: true, dryRun: true, }, + output, }) pack.exec([testDir], er => { @@ -88,7 +88,6 @@ t.test('should pack given directory for scoped package', (t) => { }) const Pack = requireInject('../../lib/pack.js', { - '../../lib/utils/output.js': output, libnpmpack, npmlog: { notice: () => {}, @@ -102,6 +101,7 @@ t.test('should pack given directory for scoped package', (t) => { json: true, dryRun: true, }, + output, }) return pack.exec([testDir], er => { @@ -116,7 +116,6 @@ t.test('should pack given directory for scoped package', (t) => { t.test('should log pack contents', (t) => { const Pack = requireInject('../../lib/pack.js', { - '../../lib/utils/output.js': output, '../../lib/utils/tar.js': { ...require('../../lib/utils/tar.js'), logTar: () => { @@ -136,6 +135,7 @@ t.test('should log pack contents', (t) => { json: false, dryRun: false, }, + output, }) pack.exec([], er => { diff --git a/test/lib/ping.js b/test/lib/ping.js index cf47530749b33..f3563036f71fd 100644 --- a/test/lib/ping.js +++ b/test/lib/ping.js @@ -81,12 +81,6 @@ test('pings and returns json', (t) => { t.equal(spec, flatOptions, 'passes flatOptions') return details }, - '../../lib/utils/output.js': function (spec) { - const parsed = JSON.parse(spec) - t.equal(parsed.registry, flatOptions.registry, 'returns the correct registry url') - t.match(parsed.details, details, 'prints returned details') - t.type(parsed.time, 'number', 'returns time as a number') - }, npmlog: { notice: (type, spec) => { ++noticeCalls @@ -100,7 +94,15 @@ test('pings and returns json', (t) => { }, }, }) - const ping = new Ping({ flatOptions }) + const ping = new Ping({ + flatOptions, + output: function (spec) { + const parsed = JSON.parse(spec) + t.equal(parsed.registry, flatOptions.registry, 'returns the correct registry url') + t.match(parsed.details, details, 'prints returned details') + t.type(parsed.time, 'number', 'returns time as a number') + }, + }) ping.exec([], (err) => { t.equal(noticeCalls, 2, 'should have logged 2 lines') diff --git a/test/lib/prefix.js b/test/lib/prefix.js index dfb50f174f5db..5eb7ddb934d93 100644 --- a/test/lib/prefix.js +++ b/test/lib/prefix.js @@ -1,16 +1,16 @@ -const { test } = require('tap') -const requireInject = require('require-inject') +const t = require('tap') -test('prefix', (t) => { +t.test('prefix', (t) => { t.plan(3) const dir = '/prefix/dir' - const Prefix = requireInject('../../lib/prefix.js', { - '../../lib/utils/output.js': (output) => { + const Prefix = require('../../lib/prefix.js') + const prefix = new Prefix({ + prefix: dir, + output: (output) => { t.equal(output, dir, 'prints the correct directory') }, }) - const prefix = new Prefix({ prefix: dir }) prefix.exec([], (err) => { t.ifError(err, 'npm prefix') diff --git a/test/lib/profile.js b/test/lib/profile.js index 743ba2d6872e1..d1be93b0cbb62 100644 --- a/test/lib/profile.js +++ b/test/lib/profile.js @@ -8,7 +8,13 @@ const flatOptions = { parseable: false, registry: 'https://registry.npmjs.org/', } -const npm = { config: {}, flatOptions: { ...flatOptions }} +const npm = { + config: {}, + flatOptions: { ...flatOptions }, + output: (...msg) => { + result = result ? `${result}\n${msg.join('\n')}` : msg.join('\n') + }, +} const mocks = { ansistyles: { bright: a => a }, npmlog: { @@ -32,9 +38,6 @@ const mocks = { .join('\n') } }, - '../../lib/utils/output.js': (...msg) => { - result += msg.join('\n') - }, '../../lib/utils/pulse-till-done.js': { withPromise: async a => a, }, diff --git a/test/lib/publish.js b/test/lib/publish.js index 0e857fafddfe2..6337a1fcf0b2a 100644 --- a/test/lib/publish.js +++ b/test/lib/publish.js @@ -134,9 +134,6 @@ t.test('if loglevel=info and json, should not output package contents', (t) => { log.level = 'info' const Publish = requireInject('../../lib/publish.js', { - '../../lib/utils/output.js': () => { - t.pass('output is called') - }, '../../lib/utils/tar.js': { getContents: () => ({ id: 'someid', @@ -162,6 +159,9 @@ t.test('if loglevel=info and json, should not output package contents', (t) => { return { token: 'some.registry.token' } }, }, + output: () => { + t.pass('output is called') + }, }) publish.exec([testDir], (er) => { @@ -184,9 +184,6 @@ t.test('if loglevel=silent and dry-run, should not output package contents or pu log.level = 'silent' const Publish = requireInject('../../lib/publish.js', { - '../../lib/utils/output.js': () => { - throw new Error('should not output in dry run mode') - }, '../../lib/utils/tar.js': { getContents: () => ({ id: 'someid', @@ -211,6 +208,9 @@ t.test('if loglevel=silent and dry-run, should not output package contents or pu throw new Error('should not call getCredentialsByURI in dry run') }, }, + output: () => { + throw new Error('should not output in dry run mode') + }, }) publish.exec([testDir], (er) => { @@ -241,9 +241,6 @@ t.test('if loglevel=info and dry-run, should not publish, should log package con t.pass('logTar is called') }, }, - '../../lib/utils/output.js': () => { - t.pass('output fn is called') - }, libnpmpublish: { publish: () => { throw new Error('should not call libnpmpublish in dry run') @@ -258,7 +255,11 @@ t.test('if loglevel=info and dry-run, should not publish, should log package con ...config, getCredentialsByURI: () => { throw new Error('should not call getCredentialsByURI in dry run') - }}, + }, + }, + output: () => { + t.pass('output fn is called') + }, }) publish.exec([testDir], (er) => { diff --git a/test/lib/rebuild.js b/test/lib/rebuild.js index ee081c087f07f..1eb45e0d1d7bd 100644 --- a/test/lib/rebuild.js +++ b/test/lib/rebuild.js @@ -1,7 +1,6 @@ const fs = require('fs') const { resolve } = require('path') const t = require('tap') -const requireInject = require('require-inject') let result = '' @@ -11,15 +10,11 @@ const npm = { global: false, }, prefix: '', -} -const mocks = { - '../../lib/utils/output.js': (...msg) => { + output: (...msg) => { result += msg.join('\n') }, - '../../lib/utils/usage.js': () => 'usage instructions', } - -const Rebuild = requireInject('../../lib/rebuild.js', mocks) +const Rebuild = require('../../lib/rebuild.js') const rebuild = new Rebuild(npm) t.afterEach(cb => { diff --git a/test/lib/root.js b/test/lib/root.js index e8ccc1106d772..4a1aefa02dcea 100644 --- a/test/lib/root.js +++ b/test/lib/root.js @@ -1,16 +1,16 @@ -const { test } = require('tap') -const requireInject = require('require-inject') +const t = require('tap') -test('root', (t) => { +t.test('root', (t) => { t.plan(3) const dir = '/root/dir' - const Root = requireInject('../../lib/root.js', { - '../../lib/utils/output.js': (output) => { + const Root = require('../../lib/root.js') + const root = new Root({ + dir, + output: (output) => { t.equal(output, dir, 'prints the correct directory') }, }) - const root = new Root({ dir }) root.exec([], (err) => { t.ifError(err, 'npm root') diff --git a/test/lib/run-script.js b/test/lib/run-script.js index 43592d3243466..0566daf2341f4 100644 --- a/test/lib/run-script.js +++ b/test/lib/run-script.js @@ -18,6 +18,7 @@ const npm = { npm.config.settings[k] = v }, }, + output: (...msg) => output.push(msg), } const output = [] @@ -40,7 +41,6 @@ const getRS = windows => { }), npmlog, '../../lib/utils/is-windows-shell.js': windows, - '../../lib/utils/output.js': (...msg) => output.push(msg), }) return new RunScript(npm) } diff --git a/test/lib/search.js b/test/lib/search.js index 59c59f3b96e27..ea7ec4ca7c19e 100644 --- a/test/lib/search.js +++ b/test/lib/search.js @@ -12,7 +12,12 @@ const flatOptions = { opts: '', }, } -const npm = { flatOptions: { ...flatOptions } } +const npm = { + flatOptions: { ...flatOptions }, + output: (...msg) => { + result += msg.join('\n') + }, +} const npmlog = { silly () {}, clearProgress () {}, @@ -23,9 +28,6 @@ const libnpmsearch = { const mocks = { npmlog, libnpmsearch, - '../../lib/utils/output.js': (...msg) => { - result += msg.join('\n') - }, '../../lib/utils/usage.js': () => 'usage instructions', // '../../lib/search/format-package-stream.js': a => a, } diff --git a/test/lib/star.js b/test/lib/star.js index 64efd9ef8c7ed..774fabe3924c4 100644 --- a/test/lib/star.js +++ b/test/lib/star.js @@ -4,15 +4,18 @@ const t = require('tap') let result = '' const noop = () => null -const npm = { config: { get () {} }, flatOptions: { unicode: false } } +const npm = { + config: { get () {} }, + flatOptions: { unicode: false }, + output: (...msg) => { + result += msg.join('\n') + }, +} const npmFetch = { json: noop } const npmlog = { error: noop, info: noop, verbose: noop } const mocks = { npmlog, 'npm-registry-fetch': npmFetch, - '../../lib/utils/output.js': (...msg) => { - result += msg.join('\n') - }, '../../lib/utils/get-identity.js': async () => 'foo', '../../lib/utils/usage.js': () => 'usage instructions', } diff --git a/test/lib/stars.js b/test/lib/stars.js index 383b5adf42677..b242a883ad90f 100644 --- a/test/lib/stars.js +++ b/test/lib/stars.js @@ -4,15 +4,18 @@ const t = require('tap') let result = '' const noop = () => null -const npm = { config: { get () {} }, flatOptions: {} } +const npm = { + config: { get () {} }, + flatOptions: {}, + output: (...msg) => { + result = [result, ...msg].join('\n') + }, +} const npmFetch = { json: noop } const npmlog = { warn: noop } const mocks = { npmlog, 'npm-registry-fetch': npmFetch, - '../../lib/utils/output.js': (...msg) => { - result = [result, ...msg].join('\n') - }, '../../lib/utils/get-identity.js': async () => 'foo', '../../lib/utils/usage.js': () => 'usage instructions', } diff --git a/test/lib/team.js b/test/lib/team.js index a264597258d5a..458f8ee6700ce 100644 --- a/test/lib/team.js +++ b/test/lib/team.js @@ -10,13 +10,15 @@ const libnpmteam = { async lsUsers () {}, async rm () {}, } -const npm = { flatOptions: {} } +const npm = { + flatOptions: {}, + output: (...msg) => { + result += msg.join('\n') + }, +} const mocks = { libnpmteam, 'cli-columns': a => a.join(' '), - '../../lib/utils/output.js': (...msg) => { - result += msg.join('\n') - }, '../../lib/utils/otplease.js': async (opts, fn) => fn(opts), '../../lib/utils/usage.js': () => 'usage instructions', } diff --git a/test/lib/token.js b/test/lib/token.js index 412d2746befd4..3ca44ab5c90c6 100644 --- a/test/lib/token.js +++ b/test/lib/token.js @@ -7,9 +7,11 @@ const mocks = { log: {}, readUserInfo: {}, } +const npm = { + output: (...args) => mocks.output(...args), +} const Token = requireInject('../../lib/token.js', { - '../../lib/utils/output.js': (...args) => mocks.output(...args), '../../lib/utils/otplease.js': (opts, fn) => { return Promise.resolve().then(() => fn(opts)) }, @@ -17,11 +19,14 @@ const Token = requireInject('../../lib/token.js', { 'npm-profile': mocks.profile, npmlog: mocks.log, }) -const token = new Token({}) + +const token = new Token(npm) const tokenWithMocks = (mockRequests) => { for (const mod in mockRequests) { - if (mod !== 'npm') { + if (mod === 'npm') + mockRequests.npm = { ...npm, ...mockRequests.npm } + else { if (typeof mockRequests[mod] === 'function') mocks[mod] = mockRequests[mod] else { @@ -44,7 +49,7 @@ const tokenWithMocks = (mockRequests) => { } } - const token = new Token(mockRequests.npm || {}) + const token = new Token(mockRequests.npm || npm) return [token, reset] } diff --git a/test/lib/unpublish.js b/test/lib/unpublish.js index 80a879cb6e6df..b1255b94a8fe4 100644 --- a/test/lib/unpublish.js +++ b/test/lib/unpublish.js @@ -10,6 +10,9 @@ const npm = { silent: false, loglevel: 'silly', }, + output: (...msg) => { + result += msg.join('\n') + }, } const mocks = { npmlog: { silly () {}, verbose () {} }, @@ -18,9 +21,6 @@ const mocks = { 'npm-package-arg': noop, 'npm-registry-fetch': { json: noop }, 'read-package-json': cb => cb(), - '../../lib/utils/output.js': (...msg) => { - result += msg.join('\n') - }, '../../lib/utils/otplease.js': async (opts, fn) => fn(opts), '../../lib/utils/usage.js': () => 'usage instructions', '../../lib/utils/get-identity.js': async () => 'foo', diff --git a/test/lib/utils/audit-error.js b/test/lib/utils/audit-error.js index ea7c84373e9f3..d236f4f9e9eaf 100644 --- a/test/lib/utils/audit-error.js +++ b/test/lib/utils/audit-error.js @@ -1,20 +1,18 @@ const t = require('tap') -const requireInject = require('require-inject') const LOGS = [] +const OUTPUT = [] +const output = (...msg) => OUTPUT.push(msg) +const auditError = require('../../../lib/utils/audit-error.js') + const npm = { command: null, flatOptions: {}, log: { warn: (...msg) => LOGS.push(msg), }, + output, } -const OUTPUT = [] -const output = (...msg) => OUTPUT.push(msg) -const auditError = requireInject('../../../lib/utils/audit-error.js', { - '../../../lib/utils/output.js': output, -}) - t.afterEach(cb => { npm.flatOptions = {} OUTPUT.length = 0 diff --git a/test/lib/utils/npm-usage.js b/test/lib/utils/npm-usage.js index dbbde947ce5ed..fbc453811ec2f 100644 --- a/test/lib/utils/npm-usage.js +++ b/test/lib/utils/npm-usage.js @@ -3,10 +3,10 @@ const t = require('tap') const OUTPUT = [] const output = (...msg) => OUTPUT.push(msg) const requireInject = require('require-inject') -const usage = requireInject('../../../lib/utils/npm-usage.js', { - '../../../lib/utils/output.js': output, -}) +const usage = require('../../../lib/utils/npm-usage.js') + const npm = requireInject('../../../lib/npm.js') +npm.output = output t.test('usage', t => { t.afterEach((cb) => { diff --git a/test/lib/utils/open-url.js b/test/lib/utils/open-url.js index e8ab8f15a14a8..781b70d3e8d31 100644 --- a/test/lib/utils/open-url.js +++ b/test/lib/utils/open-url.js @@ -1,6 +1,8 @@ const { test } = require('tap') const requireInject = require('require-inject') +const OUTPUT = [] +const output = (...args) => OUTPUT.push(args) const npm = { _config: { json: false, @@ -12,11 +14,9 @@ const npm = { npm._config[k] = v }, }, + output, } -const OUTPUT = [] -const output = (...args) => OUTPUT.push(args) - let openerUrl = null let openerOpts = null let openerResult = null @@ -27,7 +27,6 @@ const opener = (url, opts, cb) => { } const openUrl = requireInject('../../../lib/utils/open-url.js', { - '../../../lib/utils/output.js': output, opener, }) diff --git a/test/lib/utils/output.js b/test/lib/utils/output.js deleted file mode 100644 index 72871187d889a..0000000000000 --- a/test/lib/utils/output.js +++ /dev/null @@ -1,8 +0,0 @@ -const t = require('tap') -const logs = [] -console.log = (...msg) => logs.push(msg) -const output = require('../../../lib/utils/output.js') -output('hello', 'world') -output('hello') -output('world') -t.strictSame(logs, [['hello', 'world'], ['hello'], ['world']]) diff --git a/test/lib/utils/reify-output.js b/test/lib/utils/reify-output.js index e41eabcb896e9..e4f58b4668e05 100644 --- a/test/lib/utils/reify-output.js +++ b/test/lib/utils/reify-output.js @@ -1,5 +1,4 @@ const t = require('tap') -const requireInject = require('require-inject') const log = require('npmlog') log.level = 'warn' @@ -13,22 +12,13 @@ const npm = { started: Date.now(), flatOptions: settings, } -const getReifyOutput = tester => - requireInject( - '../../../lib/utils/reify-output.js', - { - '../../../lib/utils/output.js': tester, - } - ) - +const reifyOutput = require('../../../lib/utils/reify-output.js') t.test('missing info', (t) => { t.plan(1) - const reifyOutput = getReifyOutput( - out => t.doesNotHave( - out, - 'looking for funding', - 'should not print fund message if missing info' - ) + npm.output = out => t.doesNotHave( + out, + 'looking for funding', + 'should not print fund message if missing info' ) reifyOutput(npm, { @@ -43,12 +33,10 @@ t.test('missing info', (t) => { t.test('even more missing info', t => { t.plan(1) - const reifyOutput = getReifyOutput( - out => t.doesNotHave( - out, - 'looking for funding', - 'should not print fund message if missing info' - ) + npm.output = out => t.doesNotHave( + out, + 'looking for funding', + 'should not print fund message if missing info' ) reifyOutput(npm, { @@ -60,17 +48,15 @@ t.test('even more missing info', t => { t.test('single package', (t) => { t.plan(1) - const reifyOutput = getReifyOutput( - out => { - if (out.endsWith('looking for funding')) { - t.match( - out, - '1 package is looking for funding', - 'should print single package message' - ) - } + npm.output = out => { + if (out.endsWith('looking for funding')) { + t.match( + out, + '1 package is looking for funding', + 'should print single package message' + ) } - ) + } reifyOutput(npm, { // a report with an error is the same as no report at all, if @@ -110,12 +96,10 @@ t.test('no message when funding config is false', (t) => { settings.fund = true }) settings.fund = false - const reifyOutput = getReifyOutput( - out => { - if (out.endsWith('looking for funding')) - t.fail('should not print funding info', { actual: out }) - } - ) + npm.output = out => { + if (out.endsWith('looking for funding')) + t.fail('should not print funding info', { actual: out }) + } reifyOutput(npm, { actualTree: { @@ -147,17 +131,15 @@ t.test('no message when funding config is false', (t) => { t.test('print appropriate message for many packages', (t) => { t.plan(1) - const reifyOutput = getReifyOutput( - out => { - if (out.endsWith('looking for funding')) { - t.match( - out, - '3 packages are looking for funding', - 'should print single package message' - ) - } + npm.output = out => { + if (out.endsWith('looking for funding')) { + t.match( + out, + '3 packages are looking for funding', + 'should print single package message' + ) } - ) + } reifyOutput(npm, { actualTree: { @@ -206,9 +188,9 @@ t.test('print appropriate message for many packages', (t) => { }) t.test('no output when silent', t => { - const reifyOutput = getReifyOutput(out => { + npm.output = out => { t.fail('should not get output when silent', { actual: out }) - }) + } t.teardown(() => log.level = 'warn') log.level = 'silent' reifyOutput(npm, { @@ -235,9 +217,9 @@ t.test('no output when silent', t => { t.test('packages changed message', t => { const output = [] - const reifyOutput = getReifyOutput(out => { + npm.output = out => { output.push(out) - }) + } // return a test function that builds up the mock and snapshots output const testCase = (t, added, removed, changed, audited, json, command) => { @@ -311,9 +293,7 @@ t.test('packages changed message', t => { t.test('added packages should be looked up within returned tree', t => { t.test('has added pkg in inventory', t => { t.plan(1) - const reifyOutput = getReifyOutput( - out => t.matchSnapshot(out) - ) + npm.output = out => t.matchSnapshot(out) reifyOutput(npm, { actualTree: { @@ -332,9 +312,7 @@ t.test('added packages should be looked up within returned tree', t => { t.test('missing added pkg in inventory', t => { t.plan(1) - const reifyOutput = getReifyOutput( - out => t.matchSnapshot(out) - ) + npm.output = out => t.matchSnapshot(out) reifyOutput(npm, { actualTree: { diff --git a/test/lib/version.js b/test/lib/version.js index e0e07f5172efe..a8fcd831fb5c3 100644 --- a/test/lib/version.js +++ b/test/lib/version.js @@ -11,14 +11,13 @@ const npm = { }, prefix: '', version: '1.0.0', -} -const mocks = { - libnpmversion: noop, - '../../lib/utils/output.js': (...msg) => { + output: (...msg) => { for (const m of msg) result.push(m) }, - '../../lib/utils/usage.js': () => 'usage instructions', +} +const mocks = { + libnpmversion: noop, } const Version = requireInject('../../lib/version.js', mocks) @@ -65,7 +64,7 @@ t.test('too many args', t => { version.exec(['foo', 'bar'], err => { t.match( err, - 'usage instructions', + 'npm version', 'should throw usage instructions error' ) diff --git a/test/lib/whoami.js b/test/lib/whoami.js index 3d9618ffa7150..1a1ecd25742e1 100644 --- a/test/lib/whoami.js +++ b/test/lib/whoami.js @@ -5,11 +5,13 @@ test('whoami', (t) => { t.plan(3) const Whoami = requireInject('../../lib/whoami.js', { '../../lib/utils/get-identity.js': () => Promise.resolve('foo'), - '../../lib/utils/output.js': (output) => { + }) + const whoami = new Whoami({ + flatOptions: {}, + output: (output) => { t.equal(output, 'foo', 'should output the username') }, }) - const whoami = new Whoami({ flatOptions: {} }) whoami.exec([], (err) => { t.ifError(err, 'npm whoami') @@ -21,11 +23,13 @@ test('whoami json', (t) => { t.plan(3) const Whoami = requireInject('../../lib/whoami.js', { '../../lib/utils/get-identity.js': () => Promise.resolve('foo'), - '../../lib/utils/output.js': (output) => { + }) + const whoami = new Whoami({ + flatOptions: { json: true }, + output: (output) => { t.equal(output, '"foo"', 'should output the username as json') }, }) - const whoami = new Whoami({ flatOptions: { json: true } }) whoami.exec([], (err) => { t.ifError(err, 'npm whoami')