diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index 6642cafee5ef0..170be45ba13d9 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -36,7 +36,6 @@ graph LR; libnpmexec-->npmcli-mock-registry["@npmcli/mock-registry"]; libnpmexec-->npmcli-run-script["@npmcli/run-script"]; libnpmexec-->npmcli-template-oss["@npmcli/template-oss"]; - libnpmexec-->npmlog; libnpmexec-->pacote; libnpmexec-->proc-log; libnpmexec-->read-package-json-fast; @@ -131,10 +130,10 @@ graph LR; npm-->npmcli-run-script["@npmcli/run-script"]; npm-->npmcli-smoke-tests["@npmcli/smoke-tests"]; npm-->npmcli-template-oss["@npmcli/template-oss"]; - npm-->npmlog; npm-->pacote; npm-->parse-conflict-json; npm-->proc-log; + npm-->proggy; npm-->read; npm-->semver; npm-->ssri; @@ -180,10 +179,10 @@ graph LR; npmcli-arborist-->npmcli-redact["@npmcli/redact"]; npmcli-arborist-->npmcli-run-script["@npmcli/run-script"]; npmcli-arborist-->npmcli-template-oss["@npmcli/template-oss"]; - npmcli-arborist-->npmlog; npmcli-arborist-->pacote; npmcli-arborist-->parse-conflict-json; npmcli-arborist-->proc-log; + npmcli-arborist-->proggy; npmcli-arborist-->read-package-json-fast; npmcli-arborist-->semver; npmcli-arborist-->ssri; @@ -234,8 +233,6 @@ graph LR; npmcli-smoke-tests-->npmcli-promise-spawn["@npmcli/promise-spawn"]; npmcli-smoke-tests-->npmcli-template-oss["@npmcli/template-oss"]; npmcli-smoke-tests-->semver; - npmlog-->are-we-there-yet; - npmlog-->gauge; pacote-->cacache; pacote-->fs-minipass; pacote-->npm-package-arg; @@ -303,14 +300,6 @@ graph LR; foreground-child-->cross-spawn; foreground-child-->signal-exit; fs-minipass-->minipass; - gauge-->aproba; - gauge-->color-support; - gauge-->console-control-strings; - gauge-->has-unicode; - gauge-->signal-exit; - gauge-->string-width; - gauge-->strip-ansi; - gauge-->wide-align; glob-->foreground-child; glob-->jackspeak; glob-->minimatch; @@ -373,7 +362,6 @@ graph LR; libnpmexec-->npmcli-mock-registry["@npmcli/mock-registry"]; libnpmexec-->npmcli-run-script["@npmcli/run-script"]; libnpmexec-->npmcli-template-oss["@npmcli/template-oss"]; - libnpmexec-->npmlog; libnpmexec-->pacote; libnpmexec-->proc-log; libnpmexec-->read-package-json-fast; @@ -548,11 +536,11 @@ graph LR; npm-->npmcli-run-script["@npmcli/run-script"]; npm-->npmcli-smoke-tests["@npmcli/smoke-tests"]; npm-->npmcli-template-oss["@npmcli/template-oss"]; - npm-->npmlog; npm-->p-map; npm-->pacote; npm-->parse-conflict-json; npm-->proc-log; + npm-->proggy; npm-->qrcode-terminal; npm-->read; npm-->remark-gfm; @@ -627,10 +615,10 @@ graph LR; npmcli-arborist-->npmcli-redact["@npmcli/redact"]; npmcli-arborist-->npmcli-run-script["@npmcli/run-script"]; npmcli-arborist-->npmcli-template-oss["@npmcli/template-oss"]; - npmcli-arborist-->npmlog; npmcli-arborist-->pacote; npmcli-arborist-->parse-conflict-json; npmcli-arborist-->proc-log; + npmcli-arborist-->proggy; npmcli-arborist-->promise-all-reject-late; npmcli-arborist-->promise-call-limit; npmcli-arborist-->read-package-json-fast; @@ -721,10 +709,6 @@ graph LR; npmcli-smoke-tests-->semver; npmcli-smoke-tests-->tap; npmcli-smoke-tests-->which; - npmlog-->are-we-there-yet; - npmlog-->console-control-strings; - npmlog-->gauge; - npmlog-->set-blocking; p-map-->aggregate-error; pacote-->cacache; pacote-->fs-minipass; @@ -812,7 +796,6 @@ graph LR; validate-npm-package-name-->builtins; wcwidth-->defaults; which-->isexe; - wide-align-->string-width; wrap-ansi-->ansi-styles; wrap-ansi-->string-width; wrap-ansi-->strip-ansi; @@ -836,5 +819,5 @@ packages higher up the chain. - @npmcli/package-json, npm-registry-fetch - @npmcli/git, make-fetch-happen, @npmcli/config - @npmcli/installed-package-contents, @npmcli/map-workspaces, cacache, npm-pick-manifest, read-package-json, promzard - - @npmcli/docs, @npmcli/fs, npm-bundled, read-package-json-fast, unique-filename, npm-install-checks, npm-package-arg, normalize-package-data, npm-packlist, bin-links, nopt, npmlog, parse-conflict-json, @npmcli/mock-globals, read - - @npmcli/eslint-config, @npmcli/template-oss, ignore-walk, semver, npm-normalize-package-bin, @npmcli/name-from-folder, json-parse-even-better-errors, fs-minipass, ssri, unique-slug, @npmcli/promise-spawn, hosted-git-info, proc-log, validate-npm-package-name, @npmcli/node-gyp, @npmcli/redact, @npmcli/agent, minipass-fetch, @npmcli/query, cmd-shim, read-cmd-shim, write-file-atomic, abbrev, are-we-there-yet, gauge, minify-registry-metadata, ini, @npmcli/disparity-colors, mute-stream, npm-audit-report, npm-user-validate + - @npmcli/docs, @npmcli/fs, npm-bundled, read-package-json-fast, unique-filename, npm-install-checks, npm-package-arg, normalize-package-data, npm-packlist, bin-links, nopt, parse-conflict-json, @npmcli/mock-globals, read + - @npmcli/eslint-config, @npmcli/template-oss, ignore-walk, semver, npm-normalize-package-bin, @npmcli/name-from-folder, json-parse-even-better-errors, fs-minipass, ssri, unique-slug, @npmcli/promise-spawn, hosted-git-info, proc-log, validate-npm-package-name, @npmcli/node-gyp, @npmcli/redact, @npmcli/agent, minipass-fetch, @npmcli/query, cmd-shim, read-cmd-shim, write-file-atomic, abbrev, proggy, minify-registry-metadata, ini, @npmcli/disparity-colors, mute-stream, npm-audit-report, npm-user-validate diff --git a/lib/arborist-cmd.js b/lib/arborist-cmd.js index 42699ece364ad..2e300660ea468 100644 --- a/lib/arborist-cmd.js +++ b/lib/arborist-cmd.js @@ -1,4 +1,4 @@ -const log = require('./utils/log-shim.js') +const log = require('proc-log') // This is the base for all commands whose execWorkspaces just gets // a list of workspace names and passes it on to new Arborist() to diff --git a/lib/base-command.js b/lib/base-command.js index cdf7971b5aaf9..d7019001e43aa 100644 --- a/lib/base-command.js +++ b/lib/base-command.js @@ -4,7 +4,7 @@ const { relative } = require('path') const { definitions } = require('@npmcli/config/lib/definitions') const { aliases: cmdAliases } = require('./utils/cmd-list') -const log = require('./utils/log-shim.js') +const log = require('proc-log') class BaseCommand { static workspaces = false diff --git a/lib/cli-entry.js b/lib/cli-entry.js index aad06e0690385..dd8e18add7ebc 100644 --- a/lib/cli-entry.js +++ b/lib/cli-entry.js @@ -18,7 +18,7 @@ module.exports = async (process, validateEngines) => { exitHandler.setNpm(npm) // only log node and npm paths in argv initially since argv can contain sensitive info. a cleaned version will be logged later - const log = require('./utils/log-shim.js') + const log = require('proc-log') log.verbose('cli', process.argv.slice(0, 2).join(' ')) log.info('using', 'npm@%s', npm.version) log.info('using', 'node@%s', process.version) diff --git a/lib/commands/adduser.js b/lib/commands/adduser.js index a69ef366fbf32..8dfa67555ec34 100644 --- a/lib/commands/adduser.js +++ b/lib/commands/adduser.js @@ -1,4 +1,4 @@ -const log = require('../utils/log-shim.js') +const log = require('proc-log') const { redactLog: replaceInfo } = require('@npmcli/redact') const auth = require('../utils/auth.js') @@ -27,7 +27,6 @@ class AddUser extends BaseCommand { const creds = this.npm.config.getCredentialsByURI(registry) - log.disableProgress() log.notice('', `Log in on ${replaceInfo(registry)}`) const { message, newCreds } = await auth.adduser(this.npm, { diff --git a/lib/commands/audit.js b/lib/commands/audit.js index 8c10a36cfee3c..9eece15c211f0 100644 --- a/lib/commands/audit.js +++ b/lib/commands/audit.js @@ -8,7 +8,7 @@ const tufClient = require('@sigstore/tuf') const ArboristWorkspaceCmd = require('../arborist-cmd.js') const auditError = require('../utils/audit-error.js') -const log = require('../utils/log-shim.js') +const log = require('proc-log') const reifyFinish = require('../utils/reify-finish.js') const sortAlphabetically = (a, b) => localeCompare(a.name, b.name) @@ -45,12 +45,8 @@ class VerifySignatures { }) await Promise.all([...registries].map(registry => this.setKeys({ registry, tuf }))) - const progress = log.newItem('verifying registry signatures', edges.size) - const mapper = async (edge) => { - progress.completeWork(1) - await this.getVerifiedInfo(edge) - } - await pMap(edges, mapper, { concurrency: 20, stopOnError: true }) + log.verbose('verifying registry signatures') + await pMap(edges, (e) => this.getVerifiedInfo(e), { concurrency: 20, stopOnError: true }) // Didn't find any dependencies that could be verified, e.g. only local // deps, missing version, not on a registry etc. diff --git a/lib/commands/cache.js b/lib/commands/cache.js index 50bb35e3544df..1566d004ccc22 100644 --- a/lib/commands/cache.js +++ b/lib/commands/cache.js @@ -7,7 +7,7 @@ const BaseCommand = require('../base-command.js') const npa = require('npm-package-arg') const jsonParse = require('json-parse-even-better-errors') const localeCompare = require('@isaacs/string-locale-compare')('en') -const log = require('../utils/log-shim') +const log = require('proc-log') const searchCachePackage = async (path, parsed, cacheKeys) => { /* eslint-disable-next-line max-len */ diff --git a/lib/commands/ci.js b/lib/commands/ci.js index 428c43e6c30ed..13fd402516032 100644 --- a/lib/commands/ci.js +++ b/lib/commands/ci.js @@ -1,7 +1,7 @@ const reifyFinish = require('../utils/reify-finish.js') const runScript = require('@npmcli/run-script') const fs = require('fs/promises') -const log = require('../utils/log-shim.js') +const log = require('proc-log') const validateLockfile = require('../utils/validate-lockfile.js') const ArboristWorkspaceCmd = require('../arborist-cmd.js') diff --git a/lib/commands/config.js b/lib/commands/config.js index 8e8358fc50b7b..ebe5a9990accb 100644 --- a/lib/commands/config.js +++ b/lib/commands/config.js @@ -6,7 +6,7 @@ const ini = require('ini') const localeCompare = require('@isaacs/string-locale-compare')('en') const pkgJson = require('@npmcli/package-json') const { defaults, definitions } = require('@npmcli/config/lib/definitions') -const log = require('../utils/log-shim.js') +const log = require('proc-log') // These are the configs that we can nerf-dart. Not all of them currently even // *have* config definitions so we have to explicitly validate them here @@ -111,35 +111,30 @@ class Config extends BaseCommand { } async exec ([action, ...args]) { - log.disableProgress() - try { - switch (action) { - case 'set': - await this.set(args) - break - case 'get': - await this.get(args) - break - case 'delete': - case 'rm': - case 'del': - await this.del(args) - break - case 'list': - case 'ls': - await (this.npm.flatOptions.json ? this.listJson() : this.list()) - break - case 'edit': - await this.edit() - break - case 'fix': - await this.fix() - break - default: - throw this.usageError() - } - } finally { - log.enableProgress() + switch (action) { + case 'set': + await this.set(args) + break + case 'get': + await this.get(args) + break + case 'delete': + case 'rm': + case 'del': + await this.del(args) + break + case 'list': + case 'ls': + await (this.npm.flatOptions.json ? this.listJson() : this.list()) + break + case 'edit': + await this.edit() + break + case 'fix': + await this.fix() + break + default: + throw this.usageError() } } diff --git a/lib/commands/diff.js b/lib/commands/diff.js index 64d81d525d79d..c6b93d025bb52 100644 --- a/lib/commands/diff.js +++ b/lib/commands/diff.js @@ -4,7 +4,7 @@ const libnpmdiff = require('libnpmdiff') const npa = require('npm-package-arg') const pacote = require('pacote') const pickManifest = require('npm-pick-manifest') -const log = require('../utils/log-shim') +const log = require('proc-log') const pkgJson = require('@npmcli/package-json') const BaseCommand = require('../base-command.js') diff --git a/lib/commands/dist-tag.js b/lib/commands/dist-tag.js index ff49bc8e307cb..2b71d9a7a6444 100644 --- a/lib/commands/dist-tag.js +++ b/lib/commands/dist-tag.js @@ -1,7 +1,7 @@ const npa = require('npm-package-arg') const regFetch = require('npm-registry-fetch') const semver = require('semver') -const log = require('../utils/log-shim') +const log = require('proc-log') const otplease = require('../utils/otplease.js') const pkgJson = require('@npmcli/package-json') const BaseCommand = require('../base-command.js') diff --git a/lib/commands/doctor.js b/lib/commands/doctor.js index 2a528d46ddb8d..cc127287ae576 100644 --- a/lib/commands/doctor.js +++ b/lib/commands/doctor.js @@ -7,7 +7,7 @@ const pacote = require('pacote') const { resolve } = require('path') const semver = require('semver') const { promisify } = require('util') -const log = require('../utils/log-shim.js') +const log = require('proc-log') const ping = require('../utils/ping.js') const { defaults } = require('@npmcli/config/lib/definitions') const lstat = promisify(fs.lstat) @@ -113,7 +113,7 @@ class Doctor extends BaseCommand { #checkWidth = 5 async exec (args) { - log.info('Running checkup') + log.info('doctor', 'Running checkup') let allOk = true const actions = this.actions(args) @@ -155,8 +155,7 @@ class Doctor extends BaseCommand { } async checkPing () { - const tracker = log.newItem('checkPing', 1) - tracker.info('checkPing', 'Pinging registry') + log.info('doctor', 'Pinging registry') try { await ping({ ...this.npm.flatOptions, retry: false }) return '' @@ -166,23 +165,16 @@ class Doctor extends BaseCommand { } else { throw er.message } - } finally { - tracker.finish() } } async getLatestNpmVersion () { - const tracker = log.newItem('getLatestNpmVersion', 1) - tracker.info('getLatestNpmVersion', 'Getting npm package information') - try { - const latest = (await pacote.manifest('npm@latest', this.npm.flatOptions)).version - if (semver.gte(this.npm.version, latest)) { - return `current: v${this.npm.version}, latest: v${latest}` - } else { - throw `Use npm v${latest}` - } - } finally { - tracker.finish() + log.info('doctor', 'Getting npm package information') + const latest = (await pacote.manifest('npm@latest', this.npm.flatOptions)).version + if (semver.gte(this.npm.version, latest)) { + return `current: v${this.npm.version}, latest: v${latest}` + } else { + throw `Use npm v${latest}` } } @@ -191,36 +183,30 @@ class Doctor extends BaseCommand { const current = process.version const currentRange = `^${current}` const url = 'https://nodejs.org/dist/index.json' - const tracker = log.newItem('getLatestNodejsVersion', 1) - tracker.info('getLatestNodejsVersion', 'Getting Node.js release information') - try { - const res = await fetch(url, { method: 'GET', ...this.npm.flatOptions }) - const data = await res.json() - let maxCurrent = '0.0.0' - let maxLTS = '0.0.0' - for (const { lts, version } of data) { - if (lts && semver.gt(version, maxLTS)) { - maxLTS = version - } - - if (semver.satisfies(version, currentRange) && semver.gt(version, maxCurrent)) { - maxCurrent = version - } + log.info('doctor', 'Getting Node.js release information') + const res = await fetch(url, { method: 'GET', ...this.npm.flatOptions }) + const data = await res.json() + let maxCurrent = '0.0.0' + let maxLTS = '0.0.0' + for (const { lts, version } of data) { + if (lts && semver.gt(version, maxLTS)) { + maxLTS = version } - const recommended = semver.gt(maxCurrent, maxLTS) ? maxCurrent : maxLTS - if (semver.gte(process.version, recommended)) { - return `current: ${current}, recommended: ${recommended}` - } else { - throw `Use node ${recommended} (current: ${current})` + + if (semver.satisfies(version, currentRange) && semver.gt(version, maxCurrent)) { + maxCurrent = version } - } finally { - tracker.finish() + } + const recommended = semver.gt(maxCurrent, maxLTS) ? maxCurrent : maxLTS + if (semver.gte(process.version, recommended)) { + return `current: ${current}, recommended: ${recommended}` + } else { + throw `Use node ${recommended} (current: ${current})` } } - async getBinPath (dir) { - const tracker = log.newItem('getBinPath', 1) - tracker.info('getBinPath', 'Finding npm global bin in your PATH') + async getBinPath () { + log.info('doctor', 'getBinPath', 'Finding npm global bin in your PATH') if (!process.env.PATH.includes(this.npm.globalBin)) { throw new Error(`Add ${this.npm.globalBin} to your $PATH`) } @@ -250,30 +236,26 @@ class Doctor extends BaseCommand { async checkFilesPermission (root, shouldOwn, mask, missingOk) { let ok = true - const tracker = log.newItem(root, 1) - try { const uid = process.getuid() const gid = process.getgid() const files = new Set([root]) for (const f of files) { - tracker.silly('checkFilesPermission', f.slice(root.length + 1)) + log.silly('doctor', 'checkFilesPermission', f.slice(root.length + 1)) const st = await lstat(f).catch(er => { // if it can't be missing, or if it can and the error wasn't that it was missing if (!missingOk || er.code !== 'ENOENT') { ok = false - tracker.warn('checkFilesPermission', 'error getting info for ' + f) + log.warn('doctor', 'checkFilesPermission', 'error getting info for ' + f) } }) - tracker.completeWork(1) - if (!st) { continue } if (shouldOwn && (uid !== st.uid || gid !== st.gid)) { - tracker.warn('checkFilesPermission', 'should be owner of ' + f) + log.warn('doctor', 'checkFilesPermission', 'should be owner of ' + f) ok = false } @@ -286,14 +268,14 @@ class Doctor extends BaseCommand { } catch (er) { ok = false const msg = `Missing permissions on ${f} (expect: ${maskLabel(mask)})` - tracker.error('checkFilesPermission', msg) + log.error('doctor', 'checkFilesPermission', msg) continue } if (st.isDirectory()) { const entries = await readdir(f).catch(er => { ok = false - tracker.warn('checkFilesPermission', 'error reading directory ' + f) + log.warn('doctor', 'checkFilesPermission', 'error reading directory ' + f) return [] }) for (const entry of entries) { @@ -302,7 +284,6 @@ class Doctor extends BaseCommand { } } } finally { - tracker.finish() if (!ok) { throw ( `Check the permissions of files in ${root}` + @@ -315,50 +296,43 @@ class Doctor extends BaseCommand { } async getGitPath () { - const tracker = log.newItem('getGitPath', 1) - tracker.info('getGitPath', 'Finding git in your PATH') - try { - return await which('git').catch(er => { - tracker.warn(er) - throw new Error("Install git and ensure it's in your PATH.") - }) - } finally { - tracker.finish() - } + log.info('doctor', 'Finding git in your PATH') + return await which('git').catch(er => { + log.warn('doctor', 'getGitPath', er) + throw new Error("Install git and ensure it's in your PATH.") + }) } async verifyCachedFiles () { - const tracker = log.newItem('verifyCachedFiles', 1) - tracker.info('verifyCachedFiles', 'Verifying the npm cache') - try { - const stats = await cacache.verify(this.npm.flatOptions.cache) - const { badContentCount, reclaimedCount, missingContent, reclaimedSize } = stats - if (badContentCount || reclaimedCount || missingContent) { - if (badContentCount) { - tracker.warn('verifyCachedFiles', `Corrupted content removed: ${badContentCount}`) - } + log.info('doctor', 'verifyCachedFiles', 'Verifying the npm cache') - if (reclaimedCount) { - tracker.warn( - 'verifyCachedFiles', - `Content garbage-collected: ${reclaimedCount} (${reclaimedSize} bytes)` - ) - } + const stats = await cacache.verify(this.npm.flatOptions.cache) + const { badContentCount, reclaimedCount, missingContent, reclaimedSize } = stats + if (badContentCount || reclaimedCount || missingContent) { + if (badContentCount) { + log.warn('doctor', 'verifyCachedFiles', `Corrupted content removed: ${badContentCount}`) + } - if (missingContent) { - tracker.warn('verifyCachedFiles', `Missing content: ${missingContent}`) - } + if (reclaimedCount) { + log.warn( + 'doctor', + 'verifyCachedFiles', + `Content garbage-collected: ${reclaimedCount} (${reclaimedSize} bytes)` + ) + } - tracker.warn('verifyCachedFiles', 'Cache issues have been fixed') + if (missingContent) { + log.warn('doctor', 'verifyCachedFiles', `Missing content: ${missingContent}`) } - tracker.info( - 'verifyCachedFiles', - `Verification complete. Stats: ${JSON.stringify(stats, null, 2)}` - ) - return `verified ${stats.verifiedContent} tarballs` - } finally { - tracker.finish() + + log.warn('doctor', 'verifyCachedFiles', 'Cache issues have been fixed') } + log.info( + 'doctor', + 'verifyCachedFiles', + `Verification complete. Stats: ${JSON.stringify(stats, null, 2)}` + ) + return `verified ${stats.verifiedContent} tarballs` } async checkNpmRegistry () { diff --git a/lib/commands/explore.js b/lib/commands/explore.js index 7a03ea4eabd7f..23debc2743111 100644 --- a/lib/commands/explore.js +++ b/lib/commands/explore.js @@ -4,7 +4,7 @@ const pkgJson = require('@npmcli/package-json') const runScript = require('@npmcli/run-script') const { join, relative } = require('path') -const log = require('../utils/log-shim.js') +const log = require('proc-log') const completion = require('../utils/completion/installed-shallow.js') const BaseCommand = require('../base-command.js') @@ -52,28 +52,24 @@ class Explore extends BaseCommand { if (!args.length) { this.npm.output(`\nExploring ${path}\nType 'exit' or ^D when finished\n`) } - log.disableProgress() - try { - return await runScript({ - ...this.npm.flatOptions, - pkg, - banner: false, - path, - event: '_explore', - stdio: 'inherit', - }).catch(er => { - process.exitCode = typeof er.code === 'number' && er.code !== 0 ? er.code - : 1 + + return runScript({ + ...this.npm.flatOptions, + pkg, + banner: false, + path, + event: '_explore', + stdio: 'inherit', + }).catch(er => { + process.exitCode = typeof er.code === 'number' && er.code !== 0 ? er.code + : 1 // if it's not an exit error, or non-interactive, throw it - const isProcExit = er.message === 'command failed' && + const isProcExit = er.message === 'command failed' && (typeof er.code === 'number' || /^SIG/.test(er.signal || '')) - if (args.length || !isProcExit) { - throw er - } - }) - } finally { - log.enableProgress() - } + if (args.length || !isProcExit) { + throw er + } + }) } } module.exports = Explore diff --git a/lib/commands/init.js b/lib/commands/init.js index 030c97356edb8..ad3aba4d0c68c 100644 --- a/lib/commands/init.js +++ b/lib/commands/init.js @@ -6,7 +6,7 @@ const npa = require('npm-package-arg') const libexec = require('libnpmexec') const mapWorkspaces = require('@npmcli/map-workspaces') const PackageJson = require('@npmcli/package-json') -const log = require('../utils/log-shim.js') +const log = require('proc-log') const updateWorkspaces = require('../workspaces/update-workspaces.js') const posixPath = p => p.split('\\').join('/') @@ -60,7 +60,7 @@ class Init extends BaseCommand { // to create a workspace package.json file or its folders const { content: pkg } = await PackageJson.normalize(this.npm.localPrefix).catch(err => { if (err.code === 'ENOENT') { - log.warn('Missing package.json. Try with `--include-workspace-root`.') + log.warn('init', 'Missing package.json. Try with `--include-workspace-root`.') } throw err }) @@ -151,7 +151,6 @@ class Init extends BaseCommand { async template (path = process.cwd()) { log.pause() - log.disableProgress() const initFile = this.npm.config.get('init-module') if (!this.npm.config.get('yes') && !this.npm.config.get('force')) { @@ -181,7 +180,6 @@ class Init extends BaseCommand { } } finally { log.resume() - log.enableProgress() } } diff --git a/lib/commands/install.js b/lib/commands/install.js index d04a35fbec2a7..eb19c9cc76eb4 100644 --- a/lib/commands/install.js +++ b/lib/commands/install.js @@ -3,7 +3,7 @@ const fs = require('fs') const util = require('util') const readdir = util.promisify(fs.readdir) const reifyFinish = require('../utils/reify-finish.js') -const log = require('../utils/log-shim.js') +const log = require('proc-log') const { resolve, join } = require('path') const runScript = require('@npmcli/run-script') const pacote = require('pacote') diff --git a/lib/commands/login.js b/lib/commands/login.js index b498a3bf2ecd8..97a90d09ec331 100644 --- a/lib/commands/login.js +++ b/lib/commands/login.js @@ -1,4 +1,4 @@ -const log = require('../utils/log-shim.js') +const log = require('proc-log') const { redactLog: replaceInfo } = require('@npmcli/redact') const auth = require('../utils/auth.js') @@ -27,7 +27,6 @@ class Login extends BaseCommand { const creds = this.npm.config.getCredentialsByURI(registry) - log.disableProgress() log.notice('', `Log in on ${replaceInfo(registry)}`) const { message, newCreds } = await auth.login(this.npm, { diff --git a/lib/commands/logout.js b/lib/commands/logout.js index 665580930639c..60921ee3ee9f4 100644 --- a/lib/commands/logout.js +++ b/lib/commands/logout.js @@ -1,6 +1,6 @@ const npmFetch = require('npm-registry-fetch') const { getAuth } = npmFetch -const log = require('../utils/log-shim') +const log = require('proc-log') const BaseCommand = require('../base-command.js') class Logout extends BaseCommand { diff --git a/lib/commands/ls.js b/lib/commands/ls.js index 3f9775cf12504..aef3be2828a5a 100644 --- a/lib/commands/ls.js +++ b/lib/commands/ls.js @@ -1,6 +1,5 @@ const { resolve, relative, sep } = require('path') const relativePrefix = `.${sep}` -const { EOL } = require('os') const archy = require('archy') const { breadth } = require('treeverse') @@ -200,7 +199,7 @@ class LS extends ArboristWorkspaceCmd { if (shouldThrow) { throw Object.assign( - new Error([...problems].join(EOL)), + new Error([...problems].join('\n')), { code: 'ELSPROBLEMS' } ) } @@ -289,7 +288,7 @@ const getHumanOutputItem = (node, { args, chalk, global, long }) => { if (hasNoPackageJson || global) { printable = path } else { - printable += `${long ? EOL : ' '}${path}` + printable += `${long ? '\n' : ' '}${path}` } } @@ -333,7 +332,7 @@ const getHumanOutputItem = (node, { args, chalk, global, long }) => { ) + (isGitNode(node) ? ` (${node.resolved})` : '') + (node.isLink ? ` -> ${relativePrefix}${targetLocation}` : '') + - (long ? `${EOL}${node.package.description || ''}` : '') + (long ? `\n${node.package.description || ''}` : '') return augmentItemWithIncludeMetadata(node, { label, nodes: [] }) } @@ -566,7 +565,7 @@ const parseableOutput = ({ global, long, seenNodes }) => { out += node[_invalid] ? ':INVALID' : '' out += node.overridden ? ':OVERRIDDEN' : '' } - out += EOL + out += '\n' } } return out.trim() diff --git a/lib/commands/outdated.js b/lib/commands/outdated.js index 4216f1cdb1437..27b29b314b745 100644 --- a/lib/commands/outdated.js +++ b/lib/commands/outdated.js @@ -1,4 +1,3 @@ -const os = require('node:os') const { resolve } = require('node:path') const { stripVTControlCharacters } = require('node:util') const pacote = require('pacote') @@ -335,7 +334,7 @@ class Outdated extends ArboristWorkspaceCmd { } return out.join(':') - }).join(os.EOL) + }).join('\n') } makeJSON (list) { diff --git a/lib/commands/owner.js b/lib/commands/owner.js index e530e1c51c8e1..e20d05dc15fab 100644 --- a/lib/commands/owner.js +++ b/lib/commands/owner.js @@ -1,7 +1,7 @@ const npa = require('npm-package-arg') const npmFetch = require('npm-registry-fetch') const pacote = require('pacote') -const log = require('../utils/log-shim') +const log = require('proc-log') const otplease = require('../utils/otplease.js') const pkgJson = require('@npmcli/package-json') const BaseCommand = require('../base-command.js') diff --git a/lib/commands/pack.js b/lib/commands/pack.js index 6d5f00df55e3f..e1eb3f2d57aa4 100644 --- a/lib/commands/pack.js +++ b/lib/commands/pack.js @@ -1,7 +1,7 @@ const pacote = require('pacote') const libpack = require('libnpmpack') const npa = require('npm-package-arg') -const log = require('../utils/log-shim') +const log = require('proc-log') const { getContents, logTar } = require('../utils/tar.js') const BaseCommand = require('../base-command.js') diff --git a/lib/commands/ping.js b/lib/commands/ping.js index 2d60f5d69a8da..21225bc4b5a6a 100644 --- a/lib/commands/ping.js +++ b/lib/commands/ping.js @@ -1,5 +1,5 @@ const { redact } = require('@npmcli/redact') -const log = require('../utils/log-shim') +const log = require('proc-log') const pingUtil = require('../utils/ping.js') const BaseCommand = require('../base-command.js') @@ -22,7 +22,7 @@ class Ping extends BaseCommand { details, }, null, 2)) } else if (Object.keys(details).length) { - log.notice('PONG', `${JSON.stringify(details, null, 2)}`) + log.notice('PONG', JSON.stringify(details, null, 2)) } } } diff --git a/lib/commands/profile.js b/lib/commands/profile.js index a7d4ac2f29fbe..d43292f2dce09 100644 --- a/lib/commands/profile.js +++ b/lib/commands/profile.js @@ -1,12 +1,11 @@ const inspect = require('util').inspect const { URL } = require('url') -const log = require('../utils/log-shim.js') +const log = require('proc-log') const npmProfile = require('npm-profile') const qrcodeTerminal = require('qrcode-terminal') const Table = require('cli-table3') const otplease = require('../utils/otplease.js') -const pulseTillDone = require('../utils/pulse-till-done.js') const readUserInfo = require('../utils/read-user-info.js') const qrcode = url => @@ -80,8 +79,6 @@ class Profile extends BaseCommand { throw this.usageError() } - log.gauge.show('profile') - const [subcmd, ...opts] = args switch (subcmd) { @@ -106,9 +103,7 @@ class Profile extends BaseCommand { async get (args) { const tfa = 'two-factor auth' - const info = await pulseTillDone.withPromise( - npmProfile.get({ ...this.npm.flatOptions }) - ) + const info = await npmProfile.get({ ...this.npm.flatOptions }) if (!info.cidr_whitelist) { delete info.cidr_whitelist @@ -209,7 +204,7 @@ class Profile extends BaseCommand { } // FIXME: Work around to not clear everything other than what we're setting - const user = await pulseTillDone.withPromise(npmProfile.get(conf)) + const user = await npmProfile.get(conf) const newUser = {} for (const key of writableProfileKeys) { @@ -307,16 +302,12 @@ class Profile extends BaseCommand { info.tfa.password = password log.info('profile', 'Determine if tfa is pending') - const userInfo = await pulseTillDone.withPromise( - npmProfile.get({ ...this.npm.flatOptions }) - ) + const userInfo = await npmProfile.get({ ...this.npm.flatOptions }) const conf = { ...this.npm.flatOptions } if (userInfo && userInfo.tfa && userInfo.tfa.pending) { log.info('profile', 'Resetting two-factor authentication') - await pulseTillDone.withPromise( - npmProfile.set({ tfa: { password, mode: 'disable' } }, conf) - ) + await npmProfile.set({ tfa: { password, mode: 'disable' } }, conf) } else if (userInfo && userInfo.tfa) { if (!conf.otp) { conf.otp = await readUserInfo.otp( @@ -326,9 +317,7 @@ class Profile extends BaseCommand { } log.info('profile', 'Setting two-factor authentication to ' + mode) - const challenge = await pulseTillDone.withPromise( - npmProfile.set(info, conf) - ) + const challenge = await npmProfile.set(info, conf) if (challenge.tfa === null) { this.npm.output('Two factor authentication mode changed to: ' + mode) @@ -375,7 +364,7 @@ class Profile extends BaseCommand { async disable2fa (args) { const conf = { ...this.npm.flatOptions } - const info = await pulseTillDone.withPromise(npmProfile.get(conf)) + const info = await npmProfile.get(conf) if (!info.tfa || info.tfa.pending) { this.npm.output('Two factor authentication not enabled.') @@ -391,9 +380,7 @@ class Profile extends BaseCommand { log.info('profile', 'disabling tfa') - await pulseTillDone.withPromise(npmProfile.set({ - tfa: { password: password, mode: 'disable' }, - }, conf)) + await npmProfile.set({ tfa: { password: password, mode: 'disable' } }, conf) if (this.npm.config.get('json')) { this.npm.output(JSON.stringify({ tfa: false }, null, 2)) diff --git a/lib/commands/publish.js b/lib/commands/publish.js index cf6b50cce3c21..6ff6f4d85c014 100644 --- a/lib/commands/publish.js +++ b/lib/commands/publish.js @@ -1,4 +1,4 @@ -const log = require('../utils/log-shim.js') +const log = require('proc-log') const semver = require('semver') const pack = require('libnpmpack') const libpub = require('libnpmpublish').publish @@ -59,7 +59,6 @@ class Publish extends BaseCommand { } const opts = { ...this.npm.flatOptions, progress: false } - log.disableProgress() // you can publish name@version, ./foo.tgz, etc. // even though the default is the 'file:.' cwd. diff --git a/lib/commands/query.js b/lib/commands/query.js index dfa1356ebf436..acf2fe3d9e9d1 100644 --- a/lib/commands/query.js +++ b/lib/commands/query.js @@ -2,7 +2,7 @@ const { resolve } = require('path') const BaseCommand = require('../base-command.js') -const log = require('../utils/log-shim.js') +const log = require('proc-log') class QuerySelectorItem { constructor (node) { diff --git a/lib/commands/run-script.js b/lib/commands/run-script.js index 75f00a46b84e9..58bd51e00c2ad 100644 --- a/lib/commands/run-script.js +++ b/lib/commands/run-script.js @@ -1,7 +1,7 @@ const runScript = require('@npmcli/run-script') const { isServerPackage } = runScript const pkgJson = require('@npmcli/package-json') -const log = require('../utils/log-shim.js') +const log = require('proc-log') const didYouMean = require('../utils/did-you-mean.js') const { isWindowsShell } = require('../utils/is-windows.js') @@ -108,18 +108,13 @@ class RunScript extends BaseCommand { } } - const opts = { - path, - args, - scriptShell, - stdio: 'inherit', - pkg, - banner: !this.npm.silent, - } - for (const [ev, evArgs] of events) { await runScript({ - ...opts, + path, + scriptShell, + stdio: 'inherit', + pkg, + banner: !this.npm.silent, event: ev, args: evArgs, }) diff --git a/lib/commands/sbom.js b/lib/commands/sbom.js index 311dfbc852406..d43c94826dc9b 100644 --- a/lib/commands/sbom.js +++ b/lib/commands/sbom.js @@ -1,9 +1,8 @@ 'use strict' -const { EOL } = require('os') const localeCompare = require('@isaacs/string-locale-compare')('en') const BaseCommand = require('../base-command.js') -const log = require('../utils/log-shim.js') +const log = require('proc-log') const { cyclonedxOutput } = require('../utils/sbom-cyclonedx.js') const { spdxOutput } = require('../utils/sbom-spdx.js') @@ -77,7 +76,7 @@ class SBOM extends BaseCommand { if (errors.size > 0) { throw Object.assign( - new Error([...errors].join(EOL)), + new Error([...errors].join('\n')), { code: 'ESBOMPROBLEMS' } ) } diff --git a/lib/commands/search.js b/lib/commands/search.js index bb94d6da20f1c..7f92e995cf2fd 100644 --- a/lib/commands/search.js +++ b/lib/commands/search.js @@ -1,7 +1,7 @@ const { Minipass } = require('minipass') const Pipeline = require('minipass-pipeline') const libSearch = require('libnpmsearch') -const log = require('../utils/log-shim.js') +const log = require('proc-log') const formatSearchStream = require('../utils/format-search-stream.js') @@ -108,7 +108,6 @@ class Search extends BaseCommand { } log.silly('search', 'search completed') - log.clearProgress() } } module.exports = Search diff --git a/lib/commands/shrinkwrap.js b/lib/commands/shrinkwrap.js index c6d817d480142..7febc2f9b0460 100644 --- a/lib/commands/shrinkwrap.js +++ b/lib/commands/shrinkwrap.js @@ -1,6 +1,6 @@ const { resolve, basename } = require('path') const { unlink } = require('fs').promises -const log = require('../utils/log-shim') +const log = require('proc-log') const BaseCommand = require('../base-command.js') class Shrinkwrap extends BaseCommand { static description = 'Lock down dependency versions for publication' diff --git a/lib/commands/star.js b/lib/commands/star.js index 20039bf893811..4a84adf641b8d 100644 --- a/lib/commands/star.js +++ b/lib/commands/star.js @@ -1,6 +1,6 @@ const fetch = require('npm-registry-fetch') const npa = require('npm-package-arg') -const log = require('../utils/log-shim') +const log = require('proc-log') const getIdentity = require('../utils/get-identity') const BaseCommand = require('../base-command.js') diff --git a/lib/commands/stars.js b/lib/commands/stars.js index 4214134eb5871..73b5dbb2d7f7f 100644 --- a/lib/commands/stars.js +++ b/lib/commands/stars.js @@ -1,5 +1,5 @@ const fetch = require('npm-registry-fetch') -const log = require('../utils/log-shim') +const log = require('proc-log') const getIdentity = require('../utils/get-identity.js') const BaseCommand = require('../base-command.js') diff --git a/lib/commands/token.js b/lib/commands/token.js index dc1df6e0fcb25..361dfe52e8006 100644 --- a/lib/commands/token.js +++ b/lib/commands/token.js @@ -1,9 +1,8 @@ const Table = require('cli-table3') -const log = require('../utils/log-shim.js') +const log = require('proc-log') const profile = require('npm-profile') const otplease = require('../utils/otplease.js') -const pulseTillDone = require('../utils/pulse-till-done.js') const readUserInfo = require('../utils/read-user-info.js') const BaseCommand = require('../base-command.js') @@ -28,7 +27,6 @@ class Token extends BaseCommand { } async exec (args) { - log.gauge.show('token') if (args.length === 0) { return this.list() } @@ -51,7 +49,7 @@ class Token extends BaseCommand { async list () { const conf = this.config() log.info('token', 'getting list') - const tokens = await pulseTillDone.withPromise(profile.listTokens(conf)) + const tokens = profile.listTokens(conf) if (conf.json) { this.npm.output(JSON.stringify(tokens, null, 2)) return @@ -95,9 +93,8 @@ class Token extends BaseCommand { const conf = this.config() const toRemove = [] - const progress = log.newItem('removing tokens', toRemove.length) - progress.info('token', 'getting existing list') - const tokens = await pulseTillDone.withPromise(profile.listTokens(conf)) + log.info('token', `removing ${toRemove.length} tokens`) + const tokens = await profile.listTokens(conf) args.forEach(id => { const matches = tokens.filter(token => token.key.indexOf(id) === 0) if (matches.length === 1) { @@ -138,8 +135,10 @@ class Token extends BaseCommand { const password = await readUserInfo.password() const validCIDR = await this.validateCIDRList(cidr) log.info('token', 'creating') - const result = await pulseTillDone.withPromise( - otplease(this.npm, conf, c => profile.createToken(password, readonly, validCIDR, c)) + const result = await otplease( + this.npm, + conf, + c => profile.createToken(password, readonly, validCIDR, c) ) delete result.key delete result.updated diff --git a/lib/commands/unpublish.js b/lib/commands/unpublish.js index a4d445a035b62..0b351ef3e37f0 100644 --- a/lib/commands/unpublish.js +++ b/lib/commands/unpublish.js @@ -6,7 +6,7 @@ const pkgJson = require('@npmcli/package-json') const { flatten } = require('@npmcli/config/lib/definitions') const getIdentity = require('../utils/get-identity.js') -const log = require('../utils/log-shim') +const log = require('proc-log') const otplease = require('../utils/otplease.js') const LAST_REMAINING_VERSION_ERROR = 'Refusing to delete the last version of the package. ' + diff --git a/lib/commands/update.js b/lib/commands/update.js index 43d031c7ada3f..4799c635cae44 100644 --- a/lib/commands/update.js +++ b/lib/commands/update.js @@ -1,6 +1,6 @@ const path = require('path') -const log = require('../utils/log-shim.js') +const log = require('proc-log') const reifyFinish = require('../utils/reify-finish.js') diff --git a/lib/commands/view.js b/lib/commands/view.js index b19604f8c2ed3..255766267caaa 100644 --- a/lib/commands/view.js +++ b/lib/commands/view.js @@ -1,7 +1,7 @@ const columns = require('cli-columns') const fs = require('fs') const jsonParse = require('json-parse-even-better-errors') -const log = require('../utils/log-shim.js') +const log = require('proc-log') const npa = require('npm-package-arg') const { resolve } = require('path') const formatBytes = require('../utils/format-bytes.js') @@ -115,9 +115,6 @@ class View extends BaseCommand { reducedData = cleanBlanks(reducedData) log.silly('view', reducedData) } - // disable the progress bar entirely, as we can't meaningfully update it - // if we may have partial lines printed. - log.disableProgress() const msg = await this.jsonData(reducedData, pckmnt._id) if (msg !== '') { diff --git a/lib/npm.js b/lib/npm.js index d05b74ac74b83..912371a1afaf8 100644 --- a/lib/npm.js +++ b/lib/npm.js @@ -11,7 +11,7 @@ const usage = require('./utils/npm-usage.js') const LogFile = require('./utils/log-file.js') const Timers = require('./utils/timers.js') const Display = require('./utils/display.js') -const log = require('./utils/log-shim') +const log = require('proc-log') const { redactLog: replaceInfo } = require('@npmcli/redact') const updateNotifier = require('./utils/update-notifier.js') const pkg = require('../package.json') @@ -48,15 +48,14 @@ class Npm { #logChalk = null #noColorChalk = null - #outputBuffer = [] + #display = null #logFile = new LogFile() - #display = new Display() #timers = new Timers({ start: 'npm', listener: (name, ms) => { - const args = ['timing', name, `Completed in ${ms}ms`] - this.#logFile.log(...args) - this.#display.log(...args) + const args = [name, `Completed in ${ms}ms`] + this.#logFile.log('timing', ...args) + this.#display.logTiming(...args) }, }) @@ -72,7 +71,14 @@ class Npm { // allows tests created by tap inside this repo to not set the local // prefix to `npmRoot` since that is the first dir it would encounter when // doing implicit detection - constructor ({ npmRoot = dirname(__dirname), argv = [], excludeNpmCwd = false } = {}) { + constructor ({ + stdout = process.stdout, + stderr = process.stderr, + npmRoot = dirname(__dirname), + argv = [], + excludeNpmCwd = false, + } = {}) { + this.#display = new Display({ stdout, stderr }) this.#npmRoot = npmRoot this.config = new Config({ npmPath: this.#npmRoot, @@ -244,14 +250,12 @@ class Npm { this.time('npm:load:display', () => { this.#display.load({ - // Use logColor since that is based on stderr - color: this.logColor, - chalk: this.logChalk, - progress: this.flatOptions.progress, - silent: this.silent, - timing: this.config.get('timing'), loglevel: this.config.get('loglevel'), + chalk: this.logChalk, // Use logChalk since that is based on stderr + timing: this.config.get('timing'), unicode: this.config.get('unicode'), + progress: this.flatOptions.progress, + json: this.config.get('json'), heading: this.config.get('heading'), }) process.env.COLOR = this.color ? '1' : '0' @@ -436,50 +440,24 @@ class Npm { return usage(this) } - // output to stdout in a progress bar compatible way - output (...msg) { - log.clearProgress() - // eslint-disable-next-line no-console - console.log(...msg.map(Display.clean)) - log.showProgress() + forceLog (...args) { + this.#display.forceLog(...args) } - outputBuffer (item) { - this.#outputBuffer.push(item) + output (...args) { + this.#display.output(...args) } - flushOutput (jsonError) { - if (!jsonError && !this.#outputBuffer.length) { - return - } - - if (this.config.get('json')) { - const jsonOutput = this.#outputBuffer.reduce((acc, item) => { - if (typeof item === 'string') { - // try to parse it as json in case its a string - try { - item = JSON.parse(item) - } catch { - return acc - } - } - return { ...acc, ...item } - }, {}) - this.output(JSON.stringify({ ...jsonOutput, ...jsonError }, null, 2)) - } else { - for (const item of this.#outputBuffer) { - this.output(item) - } - } + outputError (...args) { + this.#display.outputError(...args) + } - this.#outputBuffer.length = 0 + outputBuffer (arg) { + this.#display.outputBuffer(arg) } - outputError (...msg) { - log.clearProgress() - // eslint-disable-next-line no-console - console.error(...msg.map(Display.clean)) - log.showProgress() + flushOutput (jsonError) { + this.#display.flushOutput(jsonError) } } module.exports = Npm diff --git a/lib/package-url-cmd.js b/lib/package-url-cmd.js index 250b46eeeddbe..6e43b8989c191 100644 --- a/lib/package-url-cmd.js +++ b/lib/package-url-cmd.js @@ -4,7 +4,7 @@ const pacote = require('pacote') const hostedGitInfo = require('hosted-git-info') const openUrl = require('./utils/open-url.js') -const log = require('./utils/log-shim') +const log = require('proc-log') const BaseCommand = require('./base-command.js') class PackageUrlCommand extends BaseCommand { diff --git a/lib/utils/audit-error.js b/lib/utils/audit-error.js index f9850d718b198..69025506d674b 100644 --- a/lib/utils/audit-error.js +++ b/lib/utils/audit-error.js @@ -1,4 +1,4 @@ -const log = require('./log-shim') +const log = require('proc-log') const { redactLog: replaceInfo } = require('@npmcli/redact') // print an error or just nothing if the audit report has an error diff --git a/lib/utils/auth.js b/lib/utils/auth.js index 729ce32c2a7a8..931c74c04f606 100644 --- a/lib/utils/auth.js +++ b/lib/utils/auth.js @@ -1,5 +1,5 @@ const profile = require('npm-profile') -const log = require('../utils/log-shim') +const log = require('proc-log') const openUrlPrompt = require('../utils/open-url-prompt.js') const read = require('../utils/read-user-info.js') const otplease = require('../utils/otplease.js') diff --git a/lib/utils/display.js b/lib/utils/display.js index c5e5ca2b5b874..c2e4918258afe 100644 --- a/lib/utils/display.js +++ b/lib/utils/display.js @@ -1,174 +1,217 @@ -const { inspect } = require('util') -const npmlog = require('npmlog') -const log = require('./log-shim.js') +const proggy = require('proggy') +const log = require('proc-log') const { explain } = require('./explain-eresolve.js') +const { formatWithOptions, format } = require('./format') + +const COLOR_PALETTE = ({ chalk: c }) => ({ + heading: c.white.bgBlack, + title: c.magenta, + timing: c.green.bgBlack, + // loglevels + error: c.red.bgBlack, + warn: c.black.bgYellow, + notice: c.blue.bgBlack, + http: c.green.bgBlack, + info: c.green, + verbose: c.blue.bgBlack, + silly: c.inverse, +}) + +const LEVELS = ['timing', ...log.LEVELS].reduce((acc, key) => { + acc[key] = key + return acc +}, {}) + +const LEVEL_OPTIONS = { + silent: { + index: 0, + }, + error: { + index: 1, + label: 'ERR!', + }, + warn: { + index: 2, + label: 'WARN', + }, + notice: { + index: 3, + }, + http: { + index: 4, + }, + info: { + index: 5, + }, + verbose: { + index: 6, + label: 'verb', + }, + silly: { + index: 7, + label: 'sill', + }, +} -const originalCustomInspect = Symbol('npm.display.original.util.inspect.custom') - -// These are most assuredly not a mistake -// https://eslint.org/docs/latest/rules/no-control-regex -/* eslint-disable no-control-regex */ -// \x00 through \x1f, \x7f through \x9f, not including \x09 \x0a \x0b \x0d -const hasC01 = /[\x00-\x08\x0c\x0e-\x1f\x7f-\x9f]/ -// Allows everything up to '[38;5;255m' in 8 bit notation -const allowedSGR = /^\[[0-9;]{0,8}m/ -// '[38;5;255m'.length -const sgrMaxLen = 10 - -// Strips all ANSI C0 and C1 control characters (except for SGR up to 8 bit) -function stripC01 (str) { - if (!hasC01.test(str)) { - return str - } - let result = '' - for (let i = 0; i < str.length; i++) { - const char = str[i] - const code = char.charCodeAt(0) - if (!hasC01.test(char)) { - // Most characters are in this set so continue early if we can - result = `${result}${char}` - } else if (code === 27 && allowedSGR.test(str.slice(i + 1, i + sgrMaxLen + 1))) { - // \x1b with allowed SGR - result = `${result}\x1b` - } else if (code <= 31) { - // escape all other C0 control characters besides \x7f - result = `${result}^${String.fromCharCode(code + 64)}` - } else { - // hasC01 ensures this is now a C1 control character or \x7f - result = `${result}^${String.fromCharCode(code - 64)}` - } +const LEVEL_METHODS = { + ...LEVEL_OPTIONS, + [LEVELS.timing]: { + show: ({ timing, index }) => !!timing && index !== 0, + }, +} + +const safeJsonParse = (maybeJsonStr) => { + if (typeof maybeJsonStr !== 'string') { + return maybeJsonStr + } + try { + return JSON.parse(maybeJsonStr) + } catch { + return {} } - return result +} + +const setBlocking = (stream) => { + // Copied from https://github.com/yargs/set-blocking + // https://raw.githubusercontent.com/yargs/set-blocking/master/LICENSE.txt + /* istanbul ignore next - we trust that this works */ + if (stream._handle && stream.isTTY && typeof stream._handle.setBlocking === 'function') { + stream._handle.setBlocking(true) + } + return stream } class Display { - #chalk = null + // pause by default until config is loaded + #paused = true - constructor () { - // pause by default until config is loaded - this.on() - log.pause() - } + // buffers to store logs when paused + #logBuffer = [] + #outputBuffer = [] - static clean (output) { - if (typeof output === 'string') { - // Strings are cleaned inline - return stripC01(output) - } - if (!output || typeof output !== 'object') { - // Numbers, booleans, null all end up here and don't need cleaning - return output - } - // output && typeof output === 'object' - // We can't use hasOwn et al for detecting the original but we can use it - // for detecting the properties we set via defineProperty - if ( - output[inspect.custom] && - (!Object.hasOwn(output, originalCustomInspect)) - ) { - // Save the old one if we didn't already do it. - Object.defineProperty(output, originalCustomInspect, { - value: output[inspect.custom], - writable: true, - }) - } - if (!Object.hasOwn(output, originalCustomInspect)) { - // Put a dummy one in for when we run multiple times on the same object - Object.defineProperty(output, originalCustomInspect, { - value: function () { - return this - }, - writable: true, - }) - } - // Set the custom inspect to our own function - Object.defineProperty(output, inspect.custom, { - value: function () { - const toClean = this[originalCustomInspect]() - // Custom inspect can return things other than objects, check type again - if (typeof toClean === 'string') { - // Strings are cleaned inline - return stripC01(toClean) - } - if (!toClean || typeof toClean !== 'object') { - // Numbers, booleans, null all end up here and don't need cleaning - return toClean - } - return stripC01(inspect(toClean, { customInspect: false })) - }, - writable: true, - }) - return output - } - - on () { + // colors + #chalk + #colors + + // progress + #progress + + // options + #levelIndex + #timing + #json + #heading + + // display streams + #stdout + #stderr + + constructor ({ stdout, stderr }) { + this.#stdout = setBlocking(stdout) + this.#stderr = setBlocking(stderr) process.on('log', this.#logHandler) } off () { process.off('log', this.#logHandler) - // Unbalanced calls to enable/disable progress - // will leave change listeners on the tracker - // This pretty much only happens in tests but - // this removes the event emitter listener warnings - log.tracker.removeAllListeners() - } - - load (config) { - const { - color, - chalk, - timing, - loglevel, - unicode, - progress, - silent, - heading = 'npm', - } = config + this.#logBuffer.length = 0 + if (this.#progress) { + this.#progress.stop() + } + } + load ({ loglevel, chalk, timing, unicode, progress, json, heading }) { this.#chalk = chalk + this.#colors = COLOR_PALETTE({ chalk }) - // npmlog is still going away someday, so this is a hack to dynamically - // set the loglevel of timing based on the timing flag, instead of making - // a breaking change to npmlog. The result is that timing logs are never - // shown except when the --timing flag is set. We also need to change - // the index of the silly level since otherwise it is set to -Infinity - // and we can't go any lower than that. silent is still set to Infinify - // because we DO want silent to hide timing levels. This allows for the - // special case of getting timing information while hiding all CLI output - // in order to get perf information that might be affected by writing to - // a terminal. XXX(npmlog): this will be removed along with npmlog - log.levels.silly = -10000 - log.levels.timing = log.levels[loglevel] + (timing ? 1 : -1) - - log.level = loglevel - log.heading = heading - - if (color) { - log.enableColor() + this.#levelIndex = LEVEL_OPTIONS[loglevel].index + this.#timing = timing + this.#json = json + this.#heading = heading + + if (this.#levelIndex <= 0) { + this.off() } else { - log.disableColor() + log.resume() + if (progress) { + this.#startProgress({ unicode }) + } } + } - if (unicode) { - log.enableUnicode() - } else { - log.disableUnicode() + logTiming (...args) { + this.#logHandler(LEVELS.timing, ...args) + } + + forceLog (level, ...args) { + // This will show the log regardless of the current loglevel, except when silent + this.#logHandler({ level, force: true }, ...args) + } + + output (...args) { + // TODO: make this respect silent option + this.#stdout.write(format(...args)) + } + + outputError (...args) { + this.#stderr.write(format(...args)) + } + + outputBuffer (item) { + this.#outputBuffer.push(item) + } + + flushOutput (jsonError) { + if (!jsonError && !this.#outputBuffer.length) { + return } - // if it's silent, don't show progress - if (progress && !silent) { - log.enableProgress() + if (this.#json) { + const output = this.#outputBuffer.reduce((a, i) => ({ ...a, ...safeJsonParse(i) }), {}) + this.output(JSON.stringify({ ...output, ...jsonError }, null, 2)) } else { - log.disableProgress() + this.#outputBuffer.forEach((item) => this.output(item)) } - // Resume displaying logs now that we have config - log.resume() + this.#outputBuffer.length = 0 } - log (...args) { - this.#logHandler(...args) + #write (...args) { + const { level: levelName, force = false } = typeof args[0] === 'string' + ? { level: args[0] } : args[0] + + if (levelName === LEVELS.pause) { + this.#paused = true + return + } + + if (levelName === LEVELS.resume) { + this.#paused = false + this.#logBuffer.forEach((item) => this.#write(...item)) + this.#logBuffer.length = 0 + return + } + + if (this.#paused) { + this.#logBuffer.push(args) + return + } + + const level = LEVEL_METHODS[levelName] + const show = level.show ?? (({ index }) => level.index <= index) + + if ((force && level.index !== 0) || show({ index: this.#levelIndex, timing: this.#timing })) { + // this mutates the array so we can pass args directly to format later + const [, title] = args.splice(0, 2) + const prefix = [ + this.#colors.heading(this.#heading), + this.#colors[levelName](level.label ?? levelName), + title ? this.#colors.title(title) : null, + ] + this.#stderr.write(formatWithOptions({ prefix }, ...args)) + } else if (this.#progress) { + // TODO: make this display a single log line of filtered messages + } } #logHandler = (level, ...args) => { @@ -177,38 +220,35 @@ class Display { } catch (ex) { try { // if it crashed once, it might again! - this.#npmlog('verbose', `attempt to log ${inspect(args)} crashed`, ex) + this.#write(LEVELS.verbose, null, `attempt to log crashed`, ...args, ex) } catch (ex2) { + /* istanbul ignore next - this happens if the object has an inspect method that crashes */ // eslint-disable-next-line no-console - console.error(`attempt to log ${inspect(args)} crashed`, ex, ex2) + console.error(`attempt to log crashed`, ex, ex2) } } } #log (...args) { - return this.#eresolveWarn(...args) || this.#npmlog(...args) - } - - // Explicitly call these on npmlog and not log shim - // This is the final place we should call npmlog before removing it. - #npmlog (level, ...args) { - npmlog[level](...args.map(Display.clean)) - } - - // Also (and this is a really inexcusable kludge), we patch the - // log.warn() method so that when we see a peerDep override - // explanation from Arborist, we can replace the object with a - // highly abbreviated explanation of what's being overridden. - #eresolveWarn (level, heading, message, expl) { - if (level === 'warn' && - heading === 'ERESOLVE' && - expl && typeof expl === 'object' - ) { - this.#npmlog(level, heading, message) - this.#npmlog(level, '', explain(expl, this.#chalk, 2)) - // Return true to short circuit other log in chain - return true + const [level, heading, message, expl] = args + if (level === LEVELS.warn && heading === 'ERESOLVE' && expl && typeof expl === 'object') { + // Also (and this is a really inexcusable kludge), we patch the + // log.warn() method so that when we see a peerDep override + // explanation from Arborist, we can replace the object with a + // highly abbreviated explanation of what's being overridden. + // TODO: this could probably be moved to arborist now that display is refactored + this.#write(level, heading, message) + this.#write(level, '', explain(expl, this.#chalk, 2)) + return } + this.#write(...args) + } + + #startProgress ({ unicode }) { + this.#progress = proggy.createClient({ normalize: true }) + // TODO: implement proggy trackers in arborist/doctor + // TODO: listen to progress events here and build progress UI + // TODO: see deprecated gauge package for what unicode chars were used } } diff --git a/lib/utils/error-message.js b/lib/utils/error-message.js index 348bb63e2d5ab..e68181bc0ea0b 100644 --- a/lib/utils/error-message.js +++ b/lib/utils/error-message.js @@ -2,7 +2,7 @@ const { format } = require('util') const { resolve } = require('path') const { redactLog: replaceInfo } = require('@npmcli/redact') const { report } = require('./explain-eresolve.js') -const log = require('./log-shim') +const log = require('proc-log') const messageText = msg => msg.map(line => line.slice(1).join(' ')).join('\n') diff --git a/lib/utils/exit-handler.js b/lib/utils/exit-handler.js index 8b4ab45c4d474..ab436a8f38951 100644 --- a/lib/utils/exit-handler.js +++ b/lib/utils/exit-handler.js @@ -1,7 +1,7 @@ const os = require('os') const fs = require('fs') -const log = require('./log-shim.js') +const log = require('proc-log') const errorMessage = require('./error-message.js') const { redactLog: replaceInfo } = require('@npmcli/redact') @@ -10,8 +10,6 @@ let exitHandlerCalled = false let showLogFileError = false process.on('exit', code => { - log.disableProgress() - // process.emit is synchronous, so the timeEnd handler will run before the // unfinished timer check below process.emit('timeEnd', 'npm') @@ -106,8 +104,6 @@ process.on('exit', code => { const exitHandler = err => { exitHandlerCalled = true - log.disableProgress() - const hasLoadedNpm = npm?.config.loaded if (!npm) { @@ -125,10 +121,7 @@ const exitHandler = err => { // only show the notification if it finished. if (typeof npm.updateNotification === 'string') { - const { level } = log - log.level = 'notice' - log.notice('', npm.updateNotification) - log.level = level + npm.forceLog('notice', '', npm.updateNotification) } let exitCode = process.exitCode || 0 diff --git a/lib/utils/format.js b/lib/utils/format.js new file mode 100644 index 0000000000000..97f01996a2025 --- /dev/null +++ b/lib/utils/format.js @@ -0,0 +1,52 @@ +const { formatWithOptions: baseFormatWithOptions } = require('util') + +// These are most assuredly not a mistake +// https://eslint.org/docs/latest/rules/no-control-regex +// \x00 through \x1f, \x7f through \x9f, not including \x09 \x0a \x0b \x0d +/* eslint-disable-next-line no-control-regex */ +const HAS_C01 = /[\x00-\x08\x0c\x0e-\x1f\x7f-\x9f]/ + +// Allows everything up to '[38;5;255m' in 8 bit notation +const ALLOWED_SGR = /^\[[0-9;]{0,8}m/ + +// '[38;5;255m'.length +const SGR_MAX_LEN = 10 + +// Strips all ANSI C0 and C1 control characters (except for SGR up to 8 bit) +function STRIP_C01 (str) { + if (!HAS_C01.test(str)) { + return str + } + let result = '' + for (let i = 0; i < str.length; i++) { + const char = str[i] + const code = char.charCodeAt(0) + if (!HAS_C01.test(char)) { + // Most characters are in this set so continue early if we can + result = `${result}${char}` + } else if (code === 27 && ALLOWED_SGR.test(str.slice(i + 1, i + SGR_MAX_LEN + 1))) { + // \x1b with allowed SGR + result = `${result}\x1b` + } else if (code <= 31) { + // escape all other C0 control characters besides \x7f + result = `${result}^${String.fromCharCode(code + 64)}` + } else { + // hasC01 ensures this is now a C1 control character or \x7f + result = `${result}^${String.fromCharCode(code - 64)}` + } + } + return result +} + +const formatWithOptions = ({ prefix: prefixes = [], eol = '\n', ...options }, ...args) => { + const prefix = prefixes.filter(p => p != null).join(' ') + const formatted = STRIP_C01(baseFormatWithOptions(options, ...args)) + // Splitting could be changed to only `\n` once we are sure we only emit unix newlines. + // The eol param to this function will put the correct newlines in place for the returned string. + const lines = formatted.split(/\r?\n/) + return lines.reduce((acc, l) => `${acc}${prefix}${prefix && l ? ' ' : ''}${l}${eol}`, '') +} + +const format = (...args) => formatWithOptions({}, ...args) + +module.exports = { format, formatWithOptions } diff --git a/lib/utils/log-file.js b/lib/utils/log-file.js index 1a46b7da0d660..4a5eaf9be0280 100644 --- a/lib/utils/log-file.js +++ b/lib/utils/log-file.js @@ -1,11 +1,10 @@ const os = require('os') const { join, dirname, basename } = require('path') -const { format } = require('util') const { Minipass } = require('minipass') const fsMiniPass = require('fs-minipass') const fs = require('fs/promises') -const log = require('./log-shim') -const Display = require('./display') +const log = require('proc-log') +const { formatWithOptions } = require('./format') const padZero = (n, length) => n.toString().padStart(length.toString().length, '0') @@ -40,21 +39,6 @@ class LogFiles { this.on() } - static format (count, level, title, ...args) { - let prefix = `${count} ${level}` - if (title) { - prefix += ` ${title}` - } - - return format(...args) - .split(/\r?\n/) - .map(Display.clean) - .reduce((lines, line) => - lines += prefix + (line ? ' ' : '') + line + os.EOL, - '' - ) - } - on () { this.#logStream = new Minipass() process.on('log', this.#logHandler) @@ -150,9 +134,10 @@ class LogFiles { } } - #formatLogItem (...args) { + #formatLogItem (level, title, ...args) { this.#fileLogCount += 1 - return LogFiles.format(this.#totalLogCount++, ...args) + const prefix = [this.#totalLogCount++, level, title || null] + return formatWithOptions({ prefix, eol: os.EOL, colors: false }, ...args) } #getLogFilePath (count = '') { diff --git a/lib/utils/log-shim.js b/lib/utils/log-shim.js deleted file mode 100644 index 9d5a36d967413..0000000000000 --- a/lib/utils/log-shim.js +++ /dev/null @@ -1,59 +0,0 @@ -const NPMLOG = require('npmlog') -const PROCLOG = require('proc-log') - -// Sets getter and optionally a setter -// otherwise setting should throw -const accessors = (obj, set) => (k) => ({ - get: () => obj[k], - set: set ? (v) => (obj[k] = v) : () => { - throw new Error(`Cant set ${k}`) - }, -}) - -// Set the value to a bound function on the object -const value = (obj) => (k) => ({ - value: (...args) => obj[k].apply(obj, args), -}) - -const properties = { - // npmlog getters/setters - level: accessors(NPMLOG, true), - heading: accessors(NPMLOG, true), - levels: accessors(NPMLOG), - gauge: accessors(NPMLOG), - stream: accessors(NPMLOG), - tracker: accessors(NPMLOG), - progressEnabled: accessors(NPMLOG), - // npmlog methods - useColor: value(NPMLOG), - enableColor: value(NPMLOG), - disableColor: value(NPMLOG), - enableUnicode: value(NPMLOG), - disableUnicode: value(NPMLOG), - enableProgress: value(NPMLOG), - disableProgress: value(NPMLOG), - clearProgress: value(NPMLOG), - showProgress: value(NPMLOG), - newItem: value(NPMLOG), - newGroup: value(NPMLOG), - // proclog methods - notice: value(PROCLOG), - error: value(PROCLOG), - warn: value(PROCLOG), - info: value(PROCLOG), - verbose: value(PROCLOG), - http: value(PROCLOG), - silly: value(PROCLOG), - pause: value(PROCLOG), - resume: value(PROCLOG), -} - -const descriptors = Object.entries(properties).reduce((acc, [k, v]) => { - acc[k] = { enumerable: true, ...v(k) } - return acc -}, {}) - -// Create an object with the allowed properties rom npm log and all -// the logging methods from proc log -// XXX: this should go away and requires of this should be replaced with proc-log + new display -module.exports = Object.freeze(Object.defineProperties({}, descriptors)) diff --git a/lib/utils/otplease.js b/lib/utils/otplease.js index b4aa167469255..b8dd0b66ed766 100644 --- a/lib/utils/otplease.js +++ b/lib/utils/otplease.js @@ -1,4 +1,3 @@ -const log = require('./log-shim') async function otplease (npm, opts, fn) { try { return await fn(opts) @@ -8,7 +7,6 @@ async function otplease (npm, opts, fn) { } if (isWebOTP(err)) { - log.disableProgress() const webAuth = require('./web-auth') const openUrlPrompt = require('./open-url-prompt') diff --git a/lib/utils/pulse-till-done.js b/lib/utils/pulse-till-done.js deleted file mode 100644 index 2229414147483..0000000000000 --- a/lib/utils/pulse-till-done.js +++ /dev/null @@ -1,26 +0,0 @@ -const log = require('./log-shim.js') - -let pulseTimer = null -const withPromise = async (promise) => { - pulseStart() - try { - return await promise - } finally { - pulseStop() - } -} - -const pulseStart = () => { - pulseTimer = pulseTimer || setInterval(() => { - log.gauge.pulse('') - }, 150) -} - -const pulseStop = () => { - clearInterval(pulseTimer) - pulseTimer = null -} - -module.exports = { - withPromise, -} diff --git a/lib/utils/read-user-info.js b/lib/utils/read-user-info.js index fa1cea158e897..3c7817e3e491a 100644 --- a/lib/utils/read-user-info.js +++ b/lib/utils/read-user-info.js @@ -1,6 +1,6 @@ const { read } = require('read') const userValidate = require('npm-user-validate') -const log = require('./log-shim.js') +const log = require('proc-log') exports.otp = readOTP exports.password = readPassword @@ -16,17 +16,12 @@ const passwordPrompt = 'npm password: ' const usernamePrompt = 'npm username: ' const emailPrompt = 'email (this IS public): ' -function readWithProgress (opts) { - log.clearProgress() - return read(opts).finally(() => log.showProgress()) -} - function readOTP (msg = otpPrompt, otp, isRetry) { if (isRetry && otp && /^[\d ]+$|^[A-Fa-f0-9]{64,64}$/.test(otp)) { return otp.replace(/\s+/g, '') } - return readWithProgress({ prompt: msg, default: otp || '' }) + return read({ prompt: msg, default: otp || '' }) .then((rOtp) => readOTP(msg, rOtp, true)) } @@ -35,7 +30,7 @@ function readPassword (msg = passwordPrompt, password, isRetry) { return password } - return readWithProgress({ prompt: msg, silent: true, default: password || '' }) + return read({ prompt: msg, silent: true, default: password || '' }) .then((rPassword) => readPassword(msg, rPassword, true)) } @@ -49,7 +44,7 @@ function readUsername (msg = usernamePrompt, username, isRetry) { } } - return readWithProgress({ prompt: msg, default: username || '' }) + return read({ prompt: msg, default: username || '' }) .then((rUsername) => readUsername(msg, rUsername, true)) } @@ -63,6 +58,6 @@ function readEmail (msg = emailPrompt, email, isRetry) { } } - return readWithProgress({ prompt: msg, default: email || '' }) + return read({ prompt: msg, default: email || '' }) .then((username) => readEmail(msg, username, true)) } diff --git a/lib/utils/reify-output.js b/lib/utils/reify-output.js index 44c913812a8ef..3b2b69279e190 100644 --- a/lib/utils/reify-output.js +++ b/lib/utils/reify-output.js @@ -9,7 +9,7 @@ // found 37 vulnerabilities (5 low, 7 moderate, 25 high) // run `npm audit fix` to fix them, or `npm audit` for details -const log = require('./log-shim.js') +const log = require('proc-log') const { depth } = require('treeverse') const ms = require('ms') const npmAuditReport = require('npm-audit-report') diff --git a/lib/utils/tar.js b/lib/utils/tar.js index c25fe71614a60..e03b4b65466e4 100644 --- a/lib/utils/tar.js +++ b/lib/utils/tar.js @@ -1,6 +1,6 @@ const tar = require('tar') const ssri = require('ssri') -const log = require('./log-shim') +const log = require('proc-log') const formatBytes = require('./format-bytes.js') const columnify = require('columnify') const localeCompare = require('@isaacs/string-locale-compare')('en', { diff --git a/lib/utils/timers.js b/lib/utils/timers.js index c215fe926afb5..c897757b697fd 100644 --- a/lib/utils/timers.js +++ b/lib/utils/timers.js @@ -1,6 +1,6 @@ const EE = require('events') const fs = require('fs') -const log = require('./log-shim') +const log = require('proc-log') // This is an event emiiter but on/off // only listen on a single internal event that gets diff --git a/node_modules/.gitignore b/node_modules/.gitignore index e0f4034c7f08b..10c7e82b9c489 100644 --- a/node_modules/.gitignore +++ b/node_modules/.gitignore @@ -57,7 +57,6 @@ !/ansi-styles !/aproba !/archy -!/are-we-there-yet !/balanced-match !/bin-links !/binary-extensions @@ -75,10 +74,8 @@ !/cmd-shim !/color-convert !/color-name -!/color-support !/columnify !/common-ancestor-path -!/console-control-strings !/cross-spawn !/cross-spawn/node_modules/ /cross-spawn/node_modules/* @@ -100,10 +97,8 @@ !/foreground-child !/fs-minipass !/function-bind -!/gauge !/glob !/graceful-fs -!/has-unicode !/hasown !/hosted-git-info !/http-cache-semantics @@ -175,7 +170,6 @@ !/npm-profile !/npm-registry-fetch !/npm-user-validate -!/npmlog !/p-map !/pacote !/parse-conflict-json @@ -183,6 +177,7 @@ !/path-scurry !/postcss-selector-parser !/proc-log +!/proggy !/promise-all-reject-late !/promise-call-limit !/promise-inflight @@ -199,7 +194,6 @@ !/semver/node_modules/ /semver/node_modules/* !/semver/node_modules/lru-cache -!/set-blocking !/shebang-command !/shebang-regex !/signal-exit @@ -246,7 +240,6 @@ !/which/node_modules/ /which/node_modules/* !/which/node_modules/isexe -!/wide-align !/wrap-ansi-cjs !/wrap-ansi-cjs/node_modules/ /wrap-ansi-cjs/node_modules/* diff --git a/node_modules/are-we-there-yet/LICENSE.md b/node_modules/are-we-there-yet/LICENSE.md deleted file mode 100644 index 845be76f64e78..0000000000000 --- a/node_modules/are-we-there-yet/LICENSE.md +++ /dev/null @@ -1,18 +0,0 @@ -ISC License - -Copyright npm, Inc. - -Permission to use, copy, modify, and/or distribute this -software for any purpose with or without fee is hereby -granted, provided that the above copyright notice and this -permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND NPM DISCLAIMS ALL -WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO -EVENT SHALL NPM BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE -USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/node_modules/are-we-there-yet/lib/index.js b/node_modules/are-we-there-yet/lib/index.js deleted file mode 100644 index 57d8743fdad17..0000000000000 --- a/node_modules/are-we-there-yet/lib/index.js +++ /dev/null @@ -1,4 +0,0 @@ -'use strict' -exports.TrackerGroup = require('./tracker-group.js') -exports.Tracker = require('./tracker.js') -exports.TrackerStream = require('./tracker-stream.js') diff --git a/node_modules/are-we-there-yet/lib/tracker-base.js b/node_modules/are-we-there-yet/lib/tracker-base.js deleted file mode 100644 index 1b5e0dc30c49b..0000000000000 --- a/node_modules/are-we-there-yet/lib/tracker-base.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict' -const EventEmitter = require('events') - -let trackerId = 0 -class TrackerBase extends EventEmitter { - constructor (name) { - super() - this.id = ++trackerId - this.name = name - } -} - -module.exports = TrackerBase diff --git a/node_modules/are-we-there-yet/lib/tracker-group.js b/node_modules/are-we-there-yet/lib/tracker-group.js deleted file mode 100644 index 162c22584cdc5..0000000000000 --- a/node_modules/are-we-there-yet/lib/tracker-group.js +++ /dev/null @@ -1,112 +0,0 @@ -'use strict' -const TrackerBase = require('./tracker-base.js') -const Tracker = require('./tracker.js') -const TrackerStream = require('./tracker-stream.js') - -class TrackerGroup extends TrackerBase { - parentGroup = null - trackers = [] - completion = {} - weight = {} - totalWeight = 0 - finished = false - bubbleChange = bubbleChange(this) - - nameInTree () { - var names = [] - var from = this - while (from) { - names.unshift(from.name) - from = from.parentGroup - } - return names.join('/') - } - - addUnit (unit, weight) { - if (unit.addUnit) { - var toTest = this - while (toTest) { - if (unit === toTest) { - throw new Error( - 'Attempted to add tracker group ' + - unit.name + ' to tree that already includes it ' + - this.nameInTree(this)) - } - toTest = toTest.parentGroup - } - unit.parentGroup = this - } - this.weight[unit.id] = weight || 1 - this.totalWeight += this.weight[unit.id] - this.trackers.push(unit) - this.completion[unit.id] = unit.completed() - unit.on('change', this.bubbleChange) - if (!this.finished) { - this.emit('change', unit.name, this.completion[unit.id], unit) - } - return unit - } - - completed () { - if (this.trackers.length === 0) { - return 0 - } - var valPerWeight = 1 / this.totalWeight - var completed = 0 - for (var ii = 0; ii < this.trackers.length; ii++) { - var trackerId = this.trackers[ii].id - completed += - valPerWeight * this.weight[trackerId] * this.completion[trackerId] - } - return completed - } - - newGroup (name, weight) { - return this.addUnit(new TrackerGroup(name), weight) - } - - newItem (name, todo, weight) { - return this.addUnit(new Tracker(name, todo), weight) - } - - newStream (name, todo, weight) { - return this.addUnit(new TrackerStream(name, todo), weight) - } - - finish () { - this.finished = true - if (!this.trackers.length) { - this.addUnit(new Tracker(), 1, true) - } - for (var ii = 0; ii < this.trackers.length; ii++) { - var tracker = this.trackers[ii] - tracker.finish() - tracker.removeListener('change', this.bubbleChange) - } - this.emit('change', this.name, 1, this) - } - - debug (depth = 0) { - const indent = ' '.repeat(depth) - let output = `${indent}${this.name || 'top'}: ${this.completed()}\n` - - this.trackers.forEach(function (tracker) { - output += tracker instanceof TrackerGroup - ? tracker.debug(depth + 1) - : `${indent} ${tracker.name}: ${tracker.completed()}\n` - }) - return output - } -} - -function bubbleChange (trackerGroup) { - return function (name, completed, tracker) { - trackerGroup.completion[tracker.id] = completed - if (trackerGroup.finished) { - return - } - trackerGroup.emit('change', name || trackerGroup.name, trackerGroup.completed(), trackerGroup) - } -} - -module.exports = TrackerGroup diff --git a/node_modules/are-we-there-yet/lib/tracker-stream.js b/node_modules/are-we-there-yet/lib/tracker-stream.js deleted file mode 100644 index 75e44df309150..0000000000000 --- a/node_modules/are-we-there-yet/lib/tracker-stream.js +++ /dev/null @@ -1,42 +0,0 @@ -'use strict' -const stream = require('stream') -const Tracker = require('./tracker.js') - -class TrackerStream extends stream.Transform { - constructor (name, size, options) { - super(options) - this.tracker = new Tracker(name, size) - this.name = name - this.id = this.tracker.id - this.tracker.on('change', this.trackerChange.bind(this)) - } - - trackerChange (name, completion) { - this.emit('change', name, completion, this) - } - - _transform (data, encoding, cb) { - this.tracker.completeWork(data.length ? data.length : 1) - this.push(data) - cb() - } - - _flush (cb) { - this.tracker.finish() - cb() - } - - completed () { - return this.tracker.completed() - } - - addWork (work) { - return this.tracker.addWork(work) - } - - finish () { - return this.tracker.finish() - } -} - -module.exports = TrackerStream diff --git a/node_modules/are-we-there-yet/lib/tracker.js b/node_modules/are-we-there-yet/lib/tracker.js deleted file mode 100644 index 02e879ce6e3e2..0000000000000 --- a/node_modules/are-we-there-yet/lib/tracker.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict' -const TrackerBase = require('./tracker-base.js') - -class Tracker extends TrackerBase { - constructor (name, todo) { - super(name) - this.workDone = 0 - this.workTodo = todo || 0 - } - - completed () { - return this.workTodo === 0 ? 0 : this.workDone / this.workTodo - } - - addWork (work) { - this.workTodo += work - this.emit('change', this.name, this.completed(), this) - } - - completeWork (work) { - this.workDone += work - if (this.workDone > this.workTodo) { - this.workDone = this.workTodo - } - this.emit('change', this.name, this.completed(), this) - } - - finish () { - this.workTodo = this.workDone = 1 - this.emit('change', this.name, 1, this) - } -} - -module.exports = Tracker diff --git a/node_modules/are-we-there-yet/package.json b/node_modules/are-we-there-yet/package.json deleted file mode 100644 index f072a21abb444..0000000000000 --- a/node_modules/are-we-there-yet/package.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "name": "are-we-there-yet", - "version": "4.0.2", - "description": "Keep track of the overall completion of many disparate processes", - "main": "lib/index.js", - "scripts": { - "test": "tap", - "lint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"", - "lintfix": "npm run lint -- --fix", - "posttest": "npm run lint", - "postsnap": "npm run lintfix --", - "snap": "tap", - "postlint": "template-oss-check", - "template-oss-apply": "template-oss-apply --force" - }, - "repository": { - "type": "git", - "url": "https://github.com/npm/are-we-there-yet.git" - }, - "author": "GitHub Inc.", - "license": "ISC", - "bugs": { - "url": "https://github.com/npm/are-we-there-yet/issues" - }, - "homepage": "https://github.com/npm/are-we-there-yet", - "devDependencies": { - "@npmcli/eslint-config": "^4.0.0", - "@npmcli/template-oss": "4.21.3", - "tap": "^16.0.1" - }, - "files": [ - "bin/", - "lib/" - ], - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "tap": { - "branches": 68, - "statements": 92, - "functions": 86, - "lines": 92, - "nyc-arg": [ - "--exclude", - "tap-snapshots/**" - ] - }, - "templateOSS": { - "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.21.3", - "publish": true - } -} diff --git a/node_modules/color-support/bin.js b/node_modules/color-support/bin.js deleted file mode 100755 index 3c0a967218083..0000000000000 --- a/node_modules/color-support/bin.js +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env node -var colorSupport = require('./')({alwaysReturn: true }) -console.log(JSON.stringify(colorSupport, null, 2)) diff --git a/node_modules/color-support/browser.js b/node_modules/color-support/browser.js deleted file mode 100644 index ab5c6631a35b8..0000000000000 --- a/node_modules/color-support/browser.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = colorSupport({ alwaysReturn: true }, colorSupport) - -function colorSupport(options, obj) { - obj = obj || {} - options = options || {} - obj.level = 0 - obj.hasBasic = false - obj.has256 = false - obj.has16m = false - if (!options.alwaysReturn) { - return false - } - return obj -} diff --git a/node_modules/color-support/index.js b/node_modules/color-support/index.js deleted file mode 100644 index 6b6f3b2819424..0000000000000 --- a/node_modules/color-support/index.js +++ /dev/null @@ -1,134 +0,0 @@ -// call it on itself so we can test the export val for basic stuff -module.exports = colorSupport({ alwaysReturn: true }, colorSupport) - -function hasNone (obj, options) { - obj.level = 0 - obj.hasBasic = false - obj.has256 = false - obj.has16m = false - if (!options.alwaysReturn) { - return false - } - return obj -} - -function hasBasic (obj) { - obj.hasBasic = true - obj.has256 = false - obj.has16m = false - obj.level = 1 - return obj -} - -function has256 (obj) { - obj.hasBasic = true - obj.has256 = true - obj.has16m = false - obj.level = 2 - return obj -} - -function has16m (obj) { - obj.hasBasic = true - obj.has256 = true - obj.has16m = true - obj.level = 3 - return obj -} - -function colorSupport (options, obj) { - options = options || {} - - obj = obj || {} - - // if just requesting a specific level, then return that. - if (typeof options.level === 'number') { - switch (options.level) { - case 0: - return hasNone(obj, options) - case 1: - return hasBasic(obj) - case 2: - return has256(obj) - case 3: - return has16m(obj) - } - } - - obj.level = 0 - obj.hasBasic = false - obj.has256 = false - obj.has16m = false - - if (typeof process === 'undefined' || - !process || - !process.stdout || - !process.env || - !process.platform) { - return hasNone(obj, options) - } - - var env = options.env || process.env - var stream = options.stream || process.stdout - var term = options.term || env.TERM || '' - var platform = options.platform || process.platform - - if (!options.ignoreTTY && !stream.isTTY) { - return hasNone(obj, options) - } - - if (!options.ignoreDumb && term === 'dumb' && !env.COLORTERM) { - return hasNone(obj, options) - } - - if (platform === 'win32') { - return hasBasic(obj) - } - - if (env.TMUX) { - return has256(obj) - } - - if (!options.ignoreCI && (env.CI || env.TEAMCITY_VERSION)) { - if (env.TRAVIS) { - return has256(obj) - } else { - return hasNone(obj, options) - } - } - - // TODO: add more term programs - switch (env.TERM_PROGRAM) { - case 'iTerm.app': - var ver = env.TERM_PROGRAM_VERSION || '0.' - if (/^[0-2]\./.test(ver)) { - return has256(obj) - } else { - return has16m(obj) - } - - case 'HyperTerm': - case 'Hyper': - return has16m(obj) - - case 'MacTerm': - return has16m(obj) - - case 'Apple_Terminal': - return has256(obj) - } - - if (/^xterm-256/.test(term)) { - return has256(obj) - } - - if (/^screen|^xterm|^vt100|color|ansi|cygwin|linux/i.test(term)) { - return hasBasic(obj) - } - - if (env.COLORTERM) { - return hasBasic(obj) - } - - return hasNone(obj, options) -} diff --git a/node_modules/color-support/package.json b/node_modules/color-support/package.json deleted file mode 100644 index f3e3b77145d6b..0000000000000 --- a/node_modules/color-support/package.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "color-support", - "version": "1.1.3", - "description": "A module which will endeavor to guess your terminal's level of color support.", - "main": "index.js", - "browser": "browser.js", - "bin": "bin.js", - "devDependencies": { - "tap": "^10.3.3" - }, - "scripts": { - "test": "tap test/*.js --100 -J", - "preversion": "npm test", - "postversion": "npm publish", - "postpublish": "git push origin --all; git push origin --tags" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/isaacs/color-support.git" - }, - "keywords": [ - "terminal", - "color", - "support", - "xterm", - "truecolor", - "256" - ], - "author": "Isaac Z. Schlueter (http://blog.izs.me/)", - "license": "ISC", - "files": [ - "browser.js", - "index.js", - "bin.js" - ] -} diff --git a/node_modules/console-control-strings/LICENSE b/node_modules/console-control-strings/LICENSE deleted file mode 100644 index e756052969b78..0000000000000 --- a/node_modules/console-control-strings/LICENSE +++ /dev/null @@ -1,13 +0,0 @@ -Copyright (c) 2014, Rebecca Turner - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/node_modules/console-control-strings/index.js b/node_modules/console-control-strings/index.js deleted file mode 100644 index bf890348ec6e3..0000000000000 --- a/node_modules/console-control-strings/index.js +++ /dev/null @@ -1,125 +0,0 @@ -'use strict' - -// These tables borrowed from `ansi` - -var prefix = '\x1b[' - -exports.up = function up (num) { - return prefix + (num || '') + 'A' -} - -exports.down = function down (num) { - return prefix + (num || '') + 'B' -} - -exports.forward = function forward (num) { - return prefix + (num || '') + 'C' -} - -exports.back = function back (num) { - return prefix + (num || '') + 'D' -} - -exports.nextLine = function nextLine (num) { - return prefix + (num || '') + 'E' -} - -exports.previousLine = function previousLine (num) { - return prefix + (num || '') + 'F' -} - -exports.horizontalAbsolute = function horizontalAbsolute (num) { - if (num == null) throw new Error('horizontalAboslute requires a column to position to') - return prefix + num + 'G' -} - -exports.eraseData = function eraseData () { - return prefix + 'J' -} - -exports.eraseLine = function eraseLine () { - return prefix + 'K' -} - -exports.goto = function (x, y) { - return prefix + y + ';' + x + 'H' -} - -exports.gotoSOL = function () { - return '\r' -} - -exports.beep = function () { - return '\x07' -} - -exports.hideCursor = function hideCursor () { - return prefix + '?25l' -} - -exports.showCursor = function showCursor () { - return prefix + '?25h' -} - -var colors = { - reset: 0, -// styles - bold: 1, - italic: 3, - underline: 4, - inverse: 7, -// resets - stopBold: 22, - stopItalic: 23, - stopUnderline: 24, - stopInverse: 27, -// colors - white: 37, - black: 30, - blue: 34, - cyan: 36, - green: 32, - magenta: 35, - red: 31, - yellow: 33, - bgWhite: 47, - bgBlack: 40, - bgBlue: 44, - bgCyan: 46, - bgGreen: 42, - bgMagenta: 45, - bgRed: 41, - bgYellow: 43, - - grey: 90, - brightBlack: 90, - brightRed: 91, - brightGreen: 92, - brightYellow: 93, - brightBlue: 94, - brightMagenta: 95, - brightCyan: 96, - brightWhite: 97, - - bgGrey: 100, - bgBrightBlack: 100, - bgBrightRed: 101, - bgBrightGreen: 102, - bgBrightYellow: 103, - bgBrightBlue: 104, - bgBrightMagenta: 105, - bgBrightCyan: 106, - bgBrightWhite: 107 -} - -exports.color = function color (colorWith) { - if (arguments.length !== 1 || !Array.isArray(colorWith)) { - colorWith = Array.prototype.slice.call(arguments) - } - return prefix + colorWith.map(colorNameToCode).join(';') + 'm' -} - -function colorNameToCode (color) { - if (colors[color] != null) return colors[color] - throw new Error('Unknown color or style name: ' + color) -} diff --git a/node_modules/console-control-strings/package.json b/node_modules/console-control-strings/package.json deleted file mode 100644 index eb6c62ae2dac7..0000000000000 --- a/node_modules/console-control-strings/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "console-control-strings", - "version": "1.1.0", - "description": "A library of cross-platform tested terminal/console command strings for doing things like color and cursor positioning. This is a subset of both ansi and vt100. All control codes included work on both Windows & Unix-like OSes, except where noted.", - "main": "index.js", - "directories": { - "test": "test" - }, - "scripts": { - "test": "standard && tap test/*.js" - }, - "repository": { - "type": "git", - "url": "https://github.com/iarna/console-control-strings" - }, - "keywords": [], - "author": "Rebecca Turner (http://re-becca.org/)", - "license": "ISC", - "files": [ - "LICENSE", - "index.js" - ], - "devDependencies": { - "standard": "^7.1.2", - "tap": "^5.7.2" - } -} diff --git a/node_modules/gauge/LICENSE.md b/node_modules/gauge/LICENSE.md deleted file mode 100644 index 5fc208ff122e0..0000000000000 --- a/node_modules/gauge/LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ - - -ISC License - -Copyright npm, Inc. - -Permission to use, copy, modify, and/or distribute this -software for any purpose with or without fee is hereby -granted, provided that the above copyright notice and this -permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND NPM DISCLAIMS ALL -WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO -EVENT SHALL NPM BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE -USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/node_modules/gauge/lib/base-theme.js b/node_modules/gauge/lib/base-theme.js deleted file mode 100644 index 00bf5684cddab..0000000000000 --- a/node_modules/gauge/lib/base-theme.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict' -var spin = require('./spin.js') -var progressBar = require('./progress-bar.js') - -module.exports = { - activityIndicator: function (values, theme, width) { - if (values.spun == null) { - return - } - return spin(theme, values.spun) - }, - progressbar: function (values, theme, width) { - if (values.completed == null) { - return - } - return progressBar(theme, width, values.completed) - }, -} diff --git a/node_modules/gauge/lib/error.js b/node_modules/gauge/lib/error.js deleted file mode 100644 index d9914ba5335d2..0000000000000 --- a/node_modules/gauge/lib/error.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict' -var util = require('util') - -var User = exports.User = function User (msg) { - var err = new Error(msg) - Error.captureStackTrace(err, User) - err.code = 'EGAUGE' - return err -} - -exports.MissingTemplateValue = function MissingTemplateValue (item, values) { - var err = new User(util.format('Missing template value "%s"', item.type)) - Error.captureStackTrace(err, MissingTemplateValue) - err.template = item - err.values = values - return err -} - -exports.Internal = function Internal (msg) { - var err = new Error(msg) - Error.captureStackTrace(err, Internal) - err.code = 'EGAUGEINTERNAL' - return err -} diff --git a/node_modules/gauge/lib/has-color.js b/node_modules/gauge/lib/has-color.js deleted file mode 100644 index 16cba0eb47d33..0000000000000 --- a/node_modules/gauge/lib/has-color.js +++ /dev/null @@ -1,4 +0,0 @@ -'use strict' -var colorSupport = require('color-support') - -module.exports = colorSupport().hasBasic diff --git a/node_modules/gauge/lib/index.js b/node_modules/gauge/lib/index.js deleted file mode 100644 index be94f53f3b5f4..0000000000000 --- a/node_modules/gauge/lib/index.js +++ /dev/null @@ -1,289 +0,0 @@ -'use strict' -var Plumbing = require('./plumbing.js') -var hasUnicode = require('has-unicode') -var hasColor = require('./has-color.js') -var onExit = require('signal-exit').onExit -var defaultThemes = require('./themes') -var setInterval = require('./set-interval.js') -var process = require('./process.js') -var setImmediate = require('./set-immediate') - -module.exports = Gauge - -function callWith (obj, method) { - return function () { - return method.call(obj) - } -} - -function Gauge (arg1, arg2) { - var options, writeTo - if (arg1 && arg1.write) { - writeTo = arg1 - options = arg2 || {} - } else if (arg2 && arg2.write) { - writeTo = arg2 - options = arg1 || {} - } else { - writeTo = process.stderr - options = arg1 || arg2 || {} - } - - this._status = { - spun: 0, - section: '', - subsection: '', - } - this._paused = false // are we paused for back pressure? - this._disabled = true // are all progress bar updates disabled? - this._showing = false // do we WANT the progress bar on screen - this._onScreen = false // IS the progress bar on screen - this._needsRedraw = false // should we print something at next tick? - this._hideCursor = options.hideCursor == null ? true : options.hideCursor - this._fixedFramerate = options.fixedFramerate == null - ? !(/^v0\.8\./.test(process.version)) - : options.fixedFramerate - this._lastUpdateAt = null - this._updateInterval = options.updateInterval == null ? 50 : options.updateInterval - - this._themes = options.themes || defaultThemes - this._theme = options.theme - var theme = this._computeTheme(options.theme) - var template = options.template || [ - { type: 'progressbar', length: 20 }, - { type: 'activityIndicator', kerning: 1, length: 1 }, - { type: 'section', kerning: 1, default: '' }, - { type: 'subsection', kerning: 1, default: '' }, - ] - this.setWriteTo(writeTo, options.tty) - var PlumbingClass = options.Plumbing || Plumbing - this._gauge = new PlumbingClass(theme, template, this.getWidth()) - - this._$$doRedraw = callWith(this, this._doRedraw) - this._$$handleSizeChange = callWith(this, this._handleSizeChange) - - this._cleanupOnExit = options.cleanupOnExit == null || options.cleanupOnExit - this._removeOnExit = null - - if (options.enabled || (options.enabled == null && this._tty && this._tty.isTTY)) { - this.enable() - } else { - this.disable() - } -} -Gauge.prototype = {} - -Gauge.prototype.isEnabled = function () { - return !this._disabled -} - -Gauge.prototype.setTemplate = function (template) { - this._gauge.setTemplate(template) - if (this._showing) { - this._requestRedraw() - } -} - -Gauge.prototype._computeTheme = function (theme) { - if (!theme) { - theme = {} - } - if (typeof theme === 'string') { - theme = this._themes.getTheme(theme) - } else if ( - Object.keys(theme).length === 0 || theme.hasUnicode != null || theme.hasColor != null - ) { - var useUnicode = theme.hasUnicode == null ? hasUnicode() : theme.hasUnicode - var useColor = theme.hasColor == null ? hasColor : theme.hasColor - theme = this._themes.getDefault({ - hasUnicode: useUnicode, - hasColor: useColor, - platform: theme.platform, - }) - } - return theme -} - -Gauge.prototype.setThemeset = function (themes) { - this._themes = themes - this.setTheme(this._theme) -} - -Gauge.prototype.setTheme = function (theme) { - this._gauge.setTheme(this._computeTheme(theme)) - if (this._showing) { - this._requestRedraw() - } - this._theme = theme -} - -Gauge.prototype._requestRedraw = function () { - this._needsRedraw = true - if (!this._fixedFramerate) { - this._doRedraw() - } -} - -Gauge.prototype.getWidth = function () { - return ((this._tty && this._tty.columns) || 80) - 1 -} - -Gauge.prototype.setWriteTo = function (writeTo, tty) { - var enabled = !this._disabled - if (enabled) { - this.disable() - } - this._writeTo = writeTo - this._tty = tty || - (writeTo === process.stderr && process.stdout.isTTY && process.stdout) || - (writeTo.isTTY && writeTo) || - this._tty - if (this._gauge) { - this._gauge.setWidth(this.getWidth()) - } - if (enabled) { - this.enable() - } -} - -Gauge.prototype.enable = function () { - if (!this._disabled) { - return - } - this._disabled = false - if (this._tty) { - this._enableEvents() - } - if (this._showing) { - this.show() - } -} - -Gauge.prototype.disable = function () { - if (this._disabled) { - return - } - if (this._showing) { - this._lastUpdateAt = null - this._showing = false - this._doRedraw() - this._showing = true - } - this._disabled = true - if (this._tty) { - this._disableEvents() - } -} - -Gauge.prototype._enableEvents = function () { - if (this._cleanupOnExit) { - this._removeOnExit = onExit(callWith(this, this.disable)) - } - this._tty.on('resize', this._$$handleSizeChange) - if (this._fixedFramerate) { - this.redrawTracker = setInterval(this._$$doRedraw, this._updateInterval) - if (this.redrawTracker.unref) { - this.redrawTracker.unref() - } - } -} - -Gauge.prototype._disableEvents = function () { - this._tty.removeListener('resize', this._$$handleSizeChange) - if (this._fixedFramerate) { - clearInterval(this.redrawTracker) - } - if (this._removeOnExit) { - this._removeOnExit() - } -} - -Gauge.prototype.hide = function (cb) { - if (this._disabled) { - return cb && process.nextTick(cb) - } - if (!this._showing) { - return cb && process.nextTick(cb) - } - this._showing = false - this._doRedraw() - cb && setImmediate(cb) -} - -Gauge.prototype.show = function (section, completed) { - this._showing = true - if (typeof section === 'string') { - this._status.section = section - } else if (typeof section === 'object') { - var sectionKeys = Object.keys(section) - for (var ii = 0; ii < sectionKeys.length; ++ii) { - var key = sectionKeys[ii] - this._status[key] = section[key] - } - } - if (completed != null) { - this._status.completed = completed - } - if (this._disabled) { - return - } - this._requestRedraw() -} - -Gauge.prototype.pulse = function (subsection) { - this._status.subsection = subsection || '' - this._status.spun++ - if (this._disabled) { - return - } - if (!this._showing) { - return - } - this._requestRedraw() -} - -Gauge.prototype._handleSizeChange = function () { - this._gauge.setWidth(this._tty.columns - 1) - this._requestRedraw() -} - -Gauge.prototype._doRedraw = function () { - if (this._disabled || this._paused) { - return - } - if (!this._fixedFramerate) { - var now = Date.now() - if (this._lastUpdateAt && now - this._lastUpdateAt < this._updateInterval) { - return - } - this._lastUpdateAt = now - } - if (!this._showing && this._onScreen) { - this._onScreen = false - var result = this._gauge.hide() - if (this._hideCursor) { - result += this._gauge.showCursor() - } - return this._writeTo.write(result) - } - if (!this._showing && !this._onScreen) { - return - } - if (this._showing && !this._onScreen) { - this._onScreen = true - this._needsRedraw = true - if (this._hideCursor) { - this._writeTo.write(this._gauge.hideCursor()) - } - } - if (!this._needsRedraw) { - return - } - if (!this._writeTo.write(this._gauge.show(this._status))) { - this._paused = true - this._writeTo.on('drain', callWith(this, function () { - this._paused = false - this._doRedraw() - })) - } -} diff --git a/node_modules/gauge/lib/plumbing.js b/node_modules/gauge/lib/plumbing.js deleted file mode 100644 index c4dc3e074b95e..0000000000000 --- a/node_modules/gauge/lib/plumbing.js +++ /dev/null @@ -1,50 +0,0 @@ -'use strict' -var consoleControl = require('console-control-strings') -var renderTemplate = require('./render-template.js') -var validate = require('aproba') - -var Plumbing = module.exports = function (theme, template, width) { - if (!width) { - width = 80 - } - validate('OAN', [theme, template, width]) - this.showing = false - this.theme = theme - this.width = width - this.template = template -} -Plumbing.prototype = {} - -Plumbing.prototype.setTheme = function (theme) { - validate('O', [theme]) - this.theme = theme -} - -Plumbing.prototype.setTemplate = function (template) { - validate('A', [template]) - this.template = template -} - -Plumbing.prototype.setWidth = function (width) { - validate('N', [width]) - this.width = width -} - -Plumbing.prototype.hide = function () { - return consoleControl.gotoSOL() + consoleControl.eraseLine() -} - -Plumbing.prototype.hideCursor = consoleControl.hideCursor - -Plumbing.prototype.showCursor = consoleControl.showCursor - -Plumbing.prototype.show = function (status) { - var values = Object.create(this.theme) - for (var key in status) { - values[key] = status[key] - } - - return renderTemplate(this.width, this.template, values).trim() + - consoleControl.color('reset') + - consoleControl.eraseLine() + consoleControl.gotoSOL() -} diff --git a/node_modules/gauge/lib/process.js b/node_modules/gauge/lib/process.js deleted file mode 100644 index 05e85694d755b..0000000000000 --- a/node_modules/gauge/lib/process.js +++ /dev/null @@ -1,3 +0,0 @@ -'use strict' -// this exists so we can replace it during testing -module.exports = process diff --git a/node_modules/gauge/lib/progress-bar.js b/node_modules/gauge/lib/progress-bar.js deleted file mode 100644 index 184ff2500aae4..0000000000000 --- a/node_modules/gauge/lib/progress-bar.js +++ /dev/null @@ -1,41 +0,0 @@ -'use strict' -var validate = require('aproba') -var renderTemplate = require('./render-template.js') -var wideTruncate = require('./wide-truncate') -var stringWidth = require('string-width') - -module.exports = function (theme, width, completed) { - validate('ONN', [theme, width, completed]) - if (completed < 0) { - completed = 0 - } - if (completed > 1) { - completed = 1 - } - if (width <= 0) { - return '' - } - var sofar = Math.round(width * completed) - var rest = width - sofar - var template = [ - { type: 'complete', value: repeat(theme.complete, sofar), length: sofar }, - { type: 'remaining', value: repeat(theme.remaining, rest), length: rest }, - ] - return renderTemplate(width, template, theme) -} - -// lodash's way of repeating -function repeat (string, width) { - var result = '' - var n = width - do { - if (n % 2) { - result += string - } - n = Math.floor(n / 2) - /* eslint no-self-assign: 0 */ - string += string - } while (n && stringWidth(result) < width) - - return wideTruncate(result, width) -} diff --git a/node_modules/gauge/lib/render-template.js b/node_modules/gauge/lib/render-template.js deleted file mode 100644 index d1b52c0f48095..0000000000000 --- a/node_modules/gauge/lib/render-template.js +++ /dev/null @@ -1,222 +0,0 @@ -'use strict' -var align = require('wide-align') -var validate = require('aproba') -var wideTruncate = require('./wide-truncate') -var error = require('./error') -var TemplateItem = require('./template-item') - -function renderValueWithValues (values) { - return function (item) { - return renderValue(item, values) - } -} - -var renderTemplate = module.exports = function (width, template, values) { - var items = prepareItems(width, template, values) - var rendered = items.map(renderValueWithValues(values)).join('') - return align.left(wideTruncate(rendered, width), width) -} - -function preType (item) { - var cappedTypeName = item.type[0].toUpperCase() + item.type.slice(1) - return 'pre' + cappedTypeName -} - -function postType (item) { - var cappedTypeName = item.type[0].toUpperCase() + item.type.slice(1) - return 'post' + cappedTypeName -} - -function hasPreOrPost (item, values) { - if (!item.type) { - return - } - return values[preType(item)] || values[postType(item)] -} - -function generatePreAndPost (baseItem, parentValues) { - var item = Object.assign({}, baseItem) - var values = Object.create(parentValues) - var template = [] - var pre = preType(item) - var post = postType(item) - if (values[pre]) { - template.push({ value: values[pre] }) - values[pre] = null - } - item.minLength = null - item.length = null - item.maxLength = null - template.push(item) - values[item.type] = values[item.type] - if (values[post]) { - template.push({ value: values[post] }) - values[post] = null - } - return function ($1, $2, length) { - return renderTemplate(length, template, values) - } -} - -function prepareItems (width, template, values) { - function cloneAndObjectify (item, index, arr) { - var cloned = new TemplateItem(item, width) - var type = cloned.type - if (cloned.value == null) { - if (!(type in values)) { - if (cloned.default == null) { - throw new error.MissingTemplateValue(cloned, values) - } else { - cloned.value = cloned.default - } - } else { - cloned.value = values[type] - } - } - if (cloned.value == null || cloned.value === '') { - return null - } - cloned.index = index - cloned.first = index === 0 - cloned.last = index === arr.length - 1 - if (hasPreOrPost(cloned, values)) { - cloned.value = generatePreAndPost(cloned, values) - } - return cloned - } - - var output = template.map(cloneAndObjectify).filter(function (item) { - return item != null - }) - - var remainingSpace = width - var variableCount = output.length - - function consumeSpace (length) { - if (length > remainingSpace) { - length = remainingSpace - } - remainingSpace -= length - } - - function finishSizing (item, length) { - if (item.finished) { - throw new error.Internal('Tried to finish template item that was already finished') - } - if (length === Infinity) { - throw new error.Internal('Length of template item cannot be infinity') - } - if (length != null) { - item.length = length - } - item.minLength = null - item.maxLength = null - --variableCount - item.finished = true - if (item.length == null) { - item.length = item.getBaseLength() - } - if (item.length == null) { - throw new error.Internal('Finished template items must have a length') - } - consumeSpace(item.getLength()) - } - - output.forEach(function (item) { - if (!item.kerning) { - return - } - var prevPadRight = item.first ? 0 : output[item.index - 1].padRight - if (!item.first && prevPadRight < item.kerning) { - item.padLeft = item.kerning - prevPadRight - } - if (!item.last) { - item.padRight = item.kerning - } - }) - - // Finish any that have a fixed (literal or intuited) length - output.forEach(function (item) { - if (item.getBaseLength() == null) { - return - } - finishSizing(item) - }) - - var resized = 0 - var resizing - var hunkSize - do { - resizing = false - hunkSize = Math.round(remainingSpace / variableCount) - output.forEach(function (item) { - if (item.finished) { - return - } - if (!item.maxLength) { - return - } - if (item.getMaxLength() < hunkSize) { - finishSizing(item, item.maxLength) - resizing = true - } - }) - } while (resizing && resized++ < output.length) - if (resizing) { - throw new error.Internal('Resize loop iterated too many times while determining maxLength') - } - - resized = 0 - do { - resizing = false - hunkSize = Math.round(remainingSpace / variableCount) - output.forEach(function (item) { - if (item.finished) { - return - } - if (!item.minLength) { - return - } - if (item.getMinLength() >= hunkSize) { - finishSizing(item, item.minLength) - resizing = true - } - }) - } while (resizing && resized++ < output.length) - if (resizing) { - throw new error.Internal('Resize loop iterated too many times while determining minLength') - } - - hunkSize = Math.round(remainingSpace / variableCount) - output.forEach(function (item) { - if (item.finished) { - return - } - finishSizing(item, hunkSize) - }) - - return output -} - -function renderFunction (item, values, length) { - validate('OON', arguments) - if (item.type) { - return item.value(values, values[item.type + 'Theme'] || {}, length) - } else { - return item.value(values, {}, length) - } -} - -function renderValue (item, values) { - var length = item.getBaseLength() - var value = typeof item.value === 'function' ? renderFunction(item, values, length) : item.value - if (value == null || value === '') { - return '' - } - var alignWith = align[item.align] || align.left - var leftPadding = item.padLeft ? align.left('', item.padLeft) : '' - var rightPadding = item.padRight ? align.right('', item.padRight) : '' - var truncated = wideTruncate(String(value), length) - var aligned = alignWith(truncated, length) - return leftPadding + aligned + rightPadding -} diff --git a/node_modules/gauge/lib/set-immediate.js b/node_modules/gauge/lib/set-immediate.js deleted file mode 100644 index 6650a485c4993..0000000000000 --- a/node_modules/gauge/lib/set-immediate.js +++ /dev/null @@ -1,7 +0,0 @@ -'use strict' -var process = require('./process') -try { - module.exports = setImmediate -} catch (ex) { - module.exports = process.nextTick -} diff --git a/node_modules/gauge/lib/set-interval.js b/node_modules/gauge/lib/set-interval.js deleted file mode 100644 index 576198793c550..0000000000000 --- a/node_modules/gauge/lib/set-interval.js +++ /dev/null @@ -1,3 +0,0 @@ -'use strict' -// this exists so we can replace it during testing -module.exports = setInterval diff --git a/node_modules/gauge/lib/spin.js b/node_modules/gauge/lib/spin.js deleted file mode 100644 index 34142ee31acc7..0000000000000 --- a/node_modules/gauge/lib/spin.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict' - -module.exports = function spin (spinstr, spun) { - return spinstr[spun % spinstr.length] -} diff --git a/node_modules/gauge/lib/template-item.js b/node_modules/gauge/lib/template-item.js deleted file mode 100644 index e307e9b7421e7..0000000000000 --- a/node_modules/gauge/lib/template-item.js +++ /dev/null @@ -1,87 +0,0 @@ -'use strict' -var stringWidth = require('string-width') - -module.exports = TemplateItem - -function isPercent (num) { - if (typeof num !== 'string') { - return false - } - return num.slice(-1) === '%' -} - -function percent (num) { - return Number(num.slice(0, -1)) / 100 -} - -function TemplateItem (values, outputLength) { - this.overallOutputLength = outputLength - this.finished = false - this.type = null - this.value = null - this.length = null - this.maxLength = null - this.minLength = null - this.kerning = null - this.align = 'left' - this.padLeft = 0 - this.padRight = 0 - this.index = null - this.first = null - this.last = null - if (typeof values === 'string') { - this.value = values - } else { - for (var prop in values) { - this[prop] = values[prop] - } - } - // Realize percents - if (isPercent(this.length)) { - this.length = Math.round(this.overallOutputLength * percent(this.length)) - } - if (isPercent(this.minLength)) { - this.minLength = Math.round(this.overallOutputLength * percent(this.minLength)) - } - if (isPercent(this.maxLength)) { - this.maxLength = Math.round(this.overallOutputLength * percent(this.maxLength)) - } - return this -} - -TemplateItem.prototype = {} - -TemplateItem.prototype.getBaseLength = function () { - var length = this.length - if ( - length == null && - typeof this.value === 'string' && - this.maxLength == null && - this.minLength == null - ) { - length = stringWidth(this.value) - } - return length -} - -TemplateItem.prototype.getLength = function () { - var length = this.getBaseLength() - if (length == null) { - return null - } - return length + this.padLeft + this.padRight -} - -TemplateItem.prototype.getMaxLength = function () { - if (this.maxLength == null) { - return null - } - return this.maxLength + this.padLeft + this.padRight -} - -TemplateItem.prototype.getMinLength = function () { - if (this.minLength == null) { - return null - } - return this.minLength + this.padLeft + this.padRight -} diff --git a/node_modules/gauge/lib/theme-set.js b/node_modules/gauge/lib/theme-set.js deleted file mode 100644 index 643d7dbb1da34..0000000000000 --- a/node_modules/gauge/lib/theme-set.js +++ /dev/null @@ -1,122 +0,0 @@ -'use strict' - -module.exports = function () { - return ThemeSetProto.newThemeSet() -} - -var ThemeSetProto = {} - -ThemeSetProto.baseTheme = require('./base-theme.js') - -ThemeSetProto.newTheme = function (parent, theme) { - if (!theme) { - theme = parent - parent = this.baseTheme - } - return Object.assign({}, parent, theme) -} - -ThemeSetProto.getThemeNames = function () { - return Object.keys(this.themes) -} - -ThemeSetProto.addTheme = function (name, parent, theme) { - this.themes[name] = this.newTheme(parent, theme) -} - -ThemeSetProto.addToAllThemes = function (theme) { - var themes = this.themes - Object.keys(themes).forEach(function (name) { - Object.assign(themes[name], theme) - }) - Object.assign(this.baseTheme, theme) -} - -ThemeSetProto.getTheme = function (name) { - if (!this.themes[name]) { - throw this.newMissingThemeError(name) - } - return this.themes[name] -} - -ThemeSetProto.setDefault = function (opts, name) { - if (name == null) { - name = opts - opts = {} - } - var platform = opts.platform == null ? 'fallback' : opts.platform - var hasUnicode = !!opts.hasUnicode - var hasColor = !!opts.hasColor - if (!this.defaults[platform]) { - this.defaults[platform] = { true: {}, false: {} } - } - this.defaults[platform][hasUnicode][hasColor] = name -} - -ThemeSetProto.getDefault = function (opts) { - if (!opts) { - opts = {} - } - var platformName = opts.platform || process.platform - var platform = this.defaults[platformName] || this.defaults.fallback - var hasUnicode = !!opts.hasUnicode - var hasColor = !!opts.hasColor - if (!platform) { - throw this.newMissingDefaultThemeError(platformName, hasUnicode, hasColor) - } - if (!platform[hasUnicode][hasColor]) { - if (hasUnicode && hasColor && platform[!hasUnicode][hasColor]) { - hasUnicode = false - } else if (hasUnicode && hasColor && platform[hasUnicode][!hasColor]) { - hasColor = false - } else if (hasUnicode && hasColor && platform[!hasUnicode][!hasColor]) { - hasUnicode = false - hasColor = false - } else if (hasUnicode && !hasColor && platform[!hasUnicode][hasColor]) { - hasUnicode = false - } else if (!hasUnicode && hasColor && platform[hasUnicode][!hasColor]) { - hasColor = false - } else if (platform === this.defaults.fallback) { - throw this.newMissingDefaultThemeError(platformName, hasUnicode, hasColor) - } - } - if (platform[hasUnicode][hasColor]) { - return this.getTheme(platform[hasUnicode][hasColor]) - } else { - return this.getDefault(Object.assign({}, opts, { platform: 'fallback' })) - } -} - -ThemeSetProto.newMissingThemeError = function newMissingThemeError (name) { - var err = new Error('Could not find a gauge theme named "' + name + '"') - Error.captureStackTrace.call(err, newMissingThemeError) - err.theme = name - err.code = 'EMISSINGTHEME' - return err -} - -ThemeSetProto.newMissingDefaultThemeError = - function newMissingDefaultThemeError (platformName, hasUnicode, hasColor) { - var err = new Error( - 'Could not find a gauge theme for your platform/unicode/color use combo:\n' + - ' platform = ' + platformName + '\n' + - ' hasUnicode = ' + hasUnicode + '\n' + - ' hasColor = ' + hasColor) - Error.captureStackTrace.call(err, newMissingDefaultThemeError) - err.platform = platformName - err.hasUnicode = hasUnicode - err.hasColor = hasColor - err.code = 'EMISSINGTHEME' - return err - } - -ThemeSetProto.newThemeSet = function () { - var themeset = function (opts) { - return themeset.getDefault(opts) - } - return Object.assign(themeset, ThemeSetProto, { - themes: Object.assign({}, this.themes), - baseTheme: Object.assign({}, this.baseTheme), - defaults: JSON.parse(JSON.stringify(this.defaults || {})), - }) -} diff --git a/node_modules/gauge/lib/themes.js b/node_modules/gauge/lib/themes.js deleted file mode 100644 index d2e62bbccb3d8..0000000000000 --- a/node_modules/gauge/lib/themes.js +++ /dev/null @@ -1,56 +0,0 @@ -'use strict' -var color = require('console-control-strings').color -var ThemeSet = require('./theme-set.js') - -var themes = module.exports = new ThemeSet() - -themes.addTheme('ASCII', { - preProgressbar: '[', - postProgressbar: ']', - progressbarTheme: { - complete: '#', - remaining: '.', - }, - activityIndicatorTheme: '-\\|/', - preSubsection: '>', -}) - -themes.addTheme('colorASCII', themes.getTheme('ASCII'), { - progressbarTheme: { - preComplete: color('bgBrightWhite', 'brightWhite'), - complete: '#', - postComplete: color('reset'), - preRemaining: color('bgBrightBlack', 'brightBlack'), - remaining: '.', - postRemaining: color('reset'), - }, -}) - -themes.addTheme('brailleSpinner', { - preProgressbar: '(', - postProgressbar: ')', - progressbarTheme: { - complete: '#', - remaining: '⠂', - }, - activityIndicatorTheme: '⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏', - preSubsection: '>', -}) - -themes.addTheme('colorBrailleSpinner', themes.getTheme('brailleSpinner'), { - progressbarTheme: { - preComplete: color('bgBrightWhite', 'brightWhite'), - complete: '#', - postComplete: color('reset'), - preRemaining: color('bgBrightBlack', 'brightBlack'), - remaining: '⠂', - postRemaining: color('reset'), - }, -}) - -themes.setDefault({}, 'ASCII') -themes.setDefault({ hasColor: true }, 'colorASCII') -themes.setDefault({ platform: 'darwin', hasUnicode: true }, 'brailleSpinner') -themes.setDefault({ platform: 'darwin', hasUnicode: true, hasColor: true }, 'colorBrailleSpinner') -themes.setDefault({ platform: 'linux', hasUnicode: true }, 'brailleSpinner') -themes.setDefault({ platform: 'linux', hasUnicode: true, hasColor: true }, 'colorBrailleSpinner') diff --git a/node_modules/gauge/lib/wide-truncate.js b/node_modules/gauge/lib/wide-truncate.js deleted file mode 100644 index 5284a699ac3fb..0000000000000 --- a/node_modules/gauge/lib/wide-truncate.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict' -var stringWidth = require('string-width') -var stripAnsi = require('strip-ansi') - -module.exports = wideTruncate - -function wideTruncate (str, target) { - if (stringWidth(str) === 0) { - return str - } - if (target <= 0) { - return '' - } - if (stringWidth(str) <= target) { - return str - } - - // We compute the number of bytes of ansi sequences here and add - // that to our initial truncation to ensure that we don't slice one - // that we want to keep in half. - var noAnsi = stripAnsi(str) - var ansiSize = str.length + noAnsi.length - var truncated = str.slice(0, target + ansiSize) - - // we have to shrink the result to account for our ansi sequence buffer - // (if an ansi sequence was truncated) and double width characters. - while (stringWidth(truncated) > target) { - truncated = truncated.slice(0, -1) - } - return truncated -} diff --git a/node_modules/gauge/package.json b/node_modules/gauge/package.json deleted file mode 100644 index 449d9dd3ed392..0000000000000 --- a/node_modules/gauge/package.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "name": "gauge", - "version": "5.0.1", - "description": "A terminal based horizontal gauge", - "main": "lib", - "scripts": { - "test": "tap", - "lint": "eslint \"**/*.js\"", - "postlint": "template-oss-check", - "lintfix": "npm run lint -- --fix", - "snap": "tap", - "posttest": "npm run lint", - "template-oss-apply": "template-oss-apply --force" - }, - "repository": { - "type": "git", - "url": "https://github.com/npm/gauge.git" - }, - "keywords": [ - "progressbar", - "progress", - "gauge" - ], - "author": "GitHub Inc.", - "license": "ISC", - "bugs": { - "url": "https://github.com/npm/gauge/issues" - }, - "homepage": "https://github.com/npm/gauge", - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^4.0.1", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "devDependencies": { - "@npmcli/eslint-config": "^4.0.0", - "@npmcli/template-oss": "4.14.1", - "readable-stream": "^4.0.0", - "tap": "^16.0.1" - }, - "files": [ - "bin/", - "lib/" - ], - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "tap": { - "branches": 79, - "statements": 89, - "functions": 92, - "lines": 90, - "nyc-arg": [ - "--exclude", - "tap-snapshots/**" - ] - }, - "templateOSS": { - "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.14.1", - "publish": "true" - } -} diff --git a/node_modules/has-unicode/LICENSE b/node_modules/has-unicode/LICENSE deleted file mode 100644 index d42e25e95655b..0000000000000 --- a/node_modules/has-unicode/LICENSE +++ /dev/null @@ -1,14 +0,0 @@ -Copyright (c) 2014, Rebecca Turner - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - diff --git a/node_modules/has-unicode/index.js b/node_modules/has-unicode/index.js deleted file mode 100644 index 9b0fe44540131..0000000000000 --- a/node_modules/has-unicode/index.js +++ /dev/null @@ -1,16 +0,0 @@ -"use strict" -var os = require("os") - -var hasUnicode = module.exports = function () { - // Recent Win32 platforms (>XP) CAN support unicode in the console but - // don't have to, and in non-english locales often use traditional local - // code pages. There's no way, short of windows system calls or execing - // the chcp command line program to figure this out. As such, we default - // this to false and encourage your users to override it via config if - // appropriate. - if (os.type() == "Windows_NT") { return false } - - var isUTF8 = /UTF-?8$/i - var ctype = process.env.LC_ALL || process.env.LC_CTYPE || process.env.LANG - return isUTF8.test(ctype) -} diff --git a/node_modules/has-unicode/package.json b/node_modules/has-unicode/package.json deleted file mode 100644 index ebe9d76d62158..0000000000000 --- a/node_modules/has-unicode/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "has-unicode", - "version": "2.0.1", - "description": "Try to guess if your terminal supports unicode", - "main": "index.js", - "scripts": { - "test": "tap test/*.js" - }, - "repository": { - "type": "git", - "url": "https://github.com/iarna/has-unicode" - }, - "keywords": [ - "unicode", - "terminal" - ], - "files": [ - "index.js" - ], - "author": "Rebecca Turner ", - "license": "ISC", - "bugs": { - "url": "https://github.com/iarna/has-unicode/issues" - }, - "homepage": "https://github.com/iarna/has-unicode", - "devDependencies": { - "require-inject": "^1.3.0", - "tap": "^2.3.1" - } -} diff --git a/node_modules/npmlog/LICENSE.md b/node_modules/npmlog/LICENSE.md deleted file mode 100644 index 5fc208ff122e0..0000000000000 --- a/node_modules/npmlog/LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ - - -ISC License - -Copyright npm, Inc. - -Permission to use, copy, modify, and/or distribute this -software for any purpose with or without fee is hereby -granted, provided that the above copyright notice and this -permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND NPM DISCLAIMS ALL -WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO -EVENT SHALL NPM BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE -USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/node_modules/npmlog/lib/log.js b/node_modules/npmlog/lib/log.js deleted file mode 100644 index 38106ea34ae08..0000000000000 --- a/node_modules/npmlog/lib/log.js +++ /dev/null @@ -1,400 +0,0 @@ -'use strict' -var Progress = require('are-we-there-yet') -var Gauge = require('gauge') -var EE = require('events').EventEmitter -var log = exports = module.exports = new EE() -var util = require('util') - -var setBlocking = require('set-blocking') -var consoleControl = require('console-control-strings') - -setBlocking(true) -var stream = process.stderr -Object.defineProperty(log, 'stream', { - set: function (newStream) { - stream = newStream - if (this.gauge) { - this.gauge.setWriteTo(stream, stream) - } - }, - get: function () { - return stream - }, -}) - -// by default, decide based on tty-ness. -var colorEnabled -log.useColor = function () { - return colorEnabled != null ? colorEnabled : stream.isTTY -} - -log.enableColor = function () { - colorEnabled = true - this.gauge.setTheme({ hasColor: colorEnabled, hasUnicode: unicodeEnabled }) -} -log.disableColor = function () { - colorEnabled = false - this.gauge.setTheme({ hasColor: colorEnabled, hasUnicode: unicodeEnabled }) -} - -// default level -log.level = 'info' - -log.gauge = new Gauge(stream, { - enabled: false, // no progress bars unless asked - theme: { hasColor: log.useColor() }, - template: [ - { type: 'progressbar', length: 20 }, - { type: 'activityIndicator', kerning: 1, length: 1 }, - { type: 'section', default: '' }, - ':', - { type: 'logline', kerning: 1, default: '' }, - ], -}) - -log.tracker = new Progress.TrackerGroup() - -// we track this separately as we may need to temporarily disable the -// display of the status bar for our own loggy purposes. -log.progressEnabled = log.gauge.isEnabled() - -var unicodeEnabled - -log.enableUnicode = function () { - unicodeEnabled = true - this.gauge.setTheme({ hasColor: this.useColor(), hasUnicode: unicodeEnabled }) -} - -log.disableUnicode = function () { - unicodeEnabled = false - this.gauge.setTheme({ hasColor: this.useColor(), hasUnicode: unicodeEnabled }) -} - -log.setGaugeThemeset = function (themes) { - this.gauge.setThemeset(themes) -} - -log.setGaugeTemplate = function (template) { - this.gauge.setTemplate(template) -} - -log.enableProgress = function () { - if (this.progressEnabled || this._paused) { - return - } - - this.progressEnabled = true - this.tracker.on('change', this.showProgress) - this.gauge.enable() -} - -log.disableProgress = function () { - if (!this.progressEnabled) { - return - } - this.progressEnabled = false - this.tracker.removeListener('change', this.showProgress) - this.gauge.disable() -} - -var trackerConstructors = ['newGroup', 'newItem', 'newStream'] - -var mixinLog = function (tracker) { - // mixin the public methods from log into the tracker - // (except: conflicts and one's we handle specially) - Object.keys(log).forEach(function (P) { - if (P[0] === '_') { - return - } - - if (trackerConstructors.filter(function (C) { - return C === P - }).length) { - return - } - - if (tracker[P]) { - return - } - - if (typeof log[P] !== 'function') { - return - } - - var func = log[P] - tracker[P] = function () { - return func.apply(log, arguments) - } - }) - // if the new tracker is a group, make sure any subtrackers get - // mixed in too - if (tracker instanceof Progress.TrackerGroup) { - trackerConstructors.forEach(function (C) { - var func = tracker[C] - tracker[C] = function () { - return mixinLog(func.apply(tracker, arguments)) - } - }) - } - return tracker -} - -// Add tracker constructors to the top level log object -trackerConstructors.forEach(function (C) { - log[C] = function () { - return mixinLog(this.tracker[C].apply(this.tracker, arguments)) - } -}) - -log.clearProgress = function (cb) { - if (!this.progressEnabled) { - return cb && process.nextTick(cb) - } - - this.gauge.hide(cb) -} - -log.showProgress = function (name, completed) { - if (!this.progressEnabled) { - return - } - - var values = {} - if (name) { - values.section = name - } - - var last = log.record[log.record.length - 1] - if (last) { - values.subsection = last.prefix - var disp = log.disp[last.level] || last.level - var logline = this._format(disp, log.style[last.level]) - if (last.prefix) { - logline += ' ' + this._format(last.prefix, this.prefixStyle) - } - - logline += ' ' + last.message.split(/\r?\n/)[0] - values.logline = logline - } - values.completed = completed || this.tracker.completed() - this.gauge.show(values) -}.bind(log) // bind for use in tracker's on-change listener - -// temporarily stop emitting, but don't drop -log.pause = function () { - this._paused = true - if (this.progressEnabled) { - this.gauge.disable() - } -} - -log.resume = function () { - if (!this._paused) { - return - } - - this._paused = false - - var b = this._buffer - this._buffer = [] - b.forEach(function (m) { - this.emitLog(m) - }, this) - if (this.progressEnabled) { - this.gauge.enable() - } -} - -log._buffer = [] - -var id = 0 -log.record = [] -log.maxRecordSize = 10000 -log.log = function (lvl, prefix, message) { - var l = this.levels[lvl] - if (l === undefined) { - return this.emit('error', new Error(util.format( - 'Undefined log level: %j', lvl))) - } - - var a = new Array(arguments.length - 2) - var stack = null - for (var i = 2; i < arguments.length; i++) { - var arg = a[i - 2] = arguments[i] - - // resolve stack traces to a plain string. - if (typeof arg === 'object' && arg instanceof Error && arg.stack) { - Object.defineProperty(arg, 'stack', { - value: stack = arg.stack + '', - enumerable: true, - writable: true, - }) - } - } - if (stack) { - a.unshift(stack + '\n') - } - message = util.format.apply(util, a) - - var m = { - id: id++, - level: lvl, - prefix: String(prefix || ''), - message: message, - messageRaw: a, - } - - this.emit('log', m) - this.emit('log.' + lvl, m) - if (m.prefix) { - this.emit(m.prefix, m) - } - - this.record.push(m) - var mrs = this.maxRecordSize - var n = this.record.length - mrs - if (n > mrs / 10) { - var newSize = Math.floor(mrs * 0.9) - this.record = this.record.slice(-1 * newSize) - } - - this.emitLog(m) -}.bind(log) - -log.emitLog = function (m) { - if (this._paused) { - this._buffer.push(m) - return - } - if (this.progressEnabled) { - this.gauge.pulse(m.prefix) - } - - var l = this.levels[m.level] - if (l === undefined) { - return - } - - if (l < this.levels[this.level]) { - return - } - - if (l > 0 && !isFinite(l)) { - return - } - - // If 'disp' is null or undefined, use the lvl as a default - // Allows: '', 0 as valid disp - var disp = log.disp[m.level] != null ? log.disp[m.level] : m.level - this.clearProgress() - m.message.split(/\r?\n/).forEach(function (line) { - var heading = this.heading - if (heading) { - this.write(heading, this.headingStyle) - this.write(' ') - } - this.write(disp, log.style[m.level]) - var p = m.prefix || '' - if (p) { - this.write(' ') - } - - this.write(p, this.prefixStyle) - this.write(' ' + line + '\n') - }, this) - this.showProgress() -} - -log._format = function (msg, style) { - if (!stream) { - return - } - - var output = '' - if (this.useColor()) { - style = style || {} - var settings = [] - if (style.fg) { - settings.push(style.fg) - } - - if (style.bg) { - settings.push('bg' + style.bg[0].toUpperCase() + style.bg.slice(1)) - } - - if (style.bold) { - settings.push('bold') - } - - if (style.underline) { - settings.push('underline') - } - - if (style.inverse) { - settings.push('inverse') - } - - if (settings.length) { - output += consoleControl.color(settings) - } - - if (style.beep) { - output += consoleControl.beep() - } - } - output += msg - if (this.useColor()) { - output += consoleControl.color('reset') - } - - return output -} - -log.write = function (msg, style) { - if (!stream) { - return - } - - stream.write(this._format(msg, style)) -} - -log.addLevel = function (lvl, n, style, disp) { - // If 'disp' is null or undefined, use the lvl as a default - if (disp == null) { - disp = lvl - } - - this.levels[lvl] = n - this.style[lvl] = style - if (!this[lvl]) { - this[lvl] = function () { - var a = new Array(arguments.length + 1) - a[0] = lvl - for (var i = 0; i < arguments.length; i++) { - a[i + 1] = arguments[i] - } - - return this.log.apply(this, a) - }.bind(this) - } - this.disp[lvl] = disp -} - -log.prefixStyle = { fg: 'magenta' } -log.headingStyle = { fg: 'white', bg: 'black' } - -log.style = {} -log.levels = {} -log.disp = {} -log.addLevel('silly', -Infinity, { inverse: true }, 'sill') -log.addLevel('verbose', 1000, { fg: 'cyan', bg: 'black' }, 'verb') -log.addLevel('info', 2000, { fg: 'green' }) -log.addLevel('timing', 2500, { fg: 'green', bg: 'black' }) -log.addLevel('http', 3000, { fg: 'green', bg: 'black' }) -log.addLevel('notice', 3500, { fg: 'cyan', bg: 'black' }) -log.addLevel('warn', 4000, { fg: 'black', bg: 'yellow' }, 'WARN') -log.addLevel('error', 5000, { fg: 'red', bg: 'black' }, 'ERR!') -log.addLevel('silent', Infinity) - -// allow 'error' prefix -log.on('error', function () {}) diff --git a/node_modules/color-support/LICENSE b/node_modules/proggy/LICENSE similarity index 93% rename from node_modules/color-support/LICENSE rename to node_modules/proggy/LICENSE index 19129e315fe59..83837797202b7 100644 --- a/node_modules/color-support/LICENSE +++ b/node_modules/proggy/LICENSE @@ -1,6 +1,6 @@ The ISC License -Copyright (c) Isaac Z. Schlueter and Contributors +Copyright (c) GitHub, Inc. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above diff --git a/node_modules/proggy/lib/client.js b/node_modules/proggy/lib/client.js new file mode 100644 index 0000000000000..2eafb9c75addc --- /dev/null +++ b/node_modules/proggy/lib/client.js @@ -0,0 +1,114 @@ +const EE = require('events') +const onProgress = Symbol('onProgress') +const bars = Symbol('bars') +const listener = Symbol('listener') +const normData = Symbol('normData') +class Client extends EE { + constructor ({ normalize = false, stopOnDone = false } = {}) { + super() + this.normalize = !!normalize + this.stopOnDone = !!stopOnDone + this[bars] = new Map() + this[listener] = null + } + + get size () { + return this[bars].size + } + + get listening () { + return !!this[listener] + } + + addListener (...args) { + return this.on(...args) + } + + on (ev, ...args) { + if (ev === 'progress' && !this[listener]) { + this.start() + } + return super.on(ev, ...args) + } + + off (ev, ...args) { + return this.removeListener(ev, ...args) + } + + removeListener (ev, ...args) { + const ret = super.removeListener(ev, ...args) + if (ev === 'progress' && this.listeners(ev).length === 0) { + this.stop() + } + return ret + } + + stop () { + if (this[listener]) { + process.removeListener('progress', this[listener]) + this[listener] = null + } + } + + start () { + if (!this[listener]) { + this[listener] = (...args) => this[onProgress](...args) + process.on('progress', this[listener]) + } + } + + [onProgress] (key, data) { + data = this[normData](key, data) + if (!this[bars].has(key)) { + this.emit('bar', key, data) + } + this[bars].set(key, data) + this.emit('progress', key, data) + if (data.done) { + this[bars].delete(key) + this.emit('barDone', key, data) + if (this.size === 0) { + if (this.stopOnDone) { + this.stop() + } + this.emit('done') + } + } + } + + [normData] (key, data) { + const actualValue = data.value + const actualTotal = data.total + let value = actualValue + let total = actualTotal + const done = data.done || value >= total + if (this.normalize) { + const bar = this[bars].get(key) + total = 100 + if (done) { + value = 100 + } else { + // show value as a portion of 100 + const pct = 100 * actualValue / actualTotal + if (bar) { + // don't ever go backwards, and don't stand still + // move at least 1% of the remaining value if it wouldn't move. + value = (pct > bar.value) ? pct + : (100 - bar.value) / 100 + bar.value + } + } + } + // include the key + return { + ...data, + key, + name: data.name || key, + value, + total, + actualValue, + actualTotal, + done, + } + } +} +module.exports = Client diff --git a/node_modules/proggy/lib/index.js b/node_modules/proggy/lib/index.js new file mode 100644 index 0000000000000..834948b4ff860 --- /dev/null +++ b/node_modules/proggy/lib/index.js @@ -0,0 +1,15 @@ +exports.Client = require('./client.js') +exports.Tracker = require('./tracker.js') + +const trackers = new Map() +exports.createTracker = (name, key, total) => { + const tracker = new exports.Tracker(name, key, total) + if (trackers.has(tracker.key)) { + const msg = `proggy: duplicate progress id ${JSON.stringify(tracker.key)}` + throw new Error(msg) + } + trackers.set(tracker.key, tracker) + tracker.on('done', () => trackers.delete(tracker.key)) + return tracker +} +exports.createClient = (options = {}) => new exports.Client(options) diff --git a/node_modules/proggy/lib/tracker.js b/node_modules/proggy/lib/tracker.js new file mode 100644 index 0000000000000..56c78d9434dc7 --- /dev/null +++ b/node_modules/proggy/lib/tracker.js @@ -0,0 +1,68 @@ +// The tracker class is intentionally as naive as possible. it is just +// an ergonomic wrapper around process.emit('progress', ...) +const EE = require('events') +class Tracker extends EE { + constructor (name, key, total) { + super() + if (!name) { + throw new Error('proggy: Tracker needs a name') + } + + if (typeof key === 'number' && !total) { + total = key + key = null + } + + if (!total) { + total = 100 + } + + if (!key) { + key = name + } + + this.done = false + this.name = name + this.key = key + this.value = 0 + this.total = total + } + + finish (metadata = {}) { + this.update(this.total, this.total, metadata) + } + + update (value, total, metadata) { + if (!metadata) { + if (total && typeof total === 'object') { + metadata = total + } else { + metadata = {} + } + } + if (typeof total !== 'number') { + total = this.total + } + + if (this.done) { + const msg = `proggy: updating completed tracker: ${JSON.stringify(this.key)}` + throw new Error(msg) + } + this.value = value + this.total = total + const done = this.value >= this.total + process.emit('progress', this.key, { + ...metadata, + name: this.name, + key: this.key, + value, + total, + done, + }) + if (done) { + this.done = true + this.emit('done') + } + } +} +module.exports = Tracker diff --git a/node_modules/npmlog/package.json b/node_modules/proggy/package.json similarity index 59% rename from node_modules/npmlog/package.json rename to node_modules/proggy/package.json index dbcc772d37ab7..4940fc9d002a6 100644 --- a/node_modules/npmlog/package.json +++ b/node_modules/proggy/package.json @@ -1,52 +1,48 @@ { - "author": "GitHub Inc.", - "name": "npmlog", - "description": "logger for npm", - "version": "7.0.1", - "repository": { - "type": "git", - "url": "https://github.com/npm/npmlog.git" - }, - "main": "lib/log.js", + "name": "proggy", + "version": "2.0.0", "files": [ "bin/", "lib/" ], + "main": "lib/index.js", + "description": "Progress bar updates at a distance", + "repository": { + "type": "git", + "url": "https://github.com/npm/proggy.git" + }, + "author": "GitHub Inc.", + "license": "ISC", "scripts": { "test": "tap", - "npmclilint": "npmcli-lint", - "lint": "eslint \"**/*.js\"", - "lintfix": "npm run lint -- --fix", "posttest": "npm run lint", - "postsnap": "npm run lintfix --", - "postlint": "template-oss-check", "snap": "tap", + "postsnap": "eslint lib test --fix", + "lint": "eslint \"**/*.js\"", + "postlint": "template-oss-check", + "lintfix": "npm run lint -- --fix", "template-oss-apply": "template-oss-apply --force" }, - "dependencies": { - "are-we-there-yet": "^4.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^5.0.0", - "set-blocking": "^2.0.0" - }, "devDependencies": { - "@npmcli/eslint-config": "^4.0.0", - "@npmcli/template-oss": "4.6.1", + "@npmcli/eslint-config": "^3.0.1", + "@npmcli/template-oss": "4.5.1", + "chalk": "^4.1.2", + "cli-progress": "^3.10.0", + "npmlog": "^6.0.1", "tap": "^16.0.1" }, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, "tap": { - "branches": 95, + "coverage-map": "map.js", "nyc-arg": [ "--exclude", "tap-snapshots/**" ] }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.6.1" + "version": "4.5.1" } } diff --git a/node_modules/set-blocking/LICENSE.txt b/node_modules/set-blocking/LICENSE.txt deleted file mode 100644 index 836440bef7cf1..0000000000000 --- a/node_modules/set-blocking/LICENSE.txt +++ /dev/null @@ -1,14 +0,0 @@ -Copyright (c) 2016, Contributors - -Permission to use, copy, modify, and/or distribute this software -for any purpose with or without fee is hereby granted, provided -that the above copyright notice and this permission notice -appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE -LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES -OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/node_modules/set-blocking/index.js b/node_modules/set-blocking/index.js deleted file mode 100644 index 6f78774bb63ee..0000000000000 --- a/node_modules/set-blocking/index.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = function (blocking) { - [process.stdout, process.stderr].forEach(function (stream) { - if (stream._handle && stream.isTTY && typeof stream._handle.setBlocking === 'function') { - stream._handle.setBlocking(blocking) - } - }) -} diff --git a/node_modules/set-blocking/package.json b/node_modules/set-blocking/package.json deleted file mode 100644 index c082db72c6259..0000000000000 --- a/node_modules/set-blocking/package.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "name": "set-blocking", - "version": "2.0.0", - "description": "set blocking stdio and stderr ensuring that terminal output does not truncate", - "main": "index.js", - "scripts": { - "pretest": "standard", - "test": "nyc mocha ./test/*.js", - "coverage": "nyc report --reporter=text-lcov | coveralls", - "version": "standard-version" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/yargs/set-blocking.git" - }, - "keywords": [ - "flush", - "terminal", - "blocking", - "shim", - "stdio", - "stderr" - ], - "author": "Ben Coe ", - "license": "ISC", - "bugs": { - "url": "https://github.com/yargs/set-blocking/issues" - }, - "homepage": "https://github.com/yargs/set-blocking#readme", - "devDependencies": { - "chai": "^3.5.0", - "coveralls": "^2.11.9", - "mocha": "^2.4.5", - "nyc": "^6.4.4", - "standard": "^7.0.1", - "standard-version": "^2.2.1" - }, - "files": [ - "index.js", - "LICENSE.txt" - ] -} \ No newline at end of file diff --git a/node_modules/wide-align/LICENSE b/node_modules/wide-align/LICENSE deleted file mode 100755 index f4be44d881b2d..0000000000000 --- a/node_modules/wide-align/LICENSE +++ /dev/null @@ -1,14 +0,0 @@ -Copyright (c) 2015, Rebecca Turner - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - diff --git a/node_modules/wide-align/align.js b/node_modules/wide-align/align.js deleted file mode 100755 index 4f94ca4cde19b..0000000000000 --- a/node_modules/wide-align/align.js +++ /dev/null @@ -1,65 +0,0 @@ -'use strict' -var stringWidth = require('string-width') - -exports.center = alignCenter -exports.left = alignLeft -exports.right = alignRight - -// lodash's way of generating pad characters. - -function createPadding (width) { - var result = '' - var string = ' ' - var n = width - do { - if (n % 2) { - result += string; - } - n = Math.floor(n / 2); - string += string; - } while (n); - - return result; -} - -function alignLeft (str, width) { - var trimmed = str.trimRight() - if (trimmed.length === 0 && str.length >= width) return str - var padding = '' - var strWidth = stringWidth(trimmed) - - if (strWidth < width) { - padding = createPadding(width - strWidth) - } - - return trimmed + padding -} - -function alignRight (str, width) { - var trimmed = str.trimLeft() - if (trimmed.length === 0 && str.length >= width) return str - var padding = '' - var strWidth = stringWidth(trimmed) - - if (strWidth < width) { - padding = createPadding(width - strWidth) - } - - return padding + trimmed -} - -function alignCenter (str, width) { - var trimmed = str.trim() - if (trimmed.length === 0 && str.length >= width) return str - var padLeft = '' - var padRight = '' - var strWidth = stringWidth(trimmed) - - if (strWidth < width) { - var padLeftBy = parseInt((width - strWidth) / 2, 10) - padLeft = createPadding(padLeftBy) - padRight = createPadding(width - (strWidth + padLeftBy)) - } - - return padLeft + trimmed + padRight -} diff --git a/node_modules/wide-align/package.json b/node_modules/wide-align/package.json deleted file mode 100755 index 2dd27074c7777..0000000000000 --- a/node_modules/wide-align/package.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "wide-align", - "version": "1.1.5", - "description": "A wide-character aware text alignment function for use on the console or with fixed width fonts.", - "main": "align.js", - "scripts": { - "test": "tap --coverage test/*.js" - }, - "keywords": [ - "wide", - "double", - "unicode", - "cjkv", - "pad", - "align" - ], - "author": "Rebecca Turner (http://re-becca.org/)", - "license": "ISC", - "repository": { - "type": "git", - "url": "https://github.com/iarna/wide-align" - }, - "//": "But not version 5 of string-width, as that's ESM only", - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - }, - "devDependencies": { - "tap": "*" - }, - "files": [ - "align.js" - ] -} diff --git a/package-lock.json b/package-lock.json index 578f864c2104e..b3d627b42b0fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -61,11 +61,11 @@ "npm-profile", "npm-registry-fetch", "npm-user-validate", - "npmlog", "p-map", "pacote", "parse-conflict-json", "proc-log", + "proggy", "qrcode-terminal", "read", "semver", @@ -142,11 +142,11 @@ "npm-profile": "^9.0.0", "npm-registry-fetch": "^16.2.0", "npm-user-validate": "^2.0.0", - "npmlog": "^7.0.1", "p-map": "^4.0.0", "pacote": "^17.0.6", "parse-conflict-json": "^3.0.1", "proc-log": "^3.0.0", + "proggy": "^2.0.0", "qrcode-terminal": "^0.12.0", "read": "^3.0.1", "semver": "^7.6.0", @@ -2493,8 +2493,7 @@ "node_modules/aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "inBundle": true + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" }, "node_modules/archy": { "version": "1.0.0", @@ -2506,7 +2505,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-4.0.2.tgz", "integrity": "sha512-ncSWAawFhKMJDTdoAeOV+jyW1VCMj5QIAwULIBV0SSR7B/RLPPEQiknKcg/RIIZlUQrxELpsxMiTUoAQ4sIUyg==", - "inBundle": true, + "dev": true, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } @@ -3480,7 +3479,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "inBundle": true, + "dev": true, "bin": { "color-support": "bin.js" } @@ -3557,7 +3556,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "inBundle": true + "dev": true }, "node_modules/conventional-changelog-angular": { "version": "7.0.0", @@ -5515,7 +5514,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/gauge/-/gauge-5.0.1.tgz", "integrity": "sha512-CmykPMJGuNan/3S4kZOpvvPYSNqSHANiWnh9XcMU2pSjtBfF0XzZ2p1bFAxTbnFxyBuPxQYHhzwaoOmUdqzvxQ==", - "inBundle": true, + "dev": true, "dependencies": { "aproba": "^1.0.3 || ^2.0.0", "color-support": "^1.1.3", @@ -5964,7 +5963,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "inBundle": true + "dev": true }, "node_modules/hasha": { "version": "5.2.2", @@ -10158,7 +10157,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-7.0.1.tgz", "integrity": "sha512-uJ0YFk/mCQpLBt+bxN88AKd+gyqZvZDbtiNxk6Waqcj2aPRyfVx8ITawkyQynxUagInjdYT1+qj4NfA5KJJUxg==", - "inBundle": true, + "dev": true, "dependencies": { "are-we-there-yet": "^4.0.0", "console-control-strings": "^1.1.0", @@ -10965,6 +10964,15 @@ "node": ">=8" } }, + "node_modules/proggy": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/proggy/-/proggy-2.0.0.tgz", + "integrity": "sha512-69agxLtnI8xBs9gUGqEnK26UfiexpHy+KUpBQWabiytQjnn5wFY8rklAi7GRfABIuPNnQ/ik48+LGLkYYJcy4A==", + "inBundle": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/promise-all-reject-late": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz", @@ -12035,7 +12043,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "inBundle": true + "dev": true }, "node_modules/set-function-length": { "version": "1.2.2", @@ -15838,7 +15846,7 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "inBundle": true, + "dev": true, "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" } @@ -16144,10 +16152,10 @@ "npm-package-arg": "^11.0.1", "npm-pick-manifest": "^9.0.0", "npm-registry-fetch": "^16.2.0", - "npmlog": "^7.0.1", "pacote": "^17.0.4", "parse-conflict-json": "^3.0.0", "proc-log": "^3.0.0", + "proggy": "^2.0.0", "promise-all-reject-late": "^1.0.0", "promise-call-limit": "^3.0.1", "read-package-json-fast": "^3.0.2", @@ -16246,7 +16254,6 @@ "@npmcli/run-script": "^7.0.2", "ci-info": "^4.0.0", "npm-package-arg": "^11.0.1", - "npmlog": "^7.0.1", "pacote": "^17.0.4", "proc-log": "^3.0.0", "read": "^3.0.1", diff --git a/package.json b/package.json index d157883a10bbc..90b6695c8973f 100644 --- a/package.json +++ b/package.json @@ -104,11 +104,11 @@ "npm-profile": "^9.0.0", "npm-registry-fetch": "^16.2.0", "npm-user-validate": "^2.0.0", - "npmlog": "^7.0.1", "p-map": "^4.0.0", "pacote": "^17.0.6", "parse-conflict-json": "^3.0.1", "proc-log": "^3.0.0", + "proggy": "^2.0.0", "qrcode-terminal": "^0.12.0", "read": "^3.0.1", "semver": "^7.6.0", @@ -177,11 +177,11 @@ "npm-profile", "npm-registry-fetch", "npm-user-validate", - "npmlog", "p-map", "pacote", "parse-conflict-json", "proc-log", + "proggy", "qrcode-terminal", "read", "semver", diff --git a/smoke-tests/tap-snapshots/test/index.js.test.cjs b/smoke-tests/tap-snapshots/test/index.js.test.cjs index 1addea5f44b10..c90e376dee20e 100644 --- a/smoke-tests/tap-snapshots/test/index.js.test.cjs +++ b/smoke-tests/tap-snapshots/test/index.js.test.cjs @@ -44,16 +44,16 @@ npm {NPM} exports[`test/index.js TAP basic npm ci > should throw mismatch deps in lock file error 1`] = ` npm ERR! code EUSAGE -npm ERR! +npm ERR! npm ERR! \`npm ci\` can only install packages when your package.json and package-lock.json or npm-shrinkwrap.json are in sync. Please update your lock file with \`npm install\` before continuing. -npm ERR! +npm ERR! npm ERR! Invalid: lock file's abbrev@1.0.4 does not satisfy abbrev@1.1.1 -npm ERR! +npm ERR! npm ERR! Clean install a project -npm ERR! +npm ERR! npm ERR! Usage: npm ERR! npm ci -npm ERR! +npm ERR! npm ERR! Options: npm ERR! [--install-strategy ] [--legacy-bundling] npm ERR! [--global-style] [--omit [--omit ...]] @@ -62,9 +62,9 @@ npm ERR! [--strict-peer-deps] [--foreground-scripts] [--ignore-scripts] [--no-au npm ERR! [--no-bin-links] [--no-fund] [--dry-run] npm ERR! [-w|--workspace [-w|--workspace ...]] npm ERR! [-ws|--workspaces] [--include-workspace-root] [--install-links] -npm ERR! +npm ERR! npm ERR! aliases: clean-install, ic, install-clean, isntall-clean -npm ERR! +npm ERR! npm ERR! Run "npm help ci" for more info npm ERR! A complete log of this run can be found in: {NPM}/{TESTDIR}/cache/_logs/{LOG} diff --git a/tap-snapshots/test/lib/commands/audit.js.test.cjs b/tap-snapshots/test/lib/commands/audit.js.test.cjs index 7611191688268..4d2e2445aa2ae 100644 --- a/tap-snapshots/test/lib/commands/audit.js.test.cjs +++ b/tap-snapshots/test/lib/commands/audit.js.test.cjs @@ -45,7 +45,6 @@ exports[`test/lib/commands/audit.js TAP audit signatures ignores optional depend audited 1 package in xxx 1 package has a verified registry signature - ` exports[`test/lib/commands/audit.js TAP audit signatures json output with invalid and missing signatures > must match snapshot 1`] = ` @@ -131,14 +130,12 @@ exports[`test/lib/commands/audit.js TAP audit signatures multiple registries wit audited 2 packages in xxx 2 packages have verified registry signatures - ` exports[`test/lib/commands/audit.js TAP audit signatures omit dev dependencies with missing signature > must match snapshot 1`] = ` audited 1 package in xxx 1 package has a verified registry signature - ` exports[`test/lib/commands/audit.js TAP audit signatures output details about missing signatures > must match snapshot 1`] = ` @@ -157,7 +154,6 @@ audited 1 package in xxx @npmcli/arborist@1.0.14 (https://verdaccio-clone.org/) Someone might have tampered with this package since it was published on the registry! - ` exports[`test/lib/commands/audit.js TAP audit signatures third-party registry with keys and missing signatures errors > must match snapshot 1`] = ` @@ -172,21 +168,18 @@ exports[`test/lib/commands/audit.js TAP audit signatures third-party registry wi audited 1 package in xxx 1 package has a verified registry signature - ` exports[`test/lib/commands/audit.js TAP audit signatures third-party registry with sub-path (trailing slash) > must match snapshot 1`] = ` audited 1 package in xxx 1 package has a verified registry signature - ` exports[`test/lib/commands/audit.js TAP audit signatures third-party registry with sub-path > must match snapshot 1`] = ` audited 1 package in xxx 1 package has a verified registry signature - ` exports[`test/lib/commands/audit.js TAP audit signatures with both invalid and missing signatures > must match snapshot 1`] = ` @@ -201,14 +194,12 @@ async@1.1.1 (https://registry.npmjs.org/) kms-demo@1.0.0 (https://registry.npmjs.org/) Someone might have tampered with this package since it was published on the registry! - ` exports[`test/lib/commands/audit.js TAP audit signatures with bundled and peer deps and no signatures > must match snapshot 1`] = ` audited 1 package in xxx 1 package has a verified registry signature - ` exports[`test/lib/commands/audit.js TAP audit signatures with invalid attestations > must match snapshot 1`] = ` @@ -219,7 +210,6 @@ audited 1 package in xxx sigstore@1.0.0 (https://registry.npmjs.org/) Someone might have tampered with this package since it was published on the registry! - ` exports[`test/lib/commands/audit.js TAP audit signatures with invalid signatures > must match snapshot 1`] = ` @@ -230,7 +220,6 @@ audited 1 package in xxx kms-demo@1.0.0 (https://registry.npmjs.org/) Someone might have tampered with this package since it was published on the registry! - ` exports[`test/lib/commands/audit.js TAP audit signatures with invalid signtaures and color output enabled > must match snapshot 1`] = ` @@ -241,14 +230,12 @@ audited 1 package in xxx kms-demo@1.0.0 (https://registry.npmjs.org/) Someone might have tampered with this package since it was published on the registry! - ` exports[`test/lib/commands/audit.js TAP audit signatures with key fallback to legacy API > must match snapshot 1`] = ` audited 1 package in xxx 1 package has a verified registry signature - ` exports[`test/lib/commands/audit.js TAP audit signatures with keys but missing signature > must match snapshot 1`] = ` @@ -268,7 +255,6 @@ sigstore@1.0.0 (https://registry.npmjs.org/) tuf-js@1.0.0 (https://registry.npmjs.org/) Someone might have tampered with these packages since they were published on the registry! - ` exports[`test/lib/commands/audit.js TAP audit signatures with multiple invalid signatures > must match snapshot 1`] = ` @@ -280,7 +266,6 @@ async@1.1.1 (https://registry.npmjs.org/) kms-demo@1.0.0 (https://registry.npmjs.org/) Someone might have tampered with these packages since they were published on the registry! - ` exports[`test/lib/commands/audit.js TAP audit signatures with multiple missing signatures > must match snapshot 1`] = ` @@ -302,7 +287,6 @@ audited 3 packages in xxx node-fetch@1.6.0 (https://registry.npmjs.org/) Someone might have tampered with this package since it was published on the registry! - ` exports[`test/lib/commands/audit.js TAP audit signatures with valid and missing signatures > must match snapshot 1`] = ` @@ -321,35 +305,30 @@ audited 1 package in xxx 1 package has a verified registry signature 1 package has a verified attestation - ` exports[`test/lib/commands/audit.js TAP audit signatures with valid signatures > must match snapshot 1`] = ` audited 1 package in xxx 1 package has a verified registry signature - ` exports[`test/lib/commands/audit.js TAP audit signatures with valid signatures using alias > must match snapshot 1`] = ` audited 1 package in xxx 1 package has a verified registry signature - ` exports[`test/lib/commands/audit.js TAP audit signatures workspaces verifies registry deps and ignores local workspace deps > must match snapshot 1`] = ` audited 3 packages in xxx 3 packages have verified registry signatures - ` exports[`test/lib/commands/audit.js TAP audit signatures workspaces verifies registry deps when filtering by workspace name > must match snapshot 1`] = ` audited 2 packages in xxx 2 packages have verified registry signatures - ` exports[`test/lib/commands/audit.js TAP fallback audit > must match snapshot 1`] = ` diff --git a/tap-snapshots/test/lib/commands/completion.js.test.cjs b/tap-snapshots/test/lib/commands/completion.js.test.cjs index 089d92440f653..a538e3c068863 100644 --- a/tap-snapshots/test/lib/commands/completion.js.test.cjs +++ b/tap-snapshots/test/lib/commands/completion.js.test.cjs @@ -7,12 +7,10 @@ 'use strict' exports[`test/lib/commands/completion.js TAP completion --no- flags > flags 1`] = ` Array [ - Array [ - String( - --no-version - --no-versions - ), - ], + String( + --no-version + --no-versions + ), ] ` @@ -42,133 +40,131 @@ Array [] exports[`test/lib/commands/completion.js TAP completion double dashes escape from flag completion > full command list 1`] = ` Array [ - Array [ - String( - access - adduser - audit - bugs - cache - ci - completion - config - dedupe - deprecate - diff - dist-tag - docs - doctor - edit - exec - explain - explore - find-dupes - fund - get - help - help-search - hook - init - install - install-ci-test - install-test - link - ll - login - logout - ls - org - outdated - owner - pack - ping - pkg - prefix - profile - prune - publish - query - rebuild - repo - restart - root - run-script - sbom - search - set - shrinkwrap - star - stars - start - stop - team - test - token - uninstall - unpublish - unstar - update - version - view - whoami - author - home - issues - info - show - find - add - unlink - remove - rm - r - un - rb - list - ln - create - i - it - cit - up - c - s - se - tst - t - ddp - v - run - clean-install - clean-install-test - x - why - la - verison - ic - innit - in - ins - inst - insta - instal - isnt - isnta - isntal - isntall - install-clean - isntall-clean - hlep - dist-tags - upgrade - udpate - rum - sit - urn - ogr - add-user - ), - ], + String( + access + adduser + audit + bugs + cache + ci + completion + config + dedupe + deprecate + diff + dist-tag + docs + doctor + edit + exec + explain + explore + find-dupes + fund + get + help + help-search + hook + init + install + install-ci-test + install-test + link + ll + login + logout + ls + org + outdated + owner + pack + ping + pkg + prefix + profile + prune + publish + query + rebuild + repo + restart + root + run-script + sbom + search + set + shrinkwrap + star + stars + start + stop + team + test + token + uninstall + unpublish + unstar + update + version + view + whoami + author + home + issues + info + show + find + add + unlink + remove + rm + r + un + rb + list + ln + create + i + it + cit + up + c + s + se + tst + t + ddp + v + run + clean-install + clean-install-test + x + why + la + verison + ic + innit + in + ins + inst + insta + instal + isnt + isnta + isntal + isntall + install-clean + isntall-clean + hlep + dist-tags + upgrade + udpate + rum + sit + urn + ogr + add-user + ), ] ` @@ -178,52 +174,44 @@ Array [] exports[`test/lib/commands/completion.js TAP completion flags > flags 1`] = ` Array [ - Array [ - String( - --version - --versions - --viewer - --verbose - --v - ), - ], + String( + --version + --versions + --viewer + --verbose + --v + ), ] ` exports[`test/lib/commands/completion.js TAP completion multiple command names > multiple command names 1`] = ` Array [ - Array [ - String( - access - adduser - audit - author - add - add-user - ), - ], + String( + access + adduser + audit + author + add + add-user + ), ] ` exports[`test/lib/commands/completion.js TAP completion single command name > single command name 1`] = ` Array [ - Array [ - "config", - ], + "config", ] ` exports[`test/lib/commands/completion.js TAP completion subcommand completion > subcommands 1`] = ` Array [ - Array [ - String( - get - grant - list - revoke - set - ), - ], + String( + get + grant + list + revoke + set + ), ] ` diff --git a/tap-snapshots/test/lib/commands/config.js.test.cjs b/tap-snapshots/test/lib/commands/config.js.test.cjs index 22eeadbaeaf44..b86820a306029 100644 --- a/tap-snapshots/test/lib/commands/config.js.test.cjs +++ b/tap-snapshots/test/lib/commands/config.js.test.cjs @@ -7,9 +7,7 @@ 'use strict' exports[`test/lib/commands/config.js TAP config list --json > output matches snapshot 1`] = ` { - "prefix": "{LOCALPREFIX}", - "userconfig": "{HOME}/.npmrc", - "cache": "{NPMDIR}/test/lib/commands/tap-testdir-config-config-list---json-sandbox/cache", + "cache": "{CACHE}", "json": true, "projectloaded": "yes", "userloaded": "yes", @@ -31,7 +29,7 @@ exports[`test/lib/commands/config.js TAP config list --json > output matches sna "call": "", "cert": null, "cidr": null, - "color": true, + "color": {COLOR}, "commit-hooks": true, "cpu": null, "depth": null, @@ -62,7 +60,7 @@ exports[`test/lib/commands/config.js TAP config list --json > output matches sna "git": "git", "git-tag-version": true, "global": false, - "globalconfig": "{GLOBALPREFIX}/npmrc", + "globalconfig": "{CWD}/global/etc/npmrc", "global-style": false, "heading": "npm", "https-proxy": null, @@ -75,13 +73,13 @@ exports[`test/lib/commands/config.js TAP config list --json > output matches sna "init-author-name": "", "init-author-url": "", "init-license": "ISC", - "init-module": "{HOME}/.npm-init.js", + "init-module": "{CWD}/home/.npm-init.js", "init-version": "1.0.0", "init.author.email": "", "init.author.name": "", "init.author.url": "", "init.license": "ISC", - "init.module": "{HOME}/.npm-init.js", + "init.module": "{CWD}/home/.npm-init.js", "init.version": "1.0.0", "install-links": false, "install-strategy": "hoisted", @@ -118,9 +116,10 @@ exports[`test/lib/commands/config.js TAP config list --json > output matches sna "prefer-dedupe": false, "prefer-offline": false, "prefer-online": false, + "prefix": "{CWD}/global", "preid": "", "production": null, - "progress": true, + "progress": {PROGRESS}, "provenance": false, "provenance-file": null, "proxy": null, @@ -158,6 +157,7 @@ exports[`test/lib/commands/config.js TAP config list --json > output matches sna "update-notifier": true, "usage": false, "user-agent": "npm/{npm-version} node/{node-version} {platform} {arch} workspaces/{workspaces} {ci}", + "userconfig": "{CWD}/home/.npmrc", "version": false, "versions": false, "viewer": "{VIEWER}", @@ -192,7 +192,7 @@ cafile = null call = "" cert = null cidr = null -color = true +color = {COLOR} commit-hooks = true cpu = null depth = null @@ -224,7 +224,7 @@ git = "git" git-tag-version = true global = false global-style = false -globalconfig = "{GLOBALPREFIX}/npmrc" +globalconfig = "{CWD}/global/etc/npmrc" heading = "npm" https-proxy = null if-present = false @@ -236,13 +236,13 @@ init-author-email = "" init-author-name = "" init-author-url = "" init-license = "ISC" -init-module = "{HOME}/.npm-init.js" +init-module = "{CWD}/home/.npm-init.js" init-version = "1.0.0" init.author.email = "" init.author.name = "" init.author.url = "" init.license = "ISC" -init.module = "{HOME}/.npm-init.js" +init.module = "{CWD}/home/.npm-init.js" init.version = "1.0.0" install-links = false install-strategy = "hoisted" @@ -279,10 +279,10 @@ parseable = false prefer-dedupe = false prefer-offline = false prefer-online = false -; prefix = "{REALGLOBALREFIX}" ; overridden by cli +prefix = "{CWD}/global" preid = "" production = null -progress = true +progress = {PROGRESS} provenance = false provenance-file = null proxy = null @@ -320,7 +320,7 @@ unicode = false update-notifier = true usage = false user-agent = "npm/{npm-version} node/{node-version} {platform} {arch} workspaces/{workspaces} {ci}" -; userconfig = "{HOME}/.npmrc" ; overridden by cli +userconfig = "{CWD}/home/.npmrc" version = false versions = false viewer = "{VIEWER}" @@ -330,98 +330,81 @@ workspaces = null workspaces-update = true yes = null -; "global" config from {GLOBALPREFIX}/npmrc +; "global" config from {CWD}/global/etc/npmrc globalloaded = "yes" -; "user" config from {HOME}/.npmrc +; "user" config from {CWD}/home/.npmrc userloaded = "yes" -; "project" config from {LOCALPREFIX}/.npmrc +; "project" config from {CWD}/prefix/.npmrc projectloaded = "yes" ; "cli" config from command line options -cache = "{NPMDIR}/test/lib/commands/tap-testdir-config-config-list---long-sandbox/cache" -long = true -prefix = "{LOCALPREFIX}" -userconfig = "{HOME}/.npmrc" +cache = "{CACHE}" +long = true ` exports[`test/lib/commands/config.js TAP config list > output matches snapshot 1`] = ` -; "global" config from {GLOBALPREFIX}/npmrc +; "global" config from {CWD}/global/etc/npmrc globalloaded = "yes" -; "user" config from {HOME}/.npmrc +; "user" config from {CWD}/home/.npmrc userloaded = "yes" -; "project" config from {LOCALPREFIX}/.npmrc +; "project" config from {CWD}/prefix/.npmrc projectloaded = "yes" ; "cli" config from command line options -cache = "{NPMDIR}/test/lib/commands/tap-testdir-config-config-list-sandbox/cache" -prefix = "{LOCALPREFIX}" -userconfig = "{HOME}/.npmrc" +cache = "{CACHE}" -; node bin location = {EXECPATH} +; node bin location = {NODE-BIN-LOCATION} ; node version = {NODE-VERSION} -; npm local prefix = {LOCALPREFIX} +; npm local prefix = {CWD}/prefix ; npm version = {NPM-VERSION} -; cwd = {NPMDIR} -; HOME = {HOME} +; cwd = {CWD}/prefix +; HOME = {CWD}/home ; Run \`npm config ls -l\` to show all defaults. ` -exports[`test/lib/commands/config.js TAP config list with publishConfig > output matches snapshot 1`] = ` +exports[`test/lib/commands/config.js TAP config list with publishConfig global > output matches snapshot 1`] = ` ; "cli" config from command line options -cache = "{NPMDIR}/test/lib/commands/tap-testdir-config-config-list-with-publishConfig-sandbox/cache" -prefix = "{LOCALPREFIX}" -userconfig = "{HOME}/.npmrc" +cache = "{CACHE}" +global = true -; node bin location = {EXECPATH} +; node bin location = {NODE-BIN-LOCATION} ; node version = {NODE-VERSION} -; npm local prefix = {LOCALPREFIX} +; npm local prefix = {CWD}/prefix ; npm version = {NPM-VERSION} -; cwd = {NPMDIR} -; HOME = {HOME} +; cwd = {CWD}/prefix +; HOME = {CWD}/home ; Run \`npm config ls -l\` to show all defaults. +` -; "publishConfig" from {LOCALPREFIX}/package.json -; This set of config values will be used at publish-time. - -_authToken = (protected) -registry = "https://some.registry" -; "env" config from environment - -; cache = "{NPMDIR}/test/lib/commands/tap-testdir-config-config-list-with-publishConfig-sandbox/cache" ; overridden by cli -global-prefix = "{LOCALPREFIX}" -globalconfig = "{GLOBALPREFIX}/npmrc" -init-module = "{HOME}/.npm-init.js" -local-prefix = "{LOCALPREFIX}" -npm-version = "{NPM-VERSION}" -; prefix = "{LOCALPREFIX}" ; overridden by cli -user-agent = "npm/{NPM-VERSION} node/{NODE-VERSION} {PLATFORM} {ARCH} workspaces/false" -; userconfig = "{HOME}/.npmrc" ; overridden by cli - +exports[`test/lib/commands/config.js TAP config list with publishConfig local > output matches snapshot 1`] = ` ; "cli" config from command line options -cache = "{NPMDIR}/test/lib/commands/tap-testdir-config-config-list-with-publishConfig-sandbox/cache" -global = true -prefix = "{LOCALPREFIX}" -userconfig = "{HOME}/.npmrc" +cache = "{CACHE}" -; node bin location = {EXECPATH} +; node bin location = {NODE-BIN-LOCATION} ; node version = {NODE-VERSION} -; npm local prefix = {LOCALPREFIX} +; npm local prefix = {CWD}/prefix ; npm version = {NPM-VERSION} -; cwd = {NPMDIR} -; HOME = {HOME} +; cwd = {CWD}/prefix +; HOME = {CWD}/home ; Run \`npm config ls -l\` to show all defaults. + +; "publishConfig" from {CWD}/prefix/package.json +; This set of config values will be used at publish-time. + +_authToken = (protected) +registry = "https://some.registry" ` diff --git a/tap-snapshots/test/lib/commands/dist-tag.js.test.cjs b/tap-snapshots/test/lib/commands/dist-tag.js.test.cjs index ebc823e7e06bb..854f93ff1e5f2 100644 --- a/tap-snapshots/test/lib/commands/dist-tag.js.test.cjs +++ b/tap-snapshots/test/lib/commands/dist-tag.js.test.cjs @@ -20,7 +20,22 @@ latest: 1.0.0 ` exports[`test/lib/commands/dist-tag.js TAP ls on missing package > should log no dist-tag found msg 1`] = ` -dist-tag ls Couldn't get dist-tag data for foo@* +dist-tag ls Couldn't get dist-tag data for Result { +dist-tag ls type: 'range', +dist-tag ls registry: true, +dist-tag ls where: undefined, +dist-tag ls raw: 'foo', +dist-tag ls name: 'foo', +dist-tag ls escapedName: 'foo', +dist-tag ls scope: undefined, +dist-tag ls rawSpec: '*', +dist-tag ls saveSpec: null, +dist-tag ls fetchSpec: '*', +dist-tag ls gitRange: undefined, +dist-tag ls gitCommittish: undefined, +dist-tag ls gitSubdir: undefined, +dist-tag ls hosted: undefined +dist-tag ls } ` exports[`test/lib/commands/dist-tag.js TAP ls on named package > should list tags for the specified package 1`] = ` diff --git a/tap-snapshots/test/lib/commands/doctor.js.test.cjs b/tap-snapshots/test/lib/commands/doctor.js.test.cjs index b14ef6ebfbd90..674237823666d 100644 --- a/tap-snapshots/test/lib/commands/doctor.js.test.cjs +++ b/tap-snapshots/test/lib/commands/doctor.js.test.cjs @@ -9,44 +9,21 @@ exports[`test/lib/commands/doctor.js TAP all clear > logs 1`] = ` Object { "error": Array [], "info": Array [ - Array [ - "Running checkup", - ], - Array [ - "checkPing", - "Pinging registry", - ], - Array [ - "getLatestNpmVersion", - "Getting npm package information", - ], - Array [ - "getLatestNodejsVersion", - "Getting Node.js release information", - ], - Array [ - "getGitPath", - "Finding git in your PATH", - ], - Array [ - "getBinPath", - "Finding npm global bin in your PATH", - ], - Array [ - "verifyCachedFiles", - "Verifying the npm cache", - ], - Array [ - "verifyCachedFiles", - String( - Verification complete. Stats: { - "badContentCount": 0, - "reclaimedCount": 0, - "missingContent": 0, - "verifiedContent": 0 - } - ), - ], + "doctor Running checkup", + "doctor Pinging registry", + "doctor Getting npm package information", + "doctor Getting Node.js release information", + "doctor Finding git in your PATH", + "doctor getBinPath Finding npm global bin in your PATH", + "doctor verifyCachedFiles Verifying the npm cache", + String( + doctor verifyCachedFiles Verification complete. Stats: { + doctor "badContentCount": 0, + doctor "reclaimedCount": 0, + doctor "missingContent": 0, + doctor "verifiedContent": 0 + doctor } + ), ], "warn": Array [], } @@ -88,44 +65,21 @@ exports[`test/lib/commands/doctor.js TAP all clear in color > logs 1`] = ` Object { "error": Array [], "info": Array [ - Array [ - "Running checkup", - ], - Array [ - "checkPing", - "Pinging registry", - ], - Array [ - "getLatestNpmVersion", - "Getting npm package information", - ], - Array [ - "getLatestNodejsVersion", - "Getting Node.js release information", - ], - Array [ - "getGitPath", - "Finding git in your PATH", - ], - Array [ - "getBinPath", - "Finding npm global bin in your PATH", - ], - Array [ - "verifyCachedFiles", - "Verifying the npm cache", - ], - Array [ - "verifyCachedFiles", - String( - Verification complete. Stats: { - "badContentCount": 0, - "reclaimedCount": 0, - "missingContent": 0, - "verifiedContent": 0 - } - ), - ], + "/u001b[35mdoctor/u001b[39m Running checkup", + "/u001b[35mdoctor/u001b[39m Pinging registry", + "/u001b[35mdoctor/u001b[39m Getting npm package information", + "/u001b[35mdoctor/u001b[39m Getting Node.js release information", + "/u001b[35mdoctor/u001b[39m Finding git in your PATH", + "/u001b[35mdoctor/u001b[39m getBinPath Finding npm global bin in your PATH", + "/u001b[35mdoctor/u001b[39m verifyCachedFiles Verifying the npm cache", + String( + /u001b[35mdoctor/u001b[39m verifyCachedFiles Verification complete. Stats: { + /u001b[35mdoctor/u001b[39m "badContentCount": 0, + /u001b[35mdoctor/u001b[39m "reclaimedCount": 0, + /u001b[35mdoctor/u001b[39m "missingContent": 0, + /u001b[35mdoctor/u001b[39m "verifiedContent": 0 + /u001b[35mdoctor/u001b[39m } + ), ], "warn": Array [], } @@ -135,44 +89,21 @@ exports[`test/lib/commands/doctor.js TAP bad proxy > logs 1`] = ` Object { "error": Array [], "info": Array [ - Array [ - "Running checkup", - ], - Array [ - "checkPing", - "Pinging registry", - ], - Array [ - "getLatestNpmVersion", - "Getting npm package information", - ], - Array [ - "getLatestNodejsVersion", - "Getting Node.js release information", - ], - Array [ - "getGitPath", - "Finding git in your PATH", - ], - Array [ - "getBinPath", - "Finding npm global bin in your PATH", - ], - Array [ - "verifyCachedFiles", - "Verifying the npm cache", - ], - Array [ - "verifyCachedFiles", - String( - Verification complete. Stats: { - "badContentCount": 0, - "reclaimedCount": 0, - "missingContent": 0, - "verifiedContent": 0 - } - ), - ], + "doctor Running checkup", + "doctor Pinging registry", + "doctor Getting npm package information", + "doctor Getting Node.js release information", + "doctor Finding git in your PATH", + "doctor getBinPath Finding npm global bin in your PATH", + "doctor verifyCachedFiles Verifying the npm cache", + String( + doctor verifyCachedFiles Verification complete. Stats: { + doctor "badContentCount": 0, + doctor "reclaimedCount": 0, + doctor "missingContent": 0, + doctor "verifiedContent": 0 + doctor } + ), ], "warn": Array [], } @@ -214,54 +145,25 @@ exports[`test/lib/commands/doctor.js TAP cacache badContent > logs 1`] = ` Object { "error": Array [], "info": Array [ - Array [ - "Running checkup", - ], - Array [ - "checkPing", - "Pinging registry", - ], - Array [ - "getLatestNpmVersion", - "Getting npm package information", - ], - Array [ - "getLatestNodejsVersion", - "Getting Node.js release information", - ], - Array [ - "getGitPath", - "Finding git in your PATH", - ], - Array [ - "getBinPath", - "Finding npm global bin in your PATH", - ], - Array [ - "verifyCachedFiles", - "Verifying the npm cache", - ], - Array [ - "verifyCachedFiles", - String( - Verification complete. Stats: { - "badContentCount": 1, - "reclaimedCount": 0, - "missingContent": 0, - "verifiedContent": 2 - } - ), - ], + "doctor Running checkup", + "doctor Pinging registry", + "doctor Getting npm package information", + "doctor Getting Node.js release information", + "doctor Finding git in your PATH", + "doctor getBinPath Finding npm global bin in your PATH", + "doctor verifyCachedFiles Verifying the npm cache", + String( + doctor verifyCachedFiles Verification complete. Stats: { + doctor "badContentCount": 1, + doctor "reclaimedCount": 0, + doctor "missingContent": 0, + doctor "verifiedContent": 2 + doctor } + ), ], "warn": Array [ - Array [ - "verifyCachedFiles", - "Corrupted content removed: 1", - ], - Array [ - "verifyCachedFiles", - "Cache issues have been fixed", - ], + "doctor verifyCachedFiles Corrupted content removed: 1", + "doctor verifyCachedFiles Cache issues have been fixed", ], } ` @@ -270,54 +172,25 @@ exports[`test/lib/commands/doctor.js TAP cacache missingContent > logs 1`] = ` Object { "error": Array [], "info": Array [ - Array [ - "Running checkup", - ], - Array [ - "checkPing", - "Pinging registry", - ], - Array [ - "getLatestNpmVersion", - "Getting npm package information", - ], - Array [ - "getLatestNodejsVersion", - "Getting Node.js release information", - ], - Array [ - "getGitPath", - "Finding git in your PATH", - ], - Array [ - "getBinPath", - "Finding npm global bin in your PATH", - ], - Array [ - "verifyCachedFiles", - "Verifying the npm cache", - ], - Array [ - "verifyCachedFiles", - String( - Verification complete. Stats: { - "badContentCount": 0, - "reclaimedCount": 0, - "missingContent": 1, - "verifiedContent": 2 - } - ), - ], + "doctor Running checkup", + "doctor Pinging registry", + "doctor Getting npm package information", + "doctor Getting Node.js release information", + "doctor Finding git in your PATH", + "doctor getBinPath Finding npm global bin in your PATH", + "doctor verifyCachedFiles Verifying the npm cache", + String( + doctor verifyCachedFiles Verification complete. Stats: { + doctor "badContentCount": 0, + doctor "reclaimedCount": 0, + doctor "missingContent": 1, + doctor "verifiedContent": 2 + doctor } + ), ], "warn": Array [ - Array [ - "verifyCachedFiles", - "Missing content: 1", - ], - Array [ - "verifyCachedFiles", - "Cache issues have been fixed", - ], + "doctor verifyCachedFiles Missing content: 1", + "doctor verifyCachedFiles Cache issues have been fixed", ], } ` @@ -358,54 +231,25 @@ exports[`test/lib/commands/doctor.js TAP cacache reclaimedCount > logs 1`] = ` Object { "error": Array [], "info": Array [ - Array [ - "Running checkup", - ], - Array [ - "checkPing", - "Pinging registry", - ], - Array [ - "getLatestNpmVersion", - "Getting npm package information", - ], - Array [ - "getLatestNodejsVersion", - "Getting Node.js release information", - ], - Array [ - "getGitPath", - "Finding git in your PATH", - ], - Array [ - "getBinPath", - "Finding npm global bin in your PATH", - ], - Array [ - "verifyCachedFiles", - "Verifying the npm cache", - ], - Array [ - "verifyCachedFiles", - String( - Verification complete. Stats: { - "badContentCount": 0, - "reclaimedCount": 1, - "missingContent": 0, - "verifiedContent": 2 - } - ), - ], + "doctor Running checkup", + "doctor Pinging registry", + "doctor Getting npm package information", + "doctor Getting Node.js release information", + "doctor Finding git in your PATH", + "doctor getBinPath Finding npm global bin in your PATH", + "doctor verifyCachedFiles Verifying the npm cache", + String( + doctor verifyCachedFiles Verification complete. Stats: { + doctor "badContentCount": 0, + doctor "reclaimedCount": 1, + doctor "missingContent": 0, + doctor "verifiedContent": 2 + doctor } + ), ], "warn": Array [ - Array [ - "verifyCachedFiles", - "Content garbage-collected: 1 (undefined bytes)", - ], - Array [ - "verifyCachedFiles", - "Cache issues have been fixed", - ], + "doctor verifyCachedFiles Content garbage-collected: 1 (undefined bytes)", + "doctor verifyCachedFiles Cache issues have been fixed", ], } ` @@ -414,24 +258,16 @@ exports[`test/lib/commands/doctor.js TAP discrete checks cache > logs 1`] = ` Object { "error": Array [], "info": Array [ - Array [ - "Running checkup", - ], - Array [ - "verifyCachedFiles", - "Verifying the npm cache", - ], - Array [ - "verifyCachedFiles", - String( - Verification complete. Stats: { - "badContentCount": 0, - "reclaimedCount": 0, - "missingContent": 0, - "verifiedContent": 0 - } - ), - ], + "doctor Running checkup", + "doctor verifyCachedFiles Verifying the npm cache", + String( + doctor verifyCachedFiles Verification complete. Stats: { + doctor "badContentCount": 0, + doctor "reclaimedCount": 0, + doctor "missingContent": 0, + doctor "verifiedContent": 0 + doctor } + ), ], "warn": Array [], } @@ -447,9 +283,7 @@ exports[`test/lib/commands/doctor.js TAP discrete checks git > logs 1`] = ` Object { "error": Array [], "info": Array [ - Array [ - "Running checkup", - ], + "doctor Running checkup", ], "warn": Array [], } @@ -463,17 +297,9 @@ exports[`test/lib/commands/doctor.js TAP discrete checks invalid environment > l Object { "error": Array [], "info": Array [ - Array [ - "Running checkup", - ], - Array [ - "getGitPath", - "Finding git in your PATH", - ], - Array [ - "getBinPath", - "Finding npm global bin in your PATH", - ], + "doctor Running checkup", + "doctor Finding git in your PATH", + "doctor getBinPath Finding npm global bin in your PATH", ], "warn": Array [], } @@ -489,9 +315,7 @@ exports[`test/lib/commands/doctor.js TAP discrete checks permissions - not windo Object { "error": Array [], "info": Array [ - Array [ - "Running checkup", - ], + "doctor Running checkup", ], "warn": Array [], } @@ -510,9 +334,7 @@ exports[`test/lib/commands/doctor.js TAP discrete checks permissions - windows > Object { "error": Array [], "info": Array [ - Array [ - "Running checkup", - ], + "doctor Running checkup", ], "warn": Array [], } @@ -526,13 +348,8 @@ exports[`test/lib/commands/doctor.js TAP discrete checks ping > logs 1`] = ` Object { "error": Array [], "info": Array [ - Array [ - "Running checkup", - ], - Array [ - "checkPing", - "Pinging registry", - ], + "doctor Running checkup", + "doctor Pinging registry", ], "warn": Array [], } @@ -547,13 +364,8 @@ exports[`test/lib/commands/doctor.js TAP discrete checks registry > logs 1`] = ` Object { "error": Array [], "info": Array [ - Array [ - "Running checkup", - ], - Array [ - "checkPing", - "Pinging registry", - ], + "doctor Running checkup", + "doctor Pinging registry", ], "warn": Array [], } @@ -569,17 +381,9 @@ exports[`test/lib/commands/doctor.js TAP discrete checks versions > logs 1`] = ` Object { "error": Array [], "info": Array [ - Array [ - "Running checkup", - ], - Array [ - "getLatestNpmVersion", - "Getting npm package information", - ], - Array [ - "getLatestNodejsVersion", - "Getting Node.js release information", - ], + "doctor Running checkup", + "doctor Getting npm package information", + "doctor Getting Node.js release information", ], "warn": Array [], } @@ -595,66 +399,28 @@ exports[`test/lib/commands/doctor.js TAP error reading directory > logs 1`] = ` Object { "error": Array [], "info": Array [ - Array [ - "Running checkup", - ], - Array [ - "checkPing", - "Pinging registry", - ], - Array [ - "getLatestNpmVersion", - "Getting npm package information", - ], - Array [ - "getLatestNodejsVersion", - "Getting Node.js release information", - ], - Array [ - "getGitPath", - "Finding git in your PATH", - ], - Array [ - "getBinPath", - "Finding npm global bin in your PATH", - ], - Array [ - "verifyCachedFiles", - "Verifying the npm cache", - ], - Array [ - "verifyCachedFiles", - String( - Verification complete. Stats: { - "badContentCount": 0, - "reclaimedCount": 0, - "missingContent": 0, - "verifiedContent": 0 - } - ), - ], + "doctor Running checkup", + "doctor Pinging registry", + "doctor Getting npm package information", + "doctor Getting Node.js release information", + "doctor Finding git in your PATH", + "doctor getBinPath Finding npm global bin in your PATH", + "doctor verifyCachedFiles Verifying the npm cache", + String( + doctor verifyCachedFiles Verification complete. Stats: { + doctor "badContentCount": 0, + doctor "reclaimedCount": 0, + doctor "missingContent": 0, + doctor "verifiedContent": 0 + doctor } + ), ], "warn": Array [ - Array [ - "checkFilesPermission", - "error reading directory {CWD}/cache", - ], - Array [ - "checkFilesPermission", - "error reading directory {CWD}/prefix/node_modules", - ], - Array [ - "checkFilesPermission", - "error reading directory {CWD}/global/node_modules", - ], - Array [ - "checkFilesPermission", - "error reading directory {CWD}/prefix/node_modules/.bin", - ], - Array [ - "checkFilesPermission", - "error reading directory {CWD}/global/bin", - ], + "doctor checkFilesPermission error reading directory {CWD}/cache", + "doctor checkFilesPermission error reading directory {CWD}/prefix/node_modules", + "doctor checkFilesPermission error reading directory {CWD}/global/node_modules", + "doctor checkFilesPermission error reading directory {CWD}/prefix/node_modules/.bin", + "doctor checkFilesPermission error reading directory {CWD}/global/bin", ], } ` @@ -695,50 +461,24 @@ exports[`test/lib/commands/doctor.js TAP incorrect owner > logs 1`] = ` Object { "error": Array [], "info": Array [ - Array [ - "Running checkup", - ], - Array [ - "checkPing", - "Pinging registry", - ], - Array [ - "getLatestNpmVersion", - "Getting npm package information", - ], - Array [ - "getLatestNodejsVersion", - "Getting Node.js release information", - ], - Array [ - "getGitPath", - "Finding git in your PATH", - ], - Array [ - "getBinPath", - "Finding npm global bin in your PATH", - ], - Array [ - "verifyCachedFiles", - "Verifying the npm cache", - ], - Array [ - "verifyCachedFiles", - String( - Verification complete. Stats: { - "badContentCount": 0, - "reclaimedCount": 0, - "missingContent": 0, - "verifiedContent": 0 - } - ), - ], + "doctor Running checkup", + "doctor Pinging registry", + "doctor Getting npm package information", + "doctor Getting Node.js release information", + "doctor Finding git in your PATH", + "doctor getBinPath Finding npm global bin in your PATH", + "doctor verifyCachedFiles Verifying the npm cache", + String( + doctor verifyCachedFiles Verification complete. Stats: { + doctor "badContentCount": 0, + doctor "reclaimedCount": 0, + doctor "missingContent": 0, + doctor "verifiedContent": 0 + doctor } + ), ], "warn": Array [ - Array [ - "checkFilesPermission", - "should be owner of {CWD}/cache/_cacache", - ], + "doctor checkFilesPermission should be owner of {CWD}/cache/_cacache", ], } ` @@ -762,66 +502,28 @@ Verify cache contents ok verified 0 tarballs exports[`test/lib/commands/doctor.js TAP incorrect permissions > logs 1`] = ` Object { "error": Array [ - Array [ - "checkFilesPermission", - "Missing permissions on {CWD}/cache (expect: readable)", - ], - Array [ - "checkFilesPermission", - "Missing permissions on {CWD}/prefix/node_modules (expect: readable, writable)", - ], - Array [ - "checkFilesPermission", - "Missing permissions on {CWD}/global/node_modules (expect: readable)", - ], - Array [ - "checkFilesPermission", - "Missing permissions on {CWD}/prefix/node_modules/.bin (expect: readable, writable, executable)", - ], - Array [ - "checkFilesPermission", - "Missing permissions on {CWD}/global/bin (expect: executable)", - ], + "doctor checkFilesPermission Missing permissions on {CWD}/cache (expect: readable)", + "doctor checkFilesPermission Missing permissions on {CWD}/prefix/node_modules (expect: readable, writable)", + "doctor checkFilesPermission Missing permissions on {CWD}/global/node_modules (expect: readable)", + "doctor checkFilesPermission Missing permissions on {CWD}/prefix/node_modules/.bin (expect: readable, writable, executable)", + "doctor checkFilesPermission Missing permissions on {CWD}/global/bin (expect: executable)", ], "info": Array [ - Array [ - "Running checkup", - ], - Array [ - "checkPing", - "Pinging registry", - ], - Array [ - "getLatestNpmVersion", - "Getting npm package information", - ], - Array [ - "getLatestNodejsVersion", - "Getting Node.js release information", - ], - Array [ - "getGitPath", - "Finding git in your PATH", - ], - Array [ - "getBinPath", - "Finding npm global bin in your PATH", - ], - Array [ - "verifyCachedFiles", - "Verifying the npm cache", - ], - Array [ - "verifyCachedFiles", - String( - Verification complete. Stats: { - "badContentCount": 0, - "reclaimedCount": 0, - "missingContent": 0, - "verifiedContent": 0 - } - ), - ], + "doctor Running checkup", + "doctor Pinging registry", + "doctor Getting npm package information", + "doctor Getting Node.js release information", + "doctor Finding git in your PATH", + "doctor getBinPath Finding npm global bin in your PATH", + "doctor verifyCachedFiles Verifying the npm cache", + String( + doctor verifyCachedFiles Verification complete. Stats: { + doctor "badContentCount": 0, + doctor "reclaimedCount": 0, + doctor "missingContent": 0, + doctor "verifiedContent": 0 + doctor } + ), ], "warn": Array [], } @@ -831,49 +533,31 @@ exports[`test/lib/commands/doctor.js TAP missing git > logs 1`] = ` Object { "error": Array [], "info": Array [ - Array [ - "Running checkup", - ], - Array [ - "checkPing", - "Pinging registry", - ], - Array [ - "getLatestNpmVersion", - "Getting npm package information", - ], - Array [ - "getLatestNodejsVersion", - "Getting Node.js release information", - ], - Array [ - "getGitPath", - "Finding git in your PATH", - ], - Array [ - "getBinPath", - "Finding npm global bin in your PATH", - ], - Array [ - "verifyCachedFiles", - "Verifying the npm cache", - ], - Array [ - "verifyCachedFiles", - String( - Verification complete. Stats: { - "badContentCount": 0, - "reclaimedCount": 0, - "missingContent": 0, - "verifiedContent": 0 - } - ), - ], + "doctor Running checkup", + "doctor Pinging registry", + "doctor Getting npm package information", + "doctor Getting Node.js release information", + "doctor Finding git in your PATH", + "doctor getBinPath Finding npm global bin in your PATH", + "doctor verifyCachedFiles Verifying the npm cache", + String( + doctor verifyCachedFiles Verification complete. Stats: { + doctor "badContentCount": 0, + doctor "reclaimedCount": 0, + doctor "missingContent": 0, + doctor "verifiedContent": 0 + doctor } + ), ], "warn": Array [ - Array [ - Error: test error, - ], + String( + doctor getGitPath Error: test error + doctor at which ({CWD}/{TESTDIR}/doctor.js:313:15) + doctor at Doctor.getGitPath ({CWD}/lib/commands/doctor.js:300:18) + doctor at Doctor.exec ({CWD}/lib/commands/doctor.js:130:40) + doctor at processTicksAndRejections (node:internal/process/task_queues:95:5) + doctor at MockNpm.exec ({CWD}/test/fixtures/mock-npm.js:80:26) + ), ], } ` @@ -898,54 +582,25 @@ exports[`test/lib/commands/doctor.js TAP missing global directories > logs 1`] = Object { "error": Array [], "info": Array [ - Array [ - "Running checkup", - ], - Array [ - "checkPing", - "Pinging registry", - ], - Array [ - "getLatestNpmVersion", - "Getting npm package information", - ], - Array [ - "getLatestNodejsVersion", - "Getting Node.js release information", - ], - Array [ - "getGitPath", - "Finding git in your PATH", - ], - Array [ - "getBinPath", - "Finding npm global bin in your PATH", - ], - Array [ - "verifyCachedFiles", - "Verifying the npm cache", - ], - Array [ - "verifyCachedFiles", - String( - Verification complete. Stats: { - "badContentCount": 0, - "reclaimedCount": 0, - "missingContent": 0, - "verifiedContent": 0 - } - ), - ], + "doctor Running checkup", + "doctor Pinging registry", + "doctor Getting npm package information", + "doctor Getting Node.js release information", + "doctor Finding git in your PATH", + "doctor getBinPath Finding npm global bin in your PATH", + "doctor verifyCachedFiles Verifying the npm cache", + String( + doctor verifyCachedFiles Verification complete. Stats: { + doctor "badContentCount": 0, + doctor "reclaimedCount": 0, + doctor "missingContent": 0, + doctor "verifiedContent": 0 + doctor } + ), ], "warn": Array [ - Array [ - "checkFilesPermission", - "error getting info for {CWD}/global/node_modules", - ], - Array [ - "checkFilesPermission", - "error getting info for {CWD}/global/bin", - ], + "doctor checkFilesPermission error getting info for {CWD}/global/node_modules", + "doctor checkFilesPermission error getting info for {CWD}/global/bin", ], } ` @@ -970,44 +625,21 @@ exports[`test/lib/commands/doctor.js TAP missing local node_modules > logs 1`] = Object { "error": Array [], "info": Array [ - Array [ - "Running checkup", - ], - Array [ - "checkPing", - "Pinging registry", - ], - Array [ - "getLatestNpmVersion", - "Getting npm package information", - ], - Array [ - "getLatestNodejsVersion", - "Getting Node.js release information", - ], - Array [ - "getGitPath", - "Finding git in your PATH", - ], - Array [ - "getBinPath", - "Finding npm global bin in your PATH", - ], - Array [ - "verifyCachedFiles", - "Verifying the npm cache", - ], - Array [ - "verifyCachedFiles", - String( - Verification complete. Stats: { - "badContentCount": 0, - "reclaimedCount": 0, - "missingContent": 0, - "verifiedContent": 0 - } - ), - ], + "doctor Running checkup", + "doctor Pinging registry", + "doctor Getting npm package information", + "doctor Getting Node.js release information", + "doctor Finding git in your PATH", + "doctor getBinPath Finding npm global bin in your PATH", + "doctor verifyCachedFiles Verifying the npm cache", + String( + doctor verifyCachedFiles Verification complete. Stats: { + doctor "badContentCount": 0, + doctor "reclaimedCount": 0, + doctor "missingContent": 0, + doctor "verifiedContent": 0 + doctor } + ), ], "warn": Array [], } @@ -1033,44 +665,21 @@ exports[`test/lib/commands/doctor.js TAP node out of date - current > logs 1`] = Object { "error": Array [], "info": Array [ - Array [ - "Running checkup", - ], - Array [ - "checkPing", - "Pinging registry", - ], - Array [ - "getLatestNpmVersion", - "Getting npm package information", - ], - Array [ - "getLatestNodejsVersion", - "Getting Node.js release information", - ], - Array [ - "getGitPath", - "Finding git in your PATH", - ], - Array [ - "getBinPath", - "Finding npm global bin in your PATH", - ], - Array [ - "verifyCachedFiles", - "Verifying the npm cache", - ], - Array [ - "verifyCachedFiles", - String( - Verification complete. Stats: { - "badContentCount": 0, - "reclaimedCount": 0, - "missingContent": 0, - "verifiedContent": 0 - } - ), - ], + "doctor Running checkup", + "doctor Pinging registry", + "doctor Getting npm package information", + "doctor Getting Node.js release information", + "doctor Finding git in your PATH", + "doctor getBinPath Finding npm global bin in your PATH", + "doctor verifyCachedFiles Verifying the npm cache", + String( + doctor verifyCachedFiles Verification complete. Stats: { + doctor "badContentCount": 0, + doctor "reclaimedCount": 0, + doctor "missingContent": 0, + doctor "verifiedContent": 0 + doctor } + ), ], "warn": Array [], } @@ -1096,44 +705,21 @@ exports[`test/lib/commands/doctor.js TAP node out of date - lts > logs 1`] = ` Object { "error": Array [], "info": Array [ - Array [ - "Running checkup", - ], - Array [ - "checkPing", - "Pinging registry", - ], - Array [ - "getLatestNpmVersion", - "Getting npm package information", - ], - Array [ - "getLatestNodejsVersion", - "Getting Node.js release information", - ], - Array [ - "getGitPath", - "Finding git in your PATH", - ], - Array [ - "getBinPath", - "Finding npm global bin in your PATH", - ], - Array [ - "verifyCachedFiles", - "Verifying the npm cache", - ], - Array [ - "verifyCachedFiles", - String( - Verification complete. Stats: { - "badContentCount": 0, - "reclaimedCount": 0, - "missingContent": 0, - "verifiedContent": 0 - } - ), - ], + "doctor Running checkup", + "doctor Pinging registry", + "doctor Getting npm package information", + "doctor Getting Node.js release information", + "doctor Finding git in your PATH", + "doctor getBinPath Finding npm global bin in your PATH", + "doctor verifyCachedFiles Verifying the npm cache", + String( + doctor verifyCachedFiles Verification complete. Stats: { + doctor "badContentCount": 0, + doctor "reclaimedCount": 0, + doctor "missingContent": 0, + doctor "verifiedContent": 0 + doctor } + ), ], "warn": Array [], } @@ -1159,44 +745,21 @@ exports[`test/lib/commands/doctor.js TAP non-default registry > logs 1`] = ` Object { "error": Array [], "info": Array [ - Array [ - "Running checkup", - ], - Array [ - "checkPing", - "Pinging registry", - ], - Array [ - "getLatestNpmVersion", - "Getting npm package information", - ], - Array [ - "getLatestNodejsVersion", - "Getting Node.js release information", - ], - Array [ - "getGitPath", - "Finding git in your PATH", - ], - Array [ - "getBinPath", - "Finding npm global bin in your PATH", - ], - Array [ - "verifyCachedFiles", - "Verifying the npm cache", - ], - Array [ - "verifyCachedFiles", - String( - Verification complete. Stats: { - "badContentCount": 0, - "reclaimedCount": 0, - "missingContent": 0, - "verifiedContent": 0 - } - ), - ], + "doctor Running checkup", + "doctor Pinging registry", + "doctor Getting npm package information", + "doctor Getting Node.js release information", + "doctor Finding git in your PATH", + "doctor getBinPath Finding npm global bin in your PATH", + "doctor verifyCachedFiles Verifying the npm cache", + String( + doctor verifyCachedFiles Verification complete. Stats: { + doctor "badContentCount": 0, + doctor "reclaimedCount": 0, + doctor "missingContent": 0, + doctor "verifiedContent": 0 + doctor } + ), ], "warn": Array [], } @@ -1222,44 +785,21 @@ exports[`test/lib/commands/doctor.js TAP npm out of date > logs 1`] = ` Object { "error": Array [], "info": Array [ - Array [ - "Running checkup", - ], - Array [ - "checkPing", - "Pinging registry", - ], - Array [ - "getLatestNpmVersion", - "Getting npm package information", - ], - Array [ - "getLatestNodejsVersion", - "Getting Node.js release information", - ], - Array [ - "getGitPath", - "Finding git in your PATH", - ], - Array [ - "getBinPath", - "Finding npm global bin in your PATH", - ], - Array [ - "verifyCachedFiles", - "Verifying the npm cache", - ], - Array [ - "verifyCachedFiles", - String( - Verification complete. Stats: { - "badContentCount": 0, - "reclaimedCount": 0, - "missingContent": 0, - "verifiedContent": 0 - } - ), - ], + "doctor Running checkup", + "doctor Pinging registry", + "doctor Getting npm package information", + "doctor Getting Node.js release information", + "doctor Finding git in your PATH", + "doctor getBinPath Finding npm global bin in your PATH", + "doctor verifyCachedFiles Verifying the npm cache", + String( + doctor verifyCachedFiles Verification complete. Stats: { + doctor "badContentCount": 0, + doctor "reclaimedCount": 0, + doctor "missingContent": 0, + doctor "verifiedContent": 0 + doctor } + ), ], "warn": Array [], } @@ -1285,44 +825,21 @@ exports[`test/lib/commands/doctor.js TAP ping 404 > logs 1`] = ` Object { "error": Array [], "info": Array [ - Array [ - "Running checkup", - ], - Array [ - "checkPing", - "Pinging registry", - ], - Array [ - "getLatestNpmVersion", - "Getting npm package information", - ], - Array [ - "getLatestNodejsVersion", - "Getting Node.js release information", - ], - Array [ - "getGitPath", - "Finding git in your PATH", - ], - Array [ - "getBinPath", - "Finding npm global bin in your PATH", - ], - Array [ - "verifyCachedFiles", - "Verifying the npm cache", - ], - Array [ - "verifyCachedFiles", - String( - Verification complete. Stats: { - "badContentCount": 0, - "reclaimedCount": 0, - "missingContent": 0, - "verifiedContent": 0 - } - ), - ], + "doctor Running checkup", + "doctor Pinging registry", + "doctor Getting npm package information", + "doctor Getting Node.js release information", + "doctor Finding git in your PATH", + "doctor getBinPath Finding npm global bin in your PATH", + "doctor verifyCachedFiles Verifying the npm cache", + String( + doctor verifyCachedFiles Verification complete. Stats: { + doctor "badContentCount": 0, + doctor "reclaimedCount": 0, + doctor "missingContent": 0, + doctor "verifiedContent": 0 + doctor } + ), ], "warn": Array [], } @@ -1348,44 +865,21 @@ exports[`test/lib/commands/doctor.js TAP ping 404 in color > logs 1`] = ` Object { "error": Array [], "info": Array [ - Array [ - "Running checkup", - ], - Array [ - "checkPing", - "Pinging registry", - ], - Array [ - "getLatestNpmVersion", - "Getting npm package information", - ], - Array [ - "getLatestNodejsVersion", - "Getting Node.js release information", - ], - Array [ - "getGitPath", - "Finding git in your PATH", - ], - Array [ - "getBinPath", - "Finding npm global bin in your PATH", - ], - Array [ - "verifyCachedFiles", - "Verifying the npm cache", - ], - Array [ - "verifyCachedFiles", - String( - Verification complete. Stats: { - "badContentCount": 0, - "reclaimedCount": 0, - "missingContent": 0, - "verifiedContent": 0 - } - ), - ], + "/u001b[35mdoctor/u001b[39m Running checkup", + "/u001b[35mdoctor/u001b[39m Pinging registry", + "/u001b[35mdoctor/u001b[39m Getting npm package information", + "/u001b[35mdoctor/u001b[39m Getting Node.js release information", + "/u001b[35mdoctor/u001b[39m Finding git in your PATH", + "/u001b[35mdoctor/u001b[39m getBinPath Finding npm global bin in your PATH", + "/u001b[35mdoctor/u001b[39m verifyCachedFiles Verifying the npm cache", + String( + /u001b[35mdoctor/u001b[39m verifyCachedFiles Verification complete. Stats: { + /u001b[35mdoctor/u001b[39m "badContentCount": 0, + /u001b[35mdoctor/u001b[39m "reclaimedCount": 0, + /u001b[35mdoctor/u001b[39m "missingContent": 0, + /u001b[35mdoctor/u001b[39m "verifiedContent": 0 + /u001b[35mdoctor/u001b[39m } + ), ], "warn": Array [], } @@ -1411,44 +905,21 @@ exports[`test/lib/commands/doctor.js TAP ping exception with code > logs 1`] = ` Object { "error": Array [], "info": Array [ - Array [ - "Running checkup", - ], - Array [ - "checkPing", - "Pinging registry", - ], - Array [ - "getLatestNpmVersion", - "Getting npm package information", - ], - Array [ - "getLatestNodejsVersion", - "Getting Node.js release information", - ], - Array [ - "getGitPath", - "Finding git in your PATH", - ], - Array [ - "getBinPath", - "Finding npm global bin in your PATH", - ], - Array [ - "verifyCachedFiles", - "Verifying the npm cache", - ], - Array [ - "verifyCachedFiles", - String( - Verification complete. Stats: { - "badContentCount": 0, - "reclaimedCount": 0, - "missingContent": 0, - "verifiedContent": 0 - } - ), - ], + "doctor Running checkup", + "doctor Pinging registry", + "doctor Getting npm package information", + "doctor Getting Node.js release information", + "doctor Finding git in your PATH", + "doctor getBinPath Finding npm global bin in your PATH", + "doctor verifyCachedFiles Verifying the npm cache", + String( + doctor verifyCachedFiles Verification complete. Stats: { + doctor "badContentCount": 0, + doctor "reclaimedCount": 0, + doctor "missingContent": 0, + doctor "verifiedContent": 0 + doctor } + ), ], "warn": Array [], } @@ -1474,44 +945,21 @@ exports[`test/lib/commands/doctor.js TAP ping exception without code > logs 1`] Object { "error": Array [], "info": Array [ - Array [ - "Running checkup", - ], - Array [ - "checkPing", - "Pinging registry", - ], - Array [ - "getLatestNpmVersion", - "Getting npm package information", - ], - Array [ - "getLatestNodejsVersion", - "Getting Node.js release information", - ], - Array [ - "getGitPath", - "Finding git in your PATH", - ], - Array [ - "getBinPath", - "Finding npm global bin in your PATH", - ], - Array [ - "verifyCachedFiles", - "Verifying the npm cache", - ], - Array [ - "verifyCachedFiles", - String( - Verification complete. Stats: { - "badContentCount": 0, - "reclaimedCount": 0, - "missingContent": 0, - "verifiedContent": 0 - } - ), - ], + "doctor Running checkup", + "doctor Pinging registry", + "doctor Getting npm package information", + "doctor Getting Node.js release information", + "doctor Finding git in your PATH", + "doctor getBinPath Finding npm global bin in your PATH", + "doctor verifyCachedFiles Verifying the npm cache", + String( + doctor verifyCachedFiles Verification complete. Stats: { + doctor "badContentCount": 0, + doctor "reclaimedCount": 0, + doctor "missingContent": 0, + doctor "verifiedContent": 0 + doctor } + ), ], "warn": Array [], } @@ -1536,15 +984,7 @@ Verify cache contents ok verified 0 tarballs exports[`test/lib/commands/doctor.js TAP silent errors > logs 1`] = ` Object { "error": Array [], - "info": Array [ - Array [ - "Running checkup", - ], - Array [ - "checkPing", - "Pinging registry", - ], - ], + "info": Array [], "warn": Array [], } ` @@ -1556,46 +996,7 @@ exports[`test/lib/commands/doctor.js TAP silent errors > output 1`] = ` exports[`test/lib/commands/doctor.js TAP silent success > logs 1`] = ` Object { "error": Array [], - "info": Array [ - Array [ - "Running checkup", - ], - Array [ - "checkPing", - "Pinging registry", - ], - Array [ - "getLatestNpmVersion", - "Getting npm package information", - ], - Array [ - "getLatestNodejsVersion", - "Getting Node.js release information", - ], - Array [ - "getGitPath", - "Finding git in your PATH", - ], - Array [ - "getBinPath", - "Finding npm global bin in your PATH", - ], - Array [ - "verifyCachedFiles", - "Verifying the npm cache", - ], - Array [ - "verifyCachedFiles", - String( - Verification complete. Stats: { - "badContentCount": 0, - "reclaimedCount": 0, - "missingContent": 0, - "verifiedContent": 0 - } - ), - ], - ], + "info": Array [], "warn": Array [], } ` @@ -1608,29 +1009,12 @@ exports[`test/lib/commands/doctor.js TAP windows skips permissions checks > logs Object { "error": Array [], "info": Array [ - Array [ - "Running checkup", - ], - Array [ - "checkPing", - "Pinging registry", - ], - Array [ - "getLatestNpmVersion", - "Getting npm package information", - ], - Array [ - "getLatestNodejsVersion", - "Getting Node.js release information", - ], - Array [ - "getGitPath", - "Finding git in your PATH", - ], - Array [ - "getBinPath", - "Finding npm global bin in your PATH", - ], + "doctor Running checkup", + "doctor Pinging registry", + "doctor Getting npm package information", + "doctor Getting Node.js release information", + "doctor Finding git in your PATH", + "doctor getBinPath Finding npm global bin in your PATH", ], "warn": Array [], } diff --git a/tap-snapshots/test/lib/commands/fund.js.test.cjs b/tap-snapshots/test/lib/commands/fund.js.test.cjs index 011315a9211ef..7b6881c2d5ebf 100644 --- a/tap-snapshots/test/lib/commands/fund.js.test.cjs +++ b/tap-snapshots/test/lib/commands/fund.js.test.cjs @@ -30,19 +30,16 @@ nested-no-funding-packages@1.0.0 | \`-- lorem@1.0.0 \`-- http://example.com/donate \`-- bar@1.0.0 - ` exports[`test/lib/commands/fund.js TAP fund in which same maintainer owns all its deps > should print stack packages together 1`] = ` http://example.com/donate \`-- maintainer-owns-all-deps@1.0.0, dep-foo@1.0.0, dep-sub-foo@1.0.0, dep-bar@1.0.0 - ` exports[`test/lib/commands/fund.js TAP fund pkg missing version number > should print name only 1`] = ` http://example.com/foo \`-- foo - ` exports[`test/lib/commands/fund.js TAP fund using bad which value: index too high > should print message about invalid which 1`] = ` @@ -61,7 +58,6 @@ Run \`npm fund [] --which=1\`, for example, to open the first fund exports[`test/lib/commands/fund.js TAP fund with no package containing funding > should print empty funding info 1`] = ` no-funding-package@0.0.0 - ` exports[`test/lib/commands/fund.js TAP sub dep with fund info and a parent with no funding info > should nest sub dep as child of root 1`] = ` @@ -70,7 +66,6 @@ test-multiple-funding-sources@1.0.0 | \`-- b@1.0.0 \`-- http://example.com/c \`-- c@1.0.0 - ` exports[`test/lib/commands/fund.js TAP workspaces filter funding info by a specific workspace name > should display only filtered workspace name and its deps 1`] = ` @@ -79,7 +74,6 @@ workspaces-support@1.0.0 | \`-- a@1.0.0 \`-- http://example.com/c \`-- c@1.0.0 - ` exports[`test/lib/commands/fund.js TAP workspaces filter funding info by a specific workspace path > should display only filtered workspace name and its deps 1`] = ` @@ -88,5 +82,4 @@ workspaces-support@1.0.0 | \`-- a@1.0.0 \`-- http://example.com/c \`-- c@1.0.0 - ` diff --git a/tap-snapshots/test/lib/commands/ls.js.test.cjs b/tap-snapshots/test/lib/commands/ls.js.test.cjs index 3831b7c72fcfc..9d040856a87c9 100644 --- a/tap-snapshots/test/lib/commands/ls.js.test.cjs +++ b/tap-snapshots/test/lib/commands/ls.js.test.cjs @@ -42,14 +42,12 @@ test-npm-ls-ignore-missing-optional@1.2.3 {CWD}/prefix +-- UNMET DEPENDENCY prod-missing@1 +-- prod-ok@1.2.3 \`-- prod-wrong@3.2.1 invalid: "1" from the root project - ` exports[`test/lib/commands/ls.js TAP ls --depth=0 > should output tree containing only top-level dependencies 1`] = ` test-npm-ls@1.0.0 {CWD}/prefix +-- chai@1.0.0 \`-- foo@1.0.0 - ` exports[`test/lib/commands/ls.js TAP ls --depth=1 > should output tree containing top-level deps and their deps only 1`] = ` @@ -57,7 +55,6 @@ test-npm-ls@1.0.0 {CWD}/prefix +-- a@1.0.0 | \`-- b@1.0.0 \`-- e@1.0.0 - ` exports[`test/lib/commands/ls.js TAP ls --dev > should output tree containing dev deps 1`] = ` @@ -65,13 +62,11 @@ test-npm-ls@1.0.0 {CWD}/prefix \`-- dev-dep@1.0.0 \`-- foo@1.0.0 \`-- dog@1.0.0 - ` exports[`test/lib/commands/ls.js TAP ls --link > should output tree containing linked deps 1`] = ` test-npm-ls@1.0.0 {CWD}/prefix \`-- linked-dep@1.0.0 -> ./linked-dep - ` exports[`test/lib/commands/ls.js TAP ls --long --depth=0 > should output tree containing top-level deps with descriptions 1`] = ` @@ -88,7 +83,6 @@ test-npm-ls@1.0.0 | Peer-dep description here \`-- prod-dep@1.0.0 A PROD dep kind of dep - ` exports[`test/lib/commands/ls.js TAP ls --long > should output tree info with descriptions 1`] = ` @@ -111,7 +105,6 @@ test-npm-ls@1.0.0 | A PROD dep kind of dep \`-- dog@2.0.0 A dep that bars - ` exports[`test/lib/commands/ls.js TAP ls --parseable --depth=0 > should output tree containing only top-level dependencies 1`] = ` @@ -318,13 +311,11 @@ test-npm-ls@1.0.0 {CWD}/prefix +-- optional-dep@1.0.0 \`-- prod-dep@1.0.0 \`-- dog@2.0.0 - ` exports[`test/lib/commands/ls.js TAP ls broken resolved field > should NOT print git refs in output tree 1`] = ` npm-broken-resolved-field-test@1.0.0 {CWD}/prefix \`-- a@1.0.1 - ` exports[`test/lib/commands/ls.js TAP ls colored output > should output tree containing color info 1`] = ` @@ -341,7 +332,6 @@ test-npm-ls@1.0.0 {CWD}/prefix \`-- a@1.0.0 \`-- b@1.0.0 \`-- a@1.0.0 deduped - ` exports[`test/lib/commands/ls.js TAP ls cycle deps with filter args > should print tree output containing deduped ref 1`] = ` @@ -357,20 +347,17 @@ test-npm-ls@1.0.0 {CWD}/prefix +-- a@1.0.0 | \`-- UNMET DEPENDENCY b@^1.0.0 \`-- UNMET DEPENDENCY b@^1.0.0 - ` exports[`test/lib/commands/ls.js TAP ls default --depth value should be 0 > should output tree containing only top-level dependencies 1`] = ` test-npm-ls@1.0.0 {CWD}/prefix +-- chai@1.0.0 \`-- foo@1.0.0 - ` exports[`test/lib/commands/ls.js TAP ls empty location > should print empty result 1`] = ` {CWD}/prefix \`-- (empty) - ` exports[`test/lib/commands/ls.js TAP ls extraneous deps > should output containing problems info 1`] = ` @@ -378,19 +365,16 @@ test-npm-ls@1.0.0 {CWD}/prefix +-- chai@1.0.0 extraneous \`-- foo@1.0.0 \`-- dog@1.0.0 - ` exports[`test/lib/commands/ls.js TAP ls filter pkg arg using depth option should list a in top-level only > output 1`] = ` test-pkg-arg-filter-with-depth-opt@1.0.0 {CWD}/prefix \`-- a@1.0.0 - ` exports[`test/lib/commands/ls.js TAP ls filter pkg arg using depth option should print empty results msg > output 1`] = ` test-pkg-arg-filter-with-depth-opt@1.0.0 {CWD}/prefix \`-- (empty) - ` exports[`test/lib/commands/ls.js TAP ls filter pkg arg using depth option should print expected result > output 1`] = ` @@ -398,7 +382,6 @@ test-pkg-arg-filter-with-depth-opt@1.0.0 {CWD}/prefix \`-- b@1.0.0 \`-- c@1.0.0 \`-- d@1.0.0 - ` exports[`test/lib/commands/ls.js TAP ls filtering by child of missing dep > should print tree and not duplicate child of missing items 1`] = ` @@ -408,13 +391,11 @@ filter-by-child-of-missing-dep@1.0.0 {CWD}/prefix +-- c@1.0.0 extraneous \`-- d@1.0.0 extraneous \`-- c@2.0.0 extraneous - ` exports[`test/lib/commands/ls.js TAP ls from and resolved properties > should not be printed in tree output 1`] = ` test-npm-ls@1.0.0 {CWD}/prefix \`-- simple-output@2.1.1 - ` exports[`test/lib/commands/ls.js TAP ls global > should print tree and not mark top-level items extraneous 1`] = ` @@ -422,7 +403,6 @@ exports[`test/lib/commands/ls.js TAP ls global > should print tree and not mark +-- a@1.0.0 \`-- b@1.0.0 \`-- c@1.0.0 - ` exports[`test/lib/commands/ls.js TAP ls invalid deduped dep > should output tree signaling mismatching peer dep in problems 1`] = ` @@ -443,20 +423,17 @@ test-npm-ls@1.0.0 {CWD}/prefix +-- peer-dep@1.0.0 invalid: "^2.0.0" from the root project \`-- prod-dep@1.0.0 \`-- dog@2.0.0 - ` exports[`test/lib/commands/ls.js TAP ls json read problems > should print empty result 1`] = ` {CWD}/prefix \`-- (empty) - ` exports[`test/lib/commands/ls.js TAP ls loading a tree containing workspaces should filter by parent folder workspace config > output 1`] = ` workspaces-tree@1.0.0 {CWD}/prefix +-- e@1.0.0 -> ./group/e \`-- f@1.0.0 -> ./group/f - ` exports[`test/lib/commands/ls.js TAP ls loading a tree containing workspaces should filter single workspace > output 1`] = ` @@ -464,7 +441,6 @@ workspaces-tree@1.0.0 {CWD}/prefix +-- a@1.0.0 -> ./a | \`-- d@1.0.0 deduped -> ./d \`-- d@1.0.0 -> ./d - ` exports[`test/lib/commands/ls.js TAP ls loading a tree containing workspaces should filter using workspace config > output 1`] = ` @@ -475,7 +451,6 @@ workspaces-tree@1.0.0 {CWD}/prefix \`-- d@1.0.0 -> ./d \`-- foo@1.1.1 \`-- bar@1.0.0 - ` exports[`test/lib/commands/ls.js TAP ls loading a tree containing workspaces should inlude root and specified workspace > output 1`] = ` @@ -484,7 +459,6 @@ workspaces-tree@1.0.0 {CWD}/prefix | \`-- foo@1.1.1 | \`-- bar@1.0.0 \`-- pacote@1.0.0 - ` exports[`test/lib/commands/ls.js TAP ls loading a tree containing workspaces should list --all workspaces properly > output 1`] = ` @@ -500,7 +474,6 @@ workspaces-tree@1.0.0 {CWD}/prefix +-- e@1.0.0 -> ./group/e +-- f@1.0.0 -> ./group/f \`-- pacote@1.0.0 - ` exports[`test/lib/commands/ls.js TAP ls loading a tree containing workspaces should list only prod deps of workspaces > output 1`] = ` @@ -515,7 +488,6 @@ workspaces-tree@1.0.0 {CWD}/prefix +-- e@1.0.0 -> ./group/e +-- f@1.0.0 -> ./group/f \`-- pacote@1.0.0 - ` exports[`test/lib/commands/ls.js TAP ls loading a tree containing workspaces should list workspaces properly with default configs > output 1`] = ` @@ -544,7 +516,6 @@ workspaces-tree@1.0.0 {CWD}/prefix \`-- d@1.0.0 -> ./d \`-- foo@1.1.1 \`-- bar@1.0.0 - ` exports[`test/lib/commands/ls.js TAP ls missing package.json > should output tree missing name/version of top-level package 1`] = ` @@ -553,7 +524,6 @@ exports[`test/lib/commands/ls.js TAP ls missing package.json > should output tre +-- dog@1.0.0 extraneous \`-- foo@1.0.0 extraneous \`-- dog@1.0.0 deduped - ` exports[`test/lib/commands/ls.js TAP ls missing/invalid/extraneous > should output tree containing missing, invalid, extraneous labels 1`] = ` @@ -562,7 +532,6 @@ test-npm-ls@1.0.0 {CWD}/prefix +-- foo@1.0.0 invalid: "^2.0.0" from the root project | \`-- dog@1.0.0 \`-- UNMET DEPENDENCY ipsum@^1.0.0 - ` exports[`test/lib/commands/ls.js TAP ls no args > should output tree representation of dependencies structure 1`] = ` @@ -570,14 +539,12 @@ test-npm-ls@1.0.0 {CWD}/prefix +-- chai@1.0.0 \`-- foo@1.0.0 \`-- dog@1.0.0 - ` exports[`test/lib/commands/ls.js TAP ls overridden dep > should contain overridden outout 1`] = ` test-overridden@1.0.0 {CWD}/prefix \`-- foo@1.0.0 \`-- bar@1.0.0 overridden - ` exports[`test/lib/commands/ls.js TAP ls overridden dep w/ color > should contain overridden outout 1`] = ` @@ -592,13 +559,11 @@ print-deduped-symlinks@1.0.0 {CWD}/prefix +-- a@1.0.0 | \`-- b@1.0.0 deduped -> ./b \`-- b@1.0.0 -> ./b - ` exports[`test/lib/commands/ls.js TAP ls resolved points to git ref > should output tree containing git refs 1`] = ` test-npm-ls@1.0.0 {CWD}/prefix \`-- abbrev@1.1.1 (git+ssh://git@github.com/isaacs/abbrev-js.git#b8f3a2fc0c3bb8ffd8b0d0072cc6b5a3667e963c) - ` exports[`test/lib/commands/ls.js TAP ls unmet optional dep > should output tree with empty entry for missing optional deps 1`] = ` @@ -618,13 +583,11 @@ exports[`test/lib/commands/ls.js TAP ls unmet optional dep > should output tree exports[`test/lib/commands/ls.js TAP ls unmet peer dep > should output tree signaling missing peer dep in problems 1`] = ` test-npm-ls@1.0.0 {CWD}/prefix \`-- UNMET DEPENDENCY peer-dep@* - ` exports[`test/lib/commands/ls.js TAP ls using aliases > should output tree containing aliases 1`] = ` test-npm-ls@1.0.0 {CWD}/prefix \`-- a@npm:b@1.0.0 - ` exports[`test/lib/commands/ls.js TAP ls with args and dedupe entries > should print tree output containing deduped ref 1`] = ` @@ -644,13 +607,11 @@ dedupe-entries@1.0.0 {CWD}/prefix +-- @npmcli/b@1.1.2 | \`-- @npmcli/c@1.0.0 deduped \`-- @npmcli/c@1.0.0 - ` exports[`test/lib/commands/ls.js TAP ls with dot filter arg > should output tree contaning only occurrences of filtered by package and colored output 1`] = ` test-npm-ls@1.0.0 {CWD}/prefix \`-- (empty) - ` exports[`test/lib/commands/ls.js TAP ls with filter arg > should output tree contaning only occurrences of filtered by package and colored output 1`] = ` @@ -663,13 +624,11 @@ exports[`test/lib/commands/ls.js TAP ls with filter arg nested dep > should outp test-npm-ls@1.0.0 {CWD}/prefix \`-- foo@1.0.0 \`-- dog@1.0.0 - ` exports[`test/lib/commands/ls.js TAP ls with missing filter arg > should output tree containing no dependencies info 1`] = ` test-npm-ls@1.0.0 {CWD}/prefix \`-- (empty) - ` exports[`test/lib/commands/ls.js TAP ls with multiple filter args > should output tree contaning only occurrences of multiple filtered packages and their ancestors 1`] = ` @@ -677,7 +636,6 @@ test-npm-ls@1.0.0 {CWD}/prefix +-- chai@1.0.0 \`-- foo@1.0.0 \`-- dog@1.0.0 - ` exports[`test/lib/commands/ls.js TAP ls with no args dedupe entries > should print tree output containing deduped ref 1`] = ` @@ -687,7 +645,6 @@ dedupe-entries@1.0.0 {CWD}/prefix +-- @npmcli/b@1.1.2 \`-- @npmcli/c@1.0.0 \`-- @npmcli/b@1.1.2 deduped - ` exports[`test/lib/commands/ls.js TAP ls with no args dedupe entries and not displaying all > should print tree output containing deduped ref 1`] = ` @@ -695,14 +652,12 @@ dedupe-entries@1.0.0 {CWD}/prefix +-- @npmcli/a@1.0.0 +-- @npmcli/b@1.1.2 \`-- @npmcli/c@1.0.0 - ` exports[`test/lib/commands/ls.js TAP ls workspace and missing optional dep > should omit missing optional dep 1`] = ` root@ {CWD}/prefix +-- baz@1.0.0 -> ./baz \`-- foo@1.0.0 - ` exports[`test/lib/commands/ls.js TAP show multiple invalid reasons > ls result 1`] = ` @@ -713,5 +668,4 @@ test-npm-ls@1.0.0 {CWD}/prefix | \`-- dog@1.0.0 deduped invalid: "^1.2.3" from the root project, "^2.0.0" from node_modules/cat, "2.x" from node_modules/chai \`-- dog@1.0.0 invalid: "^1.2.3" from the root project, "^2.0.0" from node_modules/cat, "2.x" from node_modules/chai \`-- cat@1.0.0 deduped invalid: "^2.0.0" from the root project - ` diff --git a/tap-snapshots/test/lib/commands/pack.js.test.cjs b/tap-snapshots/test/lib/commands/pack.js.test.cjs index d2148c40bd5df..d78bac7a1626e 100644 --- a/tap-snapshots/test/lib/commands/pack.js.test.cjs +++ b/tap-snapshots/test/lib/commands/pack.js.test.cjs @@ -7,11 +7,10 @@ 'use strict' exports[`test/lib/commands/pack.js TAP dry run > logs pack contents 1`] = ` Array [ - undefined, "package: test-package@1.0.0", - undefined, + "=== Tarball Contents ===", "41B package.json", - undefined, + "=== Tarball Details ===", String( name: test-package version: 1.0.0 @@ -22,17 +21,15 @@ Array [ integrity: {integrity} total files: 1 ), - "", ] ` exports[`test/lib/commands/pack.js TAP foreground-scripts can still be set to false > logs pack contents 1`] = ` Array [ - undefined, "package: test-fg-scripts@0.0.0", - undefined, + "=== Tarball Contents ===", "110B package.json", - undefined, + "=== Tarball Details ===", String( name: test-fg-scripts version: 0.0.0 @@ -43,17 +40,15 @@ Array [ integrity: {integrity} total files: 1 ), - "", ] ` exports[`test/lib/commands/pack.js TAP foreground-scripts defaults to true > logs pack contents 1`] = ` Array [ - undefined, "package: test-fg-scripts@0.0.0", - undefined, + "=== Tarball Contents ===", "110B package.json", - undefined, + "=== Tarball Details ===", String( name: test-fg-scripts version: 0.0.0 @@ -64,7 +59,6 @@ Array [ integrity: {integrity} total files: 1 ), - "", ] ` @@ -130,11 +124,10 @@ Array [ exports[`test/lib/commands/pack.js TAP should pack current directory with no arguments > logs pack contents 1`] = ` Array [ - undefined, "package: test-package@1.0.0", - undefined, + "=== Tarball Contents ===", "41B package.json", - undefined, + "=== Tarball Details ===", String( name: test-package version: 1.0.0 @@ -145,6 +138,5 @@ Array [ integrity: {integrity} total files: 1 ), - "", ] ` diff --git a/tap-snapshots/test/lib/commands/publish.js.test.cjs b/tap-snapshots/test/lib/commands/publish.js.test.cjs index 613cbe2810df5..875e25ebd8813 100644 --- a/tap-snapshots/test/lib/commands/publish.js.test.cjs +++ b/tap-snapshots/test/lib/commands/publish.js.test.cjs @@ -15,130 +15,61 @@ exports[`test/lib/commands/publish.js TAP bare _auth and registry config > new p exports[`test/lib/commands/publish.js TAP dry-run > must match snapshot 1`] = ` Array [ - Array [ - "", - ], - Array [ - "", - "package: test-package@1.0.0", - ], - Array [ - "=== Tarball Contents ===", - ], - Array [ - "", - "87B package.json", - ], - Array [ - "=== Tarball Details ===", - ], - Array [ - "", - String( - name: test-package - version: 1.0.0 - filename: test-package-1.0.0.tgz - package size: {size} - unpacked size: 87 B - shasum: {sha} - integrity: {integrity} - total files: 1 - ), - ], - Array [ - "", - "", - ], - Array [ - "", - "Publishing to https://registry.npmjs.org/ with tag latest and default access (dry-run)", - ], + "package: test-package@1.0.0", + "=== Tarball Contents ===", + "87B package.json", + "=== Tarball Details ===", + String( + name: test-package + version: 1.0.0 + filename: test-package-1.0.0.tgz + package size: {size} + unpacked size: 87 B + shasum: {sha} + integrity: {integrity} + total files: 1 + ), + "Publishing to https://registry.npmjs.org/ with tag latest and default access (dry-run)", ] ` exports[`test/lib/commands/publish.js TAP foreground-scripts can still be set to false > must match snapshot 1`] = ` Array [ - Array [ - "", - ], - Array [ - "", - "package: test-fg-scripts@0.0.0", - ], - Array [ - "=== Tarball Contents ===", - ], - Array [ - "", - "110B package.json", - ], - Array [ - "=== Tarball Details ===", - ], - Array [ - "", - String( - name: test-fg-scripts - version: 0.0.0 - filename: test-fg-scripts-0.0.0.tgz - package size: {size} - unpacked size: 110 B - shasum: {sha} - integrity: {integrity} - total files: 1 - ), - ], - Array [ - "", - "", - ], - Array [ - "", - "Publishing to https://registry.npmjs.org/ with tag latest and default access (dry-run)", - ], + "package: test-fg-scripts@0.0.0", + "=== Tarball Contents ===", + "110B package.json", + "=== Tarball Details ===", + String( + name: test-fg-scripts + version: 0.0.0 + filename: test-fg-scripts-0.0.0.tgz + package size: {size} + unpacked size: 110 B + shasum: {sha} + integrity: {integrity} + total files: 1 + ), + "Publishing to https://registry.npmjs.org/ with tag latest and default access (dry-run)", ] ` exports[`test/lib/commands/publish.js TAP foreground-scripts defaults to true > must match snapshot 1`] = ` Array [ - Array [ - "", - ], - Array [ - "", - "package: test-fg-scripts@0.0.0", - ], - Array [ - "=== Tarball Contents ===", - ], - Array [ - "", - "110B package.json", - ], - Array [ - "=== Tarball Details ===", - ], - Array [ - "", - String( - name: test-fg-scripts - version: 0.0.0 - filename: test-fg-scripts-0.0.0.tgz - package size: {size} - unpacked size: 110 B - shasum: {sha} - integrity: {integrity} - total files: 1 - ), - ], - Array [ - "", - "", - ], - Array [ - "", - "Publishing to https://registry.npmjs.org/ with tag latest and default access (dry-run)", - ], + "package: test-fg-scripts@0.0.0", + "=== Tarball Contents ===", + "110B package.json", + "=== Tarball Details ===", + String( + name: test-fg-scripts + version: 0.0.0 + filename: test-fg-scripts-0.0.0.tgz + package size: {size} + unpacked size: 110 B + shasum: {sha} + integrity: {integrity} + total files: 1 + ), + "Publishing to https://registry.npmjs.org/ with tag latest and default access (dry-run)", ] ` @@ -156,10 +87,7 @@ exports[`test/lib/commands/publish.js TAP ignore-scripts > new package version 1 exports[`test/lib/commands/publish.js TAP json > must match snapshot 1`] = ` Array [ - Array [ - "", - "Publishing to https://registry.npmjs.org/ with tag latest and default access", - ], + "Publishing to https://registry.npmjs.org/ with tag latest and default access", ] ` @@ -332,21 +260,12 @@ exports[`test/lib/commands/publish.js TAP no auth dry-run > must match snapshot exports[`test/lib/commands/publish.js TAP no auth dry-run > warns about auth being needed 1`] = ` Array [ - Array [ - "publish", - "npm auto-corrected some errors in your package.json when publishing. Please run \\"npm pkg fix\\" to address these errors.", - ], - Array [ - "publish", - String( - errors corrected: - Removed invalid "scripts" - ), - ], - Array [ - "", - "This command requires you to be logged in to https://registry.npmjs.org/ (dry-run)", - ], + "publish npm auto-corrected some errors in your package.json when publishing. Please run \\"npm pkg fix\\" to address these errors.", + String( + publish errors corrected: + publish Removed invalid "scripts" + ), + "This command requires you to be logged in to https://registry.npmjs.org/ (dry-run)", ] ` @@ -356,44 +275,21 @@ exports[`test/lib/commands/publish.js TAP prioritize CLI flags over publishConfi exports[`test/lib/commands/publish.js TAP public access > must match snapshot 1`] = ` Array [ - Array [ - "", - ], - Array [ - "", - "package: @npm/test-package@1.0.0", - ], - Array [ - "=== Tarball Contents ===", - ], - Array [ - "", - "55B package.json", - ], - Array [ - "=== Tarball Details ===", - ], - Array [ - "", - String( - name: @npm/test-package - version: 1.0.0 - filename: npm-test-package-1.0.0.tgz - package size: {size} - unpacked size: 55 B - shasum: {sha} - integrity: {integrity} - total files: 1 - ), - ], - Array [ - "", - "", - ], - Array [ - "", - "Publishing to https://registry.npmjs.org/ with tag latest and public access", - ], + "package: @npm/test-package@1.0.0", + "=== Tarball Contents ===", + "55B package.json", + "=== Tarball Details ===", + String( + name: @npm/test-package + version: 1.0.0 + filename: npm-test-package-1.0.0.tgz + package size: {size} + unpacked size: 55 B + shasum: {sha} + integrity: {integrity} + total files: 1 + ), + "Publishing to https://registry.npmjs.org/ with tag latest and public access", ] ` @@ -411,44 +307,21 @@ exports[`test/lib/commands/publish.js TAP respects publishConfig.registry, runs exports[`test/lib/commands/publish.js TAP restricted access > must match snapshot 1`] = ` Array [ - Array [ - "", - ], - Array [ - "", - "package: @npm/test-package@1.0.0", - ], - Array [ - "=== Tarball Contents ===", - ], - Array [ - "", - "55B package.json", - ], - Array [ - "=== Tarball Details ===", - ], - Array [ - "", - String( - name: @npm/test-package - version: 1.0.0 - filename: npm-test-package-1.0.0.tgz - package size: {size} - unpacked size: 55 B - shasum: {sha} - integrity: {integrity} - total files: 1 - ), - ], - Array [ - "", - "", - ], - Array [ - "", - "Publishing to https://registry.npmjs.org/ with tag latest and restricted access", - ], + "package: @npm/test-package@1.0.0", + "=== Tarball Contents ===", + "55B package.json", + "=== Tarball Details ===", + String( + name: @npm/test-package + version: 1.0.0 + filename: npm-test-package-1.0.0.tgz + package size: {size} + unpacked size: 55 B + shasum: {sha} + integrity: {integrity} + total files: 1 + ), + "Publishing to https://registry.npmjs.org/ with tag latest and restricted access", ] ` @@ -462,47 +335,24 @@ exports[`test/lib/commands/publish.js TAP scoped _auth config scoped registry > exports[`test/lib/commands/publish.js TAP tarball > must match snapshot 1`] = ` Array [ - Array [ - "", - ], - Array [ - "", - "package: test-tar-package@1.0.0", - ], - Array [ - "=== Tarball Contents ===", - ], - Array [ - "", - String( - 26B index.js - 98B package.json - ), - ], - Array [ - "=== Tarball Details ===", - ], - Array [ - "", - String( - name: test-tar-package - version: 1.0.0 - filename: test-tar-package-1.0.0.tgz - package size: {size} - unpacked size: 124 B - shasum: {sha} - integrity: {integrity} - total files: 2 - ), - ], - Array [ - "", - "", - ], - Array [ - "", - "Publishing to https://registry.npmjs.org/ with tag latest and default access", - ], + "package: test-tar-package@1.0.0", + "=== Tarball Contents ===", + String( + 26B index.js + 98B package.json + ), + "=== Tarball Details ===", + String( + name: test-tar-package + version: 1.0.0 + filename: test-tar-package-1.0.0.tgz + package size: {size} + unpacked size: 124 B + shasum: {sha} + integrity: {integrity} + total files: 2 + ), + "Publishing to https://registry.npmjs.org/ with tag latest and default access", ] ` @@ -518,57 +368,30 @@ exports[`test/lib/commands/publish.js TAP workspaces all workspaces - color > al exports[`test/lib/commands/publish.js TAP workspaces all workspaces - color > warns about skipped private workspace in color 1`] = ` Array [ - Array [ - "publish", - "npm auto-corrected some errors in your package.json when publishing. Please run \\"npm pkg fix\\" to address these errors.", - ], - Array [ - "publish", - String( - errors corrected: - Removed invalid "scripts" - "repository" was changed from a string to an object - ), - ], - Array [ - "publish", - "npm auto-corrected some errors in your package.json when publishing. Please run \\"npm pkg fix\\" to address these errors.", - ], - Array [ - "publish", - String( - errors corrected: - Removed invalid "scripts" - "repository" was changed from a string to an object - "repository.url" was normalized to "git+https://github.com/npm/workspace-b.git" - ), - ], - Array [ - "publish", - "npm auto-corrected some errors in your package.json when publishing. Please run \\"npm pkg fix\\" to address these errors.", - ], - Array [ - "publish", - String( - errors corrected: - Removed invalid "scripts" - ), - ], - Array [ - "publish", - "npm auto-corrected some errors in your package.json when publishing. Please run \\"npm pkg fix\\" to address these errors.", - ], - Array [ - "publish", - String( - errors corrected: - Removed invalid "scripts" - ), - ], - Array [ - "publish", - "Skipping workspace \\u001b[32mworkspace-p\\u001b[39m, marked as \\u001b[1mprivate\\u001b[22m", - ], + "\\u001b[35mpublish\\u001b[39m npm auto-corrected some errors in your package.json when publishing. Please run \\"npm pkg fix\\" to address these errors.", + String( + \\u001b[35mpublish\\u001b[39m errors corrected: + \\u001b[35mpublish\\u001b[39m Removed invalid "scripts" + \\u001b[35mpublish\\u001b[39m "repository" was changed from a string to an object + ), + "\\u001b[35mpublish\\u001b[39m npm auto-corrected some errors in your package.json when publishing. Please run \\"npm pkg fix\\" to address these errors.", + String( + \\u001b[35mpublish\\u001b[39m errors corrected: + \\u001b[35mpublish\\u001b[39m Removed invalid "scripts" + \\u001b[35mpublish\\u001b[39m "repository" was changed from a string to an object + \\u001b[35mpublish\\u001b[39m "repository.url" was normalized to "git+https://github.com/npm/workspace-b.git" + ), + "\\u001b[35mpublish\\u001b[39m npm auto-corrected some errors in your package.json when publishing. Please run \\"npm pkg fix\\" to address these errors.", + String( + \\u001b[35mpublish\\u001b[39m errors corrected: + \\u001b[35mpublish\\u001b[39m Removed invalid "scripts" + ), + "\\u001b[35mpublish\\u001b[39m npm auto-corrected some errors in your package.json when publishing. Please run \\"npm pkg fix\\" to address these errors.", + String( + \\u001b[35mpublish\\u001b[39m errors corrected: + \\u001b[35mpublish\\u001b[39m Removed invalid "scripts" + ), + "\\u001b[35mpublish\\u001b[39m Skipping workspace \\u001b[32mworkspace-p\\u001b[39m, marked as \\u001b[1mprivate\\u001b[22m", ] ` @@ -580,57 +403,30 @@ exports[`test/lib/commands/publish.js TAP workspaces all workspaces - no color > exports[`test/lib/commands/publish.js TAP workspaces all workspaces - no color > warns about skipped private workspace 1`] = ` Array [ - Array [ - "publish", - "npm auto-corrected some errors in your package.json when publishing. Please run \\"npm pkg fix\\" to address these errors.", - ], - Array [ - "publish", - String( - errors corrected: - Removed invalid "scripts" - "repository" was changed from a string to an object - ), - ], - Array [ - "publish", - "npm auto-corrected some errors in your package.json when publishing. Please run \\"npm pkg fix\\" to address these errors.", - ], - Array [ - "publish", - String( - errors corrected: - Removed invalid "scripts" - "repository" was changed from a string to an object - "repository.url" was normalized to "git+https://github.com/npm/workspace-b.git" - ), - ], - Array [ - "publish", - "npm auto-corrected some errors in your package.json when publishing. Please run \\"npm pkg fix\\" to address these errors.", - ], - Array [ - "publish", - String( - errors corrected: - Removed invalid "scripts" - ), - ], - Array [ - "publish", - "npm auto-corrected some errors in your package.json when publishing. Please run \\"npm pkg fix\\" to address these errors.", - ], - Array [ - "publish", - String( - errors corrected: - Removed invalid "scripts" - ), - ], - Array [ - "publish", - "Skipping workspace workspace-p, marked as private", - ], + "publish npm auto-corrected some errors in your package.json when publishing. Please run \\"npm pkg fix\\" to address these errors.", + String( + publish errors corrected: + publish Removed invalid "scripts" + publish "repository" was changed from a string to an object + ), + "publish npm auto-corrected some errors in your package.json when publishing. Please run \\"npm pkg fix\\" to address these errors.", + String( + publish errors corrected: + publish Removed invalid "scripts" + publish "repository" was changed from a string to an object + publish "repository.url" was normalized to "git+https://github.com/npm/workspace-b.git" + ), + "publish npm auto-corrected some errors in your package.json when publishing. Please run \\"npm pkg fix\\" to address these errors.", + String( + publish errors corrected: + publish Removed invalid "scripts" + ), + "publish npm auto-corrected some errors in your package.json when publishing. Please run \\"npm pkg fix\\" to address these errors.", + String( + publish errors corrected: + publish Removed invalid "scripts" + ), + "publish Skipping workspace workspace-p, marked as private", ] ` diff --git a/tap-snapshots/test/lib/commands/shrinkwrap.js.test.cjs b/tap-snapshots/test/lib/commands/shrinkwrap.js.test.cjs index d97f13d2ed85c..f0ac314925b28 100644 --- a/tap-snapshots/test/lib/commands/shrinkwrap.js.test.cjs +++ b/tap-snapshots/test/lib/commands/shrinkwrap.js.test.cjs @@ -22,7 +22,8 @@ exports[`test/lib/commands/shrinkwrap.js TAP with hidden lockfile ancient > must }, "logs": [ "created a lockfile as npm-shrinkwrap.json" - ] + ], + "warn": [] } ` @@ -46,6 +47,9 @@ exports[`test/lib/commands/shrinkwrap.js TAP with hidden lockfile ancient upgrad }, "logs": [ "created a lockfile as npm-shrinkwrap.json with version 3" + ], + "warn": [ + "Converting lock file (npm-shrinkwrap.json) from v1 -> v3" ] } ` @@ -68,7 +72,8 @@ exports[`test/lib/commands/shrinkwrap.js TAP with hidden lockfile existing > mus }, "logs": [ "created a lockfile as npm-shrinkwrap.json" - ] + ], + "warn": [] } ` @@ -91,6 +96,9 @@ exports[`test/lib/commands/shrinkwrap.js TAP with hidden lockfile existing downg }, "logs": [ "created a lockfile as npm-shrinkwrap.json with version 1" + ], + "warn": [ + "Converting lock file (npm-shrinkwrap.json) from v2 -> v1" ] } ` @@ -115,6 +123,9 @@ exports[`test/lib/commands/shrinkwrap.js TAP with hidden lockfile existing upgra }, "logs": [ "created a lockfile as npm-shrinkwrap.json with version 3" + ], + "warn": [ + "Converting lock file (npm-shrinkwrap.json) from v2 -> v3" ] } ` @@ -131,7 +142,8 @@ exports[`test/lib/commands/shrinkwrap.js TAP with nothing ancient > must match s }, "logs": [ "created a lockfile as npm-shrinkwrap.json with version 3" - ] + ], + "warn": [] } ` @@ -149,7 +161,8 @@ exports[`test/lib/commands/shrinkwrap.js TAP with nothing ancient upgrade > must }, "logs": [ "created a lockfile as npm-shrinkwrap.json with version 3" - ] + ], + "warn": [] } ` @@ -173,6 +186,9 @@ exports[`test/lib/commands/shrinkwrap.js TAP with npm-shrinkwrap.json ancient > }, "logs": [ "npm-shrinkwrap.json updated to version 3" + ], + "warn": [ + "Converting lock file (npm-shrinkwrap.json) from v1 -> v3" ] } ` @@ -199,6 +215,9 @@ exports[`test/lib/commands/shrinkwrap.js TAP with npm-shrinkwrap.json ancient up }, "logs": [ "npm-shrinkwrap.json updated to version 3" + ], + "warn": [ + "Converting lock file (npm-shrinkwrap.json) from v1 -> v3" ] } ` @@ -223,7 +242,8 @@ exports[`test/lib/commands/shrinkwrap.js TAP with npm-shrinkwrap.json existing > }, "logs": [ "npm-shrinkwrap.json up to date" - ] + ], + "warn": [] } ` @@ -244,6 +264,9 @@ exports[`test/lib/commands/shrinkwrap.js TAP with npm-shrinkwrap.json existing d }, "logs": [ "npm-shrinkwrap.json updated to version 1" + ], + "warn": [ + "Converting lock file (npm-shrinkwrap.json) from v2 -> v1" ] } ` @@ -270,6 +293,9 @@ exports[`test/lib/commands/shrinkwrap.js TAP with npm-shrinkwrap.json existing u }, "logs": [ "npm-shrinkwrap.json updated to version 3" + ], + "warn": [ + "Converting lock file (npm-shrinkwrap.json) from v2 -> v3" ] } ` @@ -294,6 +320,9 @@ exports[`test/lib/commands/shrinkwrap.js TAP with package-lock.json ancient > mu }, "logs": [ "package-lock.json has been renamed to npm-shrinkwrap.json and updated to version 3" + ], + "warn": [ + "Converting lock file (npm-shrinkwrap.json) from v1 -> v3" ] } ` @@ -320,6 +349,9 @@ exports[`test/lib/commands/shrinkwrap.js TAP with package-lock.json ancient upgr }, "logs": [ "package-lock.json has been renamed to npm-shrinkwrap.json and updated to version 3" + ], + "warn": [ + "Converting lock file (npm-shrinkwrap.json) from v1 -> v3" ] } ` @@ -344,7 +376,8 @@ exports[`test/lib/commands/shrinkwrap.js TAP with package-lock.json existing > m }, "logs": [ "package-lock.json has been renamed to npm-shrinkwrap.json" - ] + ], + "warn": [] } ` @@ -365,6 +398,9 @@ exports[`test/lib/commands/shrinkwrap.js TAP with package-lock.json existing dow }, "logs": [ "package-lock.json has been renamed to npm-shrinkwrap.json and updated to version 1" + ], + "warn": [ + "Converting lock file (npm-shrinkwrap.json) from v2 -> v1" ] } ` @@ -391,6 +427,9 @@ exports[`test/lib/commands/shrinkwrap.js TAP with package-lock.json existing upg }, "logs": [ "package-lock.json has been renamed to npm-shrinkwrap.json and updated to version 3" + ], + "warn": [ + "Converting lock file (npm-shrinkwrap.json) from v2 -> v3" ] } ` diff --git a/tap-snapshots/test/lib/commands/view.js.test.cjs b/tap-snapshots/test/lib/commands/view.js.test.cjs index 3bda4e7de2853..fe22a14dc179c 100644 --- a/tap-snapshots/test/lib/commands/view.js.test.cjs +++ b/tap-snapshots/test/lib/commands/view.js.test.cjs @@ -542,9 +542,7 @@ dist-tags: exports[`test/lib/commands/view.js TAP workspaces remote package name > should have warning of ignoring workspaces 1`] = ` Array [ - Array [ - "Ignoring workspaces for specified package(s)", - ], + "\\u001b[35mIgnoring workspaces for specified package(s)\\u001b[39m", ] ` diff --git a/tap-snapshots/test/lib/npm.js.test.cjs b/tap-snapshots/test/lib/npm.js.test.cjs index e29061291137e..32ab47ef06b18 100644 --- a/tap-snapshots/test/lib/npm.js.test.cjs +++ b/tap-snapshots/test/lib/npm.js.test.cjs @@ -5,6 +5,16 @@ * Make sure to inspect the output below. Do not ignore changes! */ 'use strict' +exports[`test/lib/npm.js TAP npm.load workspace-aware configs and commands > should exec workspaces version of commands 1`] = ` +Lifecycle scripts included in a@1.0.0: + test + echo test a + +Lifecycle scripts included in b@1.0.0: + test + echo test b +` + exports[`test/lib/npm.js TAP usage set process.stdout.columns column width 0 > must match snapshot 1`] = ` npm diff --git a/tap-snapshots/test/lib/utils/error-message.js.test.cjs b/tap-snapshots/test/lib/utils/error-message.js.test.cjs index 13e3104af9302..c6c694e2250b0 100644 --- a/tap-snapshots/test/lib/utils/error-message.js.test.cjs +++ b/tap-snapshots/test/lib/utils/error-message.js.test.cjs @@ -519,22 +519,10 @@ Object { exports[`test/lib/utils/error-message.js TAP eacces/eperm {"windows":false,"loaded":true,"cachePath":false,"cacheDest":false} > must match snapshot 2`] = ` Array [ - Array [ - "title", - "npm", - ], - Array [ - "argv", - "/"--fetch-retries/" /"0/" /"--cache/" /"{CWD}/cache/"", - ], - Array [ - "logfile", - "logs-max:10 dir:{CWD}/cache/_logs/{DATE}-", - ], - Array [ - "logfile", - "{CWD}/cache/_logs/{DATE}-debug-0.log", - ], + "title npm", + "argv /"--fetch-retries/" /"0/" /"--cache/" /"{CWD}/cache/" /"--loglevel/" /"silly/" /"--color/" /"false/"", + "logfile logs-max:10 dir:{CWD}/cache/_logs/{DATE}-", + "logfile {CWD}/cache/_logs/{DATE}-debug-0.log", ] ` @@ -559,22 +547,11 @@ Object { exports[`test/lib/utils/error-message.js TAP eacces/eperm {"windows":false,"loaded":true,"cachePath":false,"cacheDest":true} > must match snapshot 2`] = ` Array [ - Array [ - "title", - "npm", - ], - Array [ - "argv", - "/"--fetch-retries/" /"0/" /"--cache/" /"{CWD}/cache/"", - ], - Array [ - "logfile", - "logs-max:10 dir:{CWD}/cache/_logs/{DATE}-", - ], - Array [ - "logfile", - "{CWD}/cache/_logs/{DATE}-debug-0.log", - ], + "title npm", + "argv /"--fetch-retries/" /"0/" /"--cache/" /"{CWD}/cache/" /"--loglevel/" /"silly/" /"--color/" /"false/"", + "logfile logs-max:10 dir:{CWD}/cache/_logs/{DATE}-", + "logfile {CWD}/cache/_logs/{DATE}-debug-0.log", + "dummy stack trace", ] ` @@ -599,22 +576,11 @@ Object { exports[`test/lib/utils/error-message.js TAP eacces/eperm {"windows":false,"loaded":true,"cachePath":true,"cacheDest":false} > must match snapshot 2`] = ` Array [ - Array [ - "title", - "npm", - ], - Array [ - "argv", - "/"--fetch-retries/" /"0/" /"--cache/" /"{CWD}/cache/"", - ], - Array [ - "logfile", - "logs-max:10 dir:{CWD}/cache/_logs/{DATE}-", - ], - Array [ - "logfile", - "{CWD}/cache/_logs/{DATE}-debug-0.log", - ], + "title npm", + "argv /"--fetch-retries/" /"0/" /"--cache/" /"{CWD}/cache/" /"--loglevel/" /"silly/" /"--color/" /"false/"", + "logfile logs-max:10 dir:{CWD}/cache/_logs/{DATE}-", + "logfile {CWD}/cache/_logs/{DATE}-debug-0.log", + "dummy stack trace", ] ` @@ -639,22 +605,11 @@ Object { exports[`test/lib/utils/error-message.js TAP eacces/eperm {"windows":false,"loaded":true,"cachePath":true,"cacheDest":true} > must match snapshot 2`] = ` Array [ - Array [ - "title", - "npm", - ], - Array [ - "argv", - "/"--fetch-retries/" /"0/" /"--cache/" /"{CWD}/cache/"", - ], - Array [ - "logfile", - "logs-max:10 dir:{CWD}/cache/_logs/{DATE}-", - ], - Array [ - "logfile", - "{CWD}/cache/_logs/{DATE}-debug-0.log", - ], + "title npm", + "argv /"--fetch-retries/" /"0/" /"--cache/" /"{CWD}/cache/" /"--loglevel/" /"silly/" /"--color/" /"false/"", + "logfile logs-max:10 dir:{CWD}/cache/_logs/{DATE}-", + "logfile {CWD}/cache/_logs/{DATE}-debug-0.log", + "dummy stack trace", ] ` @@ -826,22 +781,10 @@ Object { exports[`test/lib/utils/error-message.js TAP eacces/eperm {"windows":true,"loaded":true,"cachePath":false,"cacheDest":false} > must match snapshot 2`] = ` Array [ - Array [ - "title", - "npm", - ], - Array [ - "argv", - "/"--fetch-retries/" /"0/" /"--cache/" /"{CWD}/cache/"", - ], - Array [ - "logfile", - "logs-max:10 dir:{CWD}/cache/_logs/{DATE}-", - ], - Array [ - "logfile", - "{CWD}/cache/_logs/{DATE}-debug-0.log", - ], + "title npm", + "argv /"--fetch-retries/" /"0/" /"--cache/" /"{CWD}/cache/" /"--loglevel/" /"silly/" /"--color/" /"false/"", + "logfile logs-max:10 dir:{CWD}/cache/_logs/{DATE}-", + "logfile {CWD}/cache/_logs/{DATE}-debug-0.log", ] ` @@ -877,22 +820,10 @@ Object { exports[`test/lib/utils/error-message.js TAP eacces/eperm {"windows":true,"loaded":true,"cachePath":false,"cacheDest":true} > must match snapshot 2`] = ` Array [ - Array [ - "title", - "npm", - ], - Array [ - "argv", - "/"--fetch-retries/" /"0/" /"--cache/" /"{CWD}/cache/"", - ], - Array [ - "logfile", - "logs-max:10 dir:{CWD}/cache/_logs/{DATE}-", - ], - Array [ - "logfile", - "{CWD}/cache/_logs/{DATE}-debug-0.log", - ], + "title npm", + "argv /"--fetch-retries/" /"0/" /"--cache/" /"{CWD}/cache/" /"--loglevel/" /"silly/" /"--color/" /"false/"", + "logfile logs-max:10 dir:{CWD}/cache/_logs/{DATE}-", + "logfile {CWD}/cache/_logs/{DATE}-debug-0.log", ] ` @@ -928,22 +859,10 @@ Object { exports[`test/lib/utils/error-message.js TAP eacces/eperm {"windows":true,"loaded":true,"cachePath":true,"cacheDest":false} > must match snapshot 2`] = ` Array [ - Array [ - "title", - "npm", - ], - Array [ - "argv", - "/"--fetch-retries/" /"0/" /"--cache/" /"{CWD}/cache/"", - ], - Array [ - "logfile", - "logs-max:10 dir:{CWD}/cache/_logs/{DATE}-", - ], - Array [ - "logfile", - "{CWD}/cache/_logs/{DATE}-debug-0.log", - ], + "title npm", + "argv /"--fetch-retries/" /"0/" /"--cache/" /"{CWD}/cache/" /"--loglevel/" /"silly/" /"--color/" /"false/"", + "logfile logs-max:10 dir:{CWD}/cache/_logs/{DATE}-", + "logfile {CWD}/cache/_logs/{DATE}-debug-0.log", ] ` @@ -979,22 +898,10 @@ Object { exports[`test/lib/utils/error-message.js TAP eacces/eperm {"windows":true,"loaded":true,"cachePath":true,"cacheDest":true} > must match snapshot 2`] = ` Array [ - Array [ - "title", - "npm", - ], - Array [ - "argv", - "/"--fetch-retries/" /"0/" /"--cache/" /"{CWD}/cache/"", - ], - Array [ - "logfile", - "logs-max:10 dir:{CWD}/cache/_logs/{DATE}-", - ], - Array [ - "logfile", - "{CWD}/cache/_logs/{DATE}-debug-0.log", - ], + "title npm", + "argv /"--fetch-retries/" /"0/" /"--cache/" /"{CWD}/cache/" /"--loglevel/" /"silly/" /"--color/" /"false/"", + "logfile logs-max:10 dir:{CWD}/cache/_logs/{DATE}-", + "logfile {CWD}/cache/_logs/{DATE}-debug-0.log", ] ` diff --git a/tap-snapshots/test/lib/utils/exit-handler.js.test.cjs b/tap-snapshots/test/lib/utils/exit-handler.js.test.cjs index 3e7bc4570dd4a..cfb3034b3b06a 100644 --- a/tap-snapshots/test/lib/utils/exit-handler.js.test.cjs +++ b/tap-snapshots/test/lib/utils/exit-handler.js.test.cjs @@ -12,7 +12,7 @@ XX timing npm:load:configload Completed in {TIME}ms XX timing npm:load:mkdirpcache Completed in {TIME}ms XX timing npm:load:mkdirplogs Completed in {TIME}ms XX verbose title npm -XX verbose argv "--fetch-retries" "0" "--cache" "{CWD}/cache" "--loglevel" "notice" +XX verbose argv "--fetch-retries" "0" "--cache" "{CWD}/cache" "--loglevel" "silly" "--color" "false" "--timing" "true" XX timing npm:load:setTitle Completed in {TIME}ms XX timing npm:load:display Completed in {TIME}ms XX verbose logfile logs-max:10 dir:{CWD}/cache/_logs/{DATE}- @@ -32,6 +32,7 @@ XX error ERR DETAIL Unknown error XX verbose exit 1 XX timing npm Completed in {TIME}ms XX verbose code 1 +XX error Timing info written to: {CWD}/cache/_logs/{DATE}-timing.json XX error A complete log of this run can be found in: {CWD}/cache/_logs/{DATE}-debug-0.log ` @@ -42,7 +43,7 @@ timing npm:load:configload Completed in {TIME}ms timing npm:load:mkdirpcache Completed in {TIME}ms timing npm:load:mkdirplogs Completed in {TIME}ms verbose title npm -verbose argv "--fetch-retries" "0" "--cache" "{CWD}/cache" "--loglevel" "notice" +verbose argv "--fetch-retries" "0" "--cache" "{CWD}/cache" "--loglevel" "silly" "--color" "false" "--timing" "true" timing npm:load:setTitle Completed in {TIME}ms timing npm:load:display Completed in {TIME}ms verbose logfile logs-max:10 dir:{CWD}/cache/_logs/{DATE}- @@ -53,7 +54,7 @@ timing npm:load:configScope Completed in {TIME}ms timing npm:load Completed in {TIME}ms verbose stack Error: Unknown error verbose cwd {CWD}/prefix -verbose Foo 1.0.0 +verbose Foo 1.0.0 verbose node v1.0.0 verbose npm v1.0.0 error code ECODE @@ -62,6 +63,6 @@ error ERR DETAIL Unknown error verbose exit 1 timing npm Completed in {TIME}ms verbose code 1 -error A complete log of this run can be found in: {CWD}/cache/_logs/{DATE}-debug-0.log -silly logfile done cleaning log files +error Timing info written to: {CWD}/cache/_logs/{DATE}-timing.json +error A complete log of this run can be found in: {CWD}/cache/_logs/{DATE}-debug-0.log ` diff --git a/tap-snapshots/test/lib/utils/open-url-prompt.js.test.cjs b/tap-snapshots/test/lib/utils/open-url-prompt.js.test.cjs index f31ec8e041f51..cf5feed44cc37 100644 --- a/tap-snapshots/test/lib/utils/open-url-prompt.js.test.cjs +++ b/tap-snapshots/test/lib/utils/open-url-prompt.js.test.cjs @@ -10,7 +10,6 @@ npm home: https://www.npmjs.com Browser unavailable. Please open the URL manually: https://www.npmjs.com - ` exports[`test/lib/utils/open-url-prompt.js TAP opens a url > must match snapshot 1`] = ` diff --git a/tap-snapshots/test/lib/utils/open-url.js.test.cjs b/tap-snapshots/test/lib/utils/open-url.js.test.cjs index 8c8159ebcfc04..f1560db686cde 100644 --- a/tap-snapshots/test/lib/utils/open-url.js.test.cjs +++ b/tap-snapshots/test/lib/utils/open-url.js.test.cjs @@ -8,7 +8,6 @@ exports[`test/lib/utils/open-url.js TAP prints where to go when browser is disabled > printed expected message 1`] = ` npm home: https://www.npmjs.com - ` exports[`test/lib/utils/open-url.js TAP prints where to go when browser is disabled and json is enabled > printed expected message 1`] = ` @@ -21,5 +20,4 @@ exports[`test/lib/utils/open-url.js TAP prints where to go when browser is disab exports[`test/lib/utils/open-url.js TAP prints where to go when given browser does not exist > printed expected message 1`] = ` npm home: https://www.npmjs.com - ` diff --git a/test/fixtures/mock-logs.js b/test/fixtures/mock-logs.js index c75de5e509463..3f25737ef4501 100644 --- a/test/fixtures/mock-logs.js +++ b/test/fixtures/mock-logs.js @@ -1,131 +1,106 @@ +const { LEVELS: PROC_LOC_LEVELS } = require('proc-log') +const { stripVTControlCharacters: stripAnsi } = require('util') -const NPMLOG = require('npmlog') -const { LEVELS } = require('proc-log') +const levels = ['timing', ...PROC_LOC_LEVELS] +const labels = new Map([ + ['error', 'ERR!'], + ['warn', 'WARN'], + ['verbose', 'verb'], + ['silly', 'sill'], +].reduce((acc, v) => acc.concat([v, v.slice(0).reverse()]), [])) +const logPrefix = new RegExp(`^npm (${levels.map(l => labels.get(l) ?? l).join('|')})\\s`) +const isLog = (str) => logPrefix.test(stripAnsi(str)) -const npmEmitLog = NPMLOG.emitLog.bind(NPMLOG) -const npmLog = NPMLOG.log.bind(NPMLOG) +// We only strip trailing newlines since some output will +// have significant tabs and spaces +const trimTrailingNewline = (str) => str.replace(/\n$/, '') -const merge = (...objs) => objs.reduce((acc, obj) => ({ ...acc, ...obj })) +const joinAndTrimTrailingNewlines = (arr) => + trimTrailingNewline(arr.map(trimTrailingNewline).join('\n')) -const mockLogs = (otherMocks = {}) => { - // Return mocks as an array with getters for each level - // that return an array of logged properties with the - // level removed. This is for convenience throughout tests - const logs = Object.defineProperties( - [], - ['timing', ...LEVELS].reduce((acc, level) => { - acc[level] = { - get () { - return this - .filter(([l]) => level === l) - .map(([l, ...args]) => args) - }, - } - return acc - }, {}) - ) +const logsByTitle = (logs) => ({ + byTitle: { + value: (title) => { + return logs + .filter((l) => stripAnsi(l.message).startsWith(`${title} `)) + .map((l) => l.message) + }, + }, +}) - // the above logs array is anything logged and it not filtered by level. - // this display array is filtered and will not include items that - // would not be shown in the terminal - const display = Object.defineProperties( - [], - ['timing', ...LEVELS].reduce((acc, level) => { +module.exports = () => { + const outputs = [] + const outputErrors = [] + + const levelLogs = [] + const logs = Object.defineProperties([], { + ...logsByTitle(levelLogs), + ...levels.reduce((acc, level) => { acc[level] = { get () { - return this - .filter(([l]) => level === l) - .map(([l, ...args]) => args) + const byLevel = levelLogs.filter((l) => l.level === level) + return Object.defineProperties(byLevel.map((l) => l.message), logsByTitle(byLevel)) }, } return acc - }, {}) - ) + }, {}), + }) - const npmLogBuffer = [] + const streams = { + stderr: { + write: (str) => { + str = trimTrailingNewline(str) - // This returns an object with mocked versions of all necessary - // logging modules. It mocks them with methods that add logs - // to an array which it also returns. The reason it also returns - // the mocks is that in tests the same instance of these mocks - // should be passed to multiple calls to t.mock. - // XXX: this is messy and fragile and should be removed in favor - // of some other way to collect and filter logs across all tests - const logMocks = { - 'proc-log': merge( - { LEVELS }, - LEVELS.reduce((acc, l) => { - acc[l] = (...args) => { - // Re-emit log item for since the log file listens on these - process.emit('log', l, ...args) - // Dont add pause/resume events to the logs. Those aren't displayed - // and emitting them is tested in the display layer - if (l !== 'pause' && l !== 'resume') { - logs.push([l, ...args]) - } + // Use the beginning of each line to determine if its a log + // or an output error since we write both of those to stderr. + // This couples logging format to this test but we only need + // to do it in a single place so hopefully its easy to change + // in the future if/when we refactor what logs look like. + if (!isLog(str)) { + outputErrors.push(str) + return } - return acc - }, {}), - otherMocks['proc-log'] - ), - // Object.assign is important here because we need to assign - // mocked properties directly to npmlog and then mock with that - // object. This is necessary so tests can still directly set - // `log.level = 'silent'` anywhere in the test and have that - // that reflected in the npmlog singleton. - // XXX: remove with npmlog - npmlog: Object.assign(NPMLOG, merge( - { - log: (level, ...args) => { - // timing does not exist on proclog, so if it got logged - // with npmlog we need to push it to our logs - if (level === 'timing') { - logs.push([level, ...args]) - } - npmLog(level, ...args) - }, - write: (msg) => { - // npmlog.write is what outputs to the terminal. - // it writes in chunks so we push each chunk to an - // array that we will log and zero out - npmLogBuffer.push(msg) - }, - emitLog: (m) => { - // this calls the original emitLog method - // which will filter based on loglevel - npmEmitLog(m) - // if anything was logged then we push to our display - // array which we can assert against in tests - if (npmLogBuffer.length) { - // first two parts are 'npm' and a single space - display.push(npmLogBuffer.slice(2)) - } - npmLogBuffer.length = 0 - }, - newItem: () => { - return { - info: (...p) => { - logs.push(['info', ...p]) - }, - warn: (...p) => { - logs.push(['warn', ...p]) - }, - error: (...p) => { - logs.push(['error', ...p]) - }, - silly: (...p) => { - logs.push(['silly', ...p]) - }, - completeWork: () => {}, - finish: () => {}, - } - }, + + // Split on spaces for the heading and level/label. We know that + // none of those have spaces but could be colorized so there's no + // other good way to get each of those including control chars + const [rawHeading, rawLabel] = str.split(' ') + const rawPrefix = `${rawHeading} ${rawLabel} ` + // If message is colorized we can just replaceAll with the string since + // it will be unique due to control chars. Otherwise we create a regex + // that will only match the beginning of each line. + const prefix = stripAnsi(str) !== str ? rawPrefix : new RegExp(`^${rawPrefix}`, 'gm') + + // The level needs color stripped always because we use it to filter logs + const level = labels.get(stripAnsi(rawLabel)) ?? stripAnsi(rawLabel) + + logs.push(str.replaceAll(prefix, `${level} `)) + levelLogs.push({ level, message: str.replaceAll(prefix, '') }) + }, + }, + stdout: { + write: (str) => { + outputs.push(trimTrailingNewline(str)) }, - otherMocks.npmlog - )), + }, } - return { logs, logMocks, display } + return { + streams, + logs: { + outputs, + joinedOutput: () => joinAndTrimTrailingNewlines(outputs), + clearOutput: () => { + outputs.length = 0 + outputErrors.length = 0 + }, + outputErrors, + joinedOutputError: () => joinAndTrimTrailingNewlines(outputs), + logs, + clearLogs: () => { + levelLogs.length = 0 + logs.length = 0 + }, + }, + } } - -module.exports = mockLogs diff --git a/test/fixtures/mock-npm.js b/test/fixtures/mock-npm.js index 4646e79146e86..6bb3123d2b091 100644 --- a/test/fixtures/mock-npm.js +++ b/test/fixtures/mock-npm.js @@ -3,7 +3,7 @@ const fs = require('fs').promises const path = require('path') const tap = require('tap') const errorMessage = require('../../lib/utils/error-message') -const mockLogs = require('./mock-logs') +const mockLogs = require('./mock-logs.js') const mockGlobals = require('@npmcli/mock-globals') const tmock = require('./tmock') const defExitCode = process.exitCode @@ -63,14 +63,19 @@ const buildMocks = (t, mocks) => { } const getMockNpm = async (t, { mocks, init, load, npm: npmOpts }) => { - const { logMocks, logs, display } = mockLogs(mocks) - const allMocks = buildMocks(t, { ...mocks, ...logMocks }) + const { streams, logs } = mockLogs() + const allMocks = buildMocks(t, mocks) const Npm = tmock(t, '{LIB}/npm.js', allMocks) - const outputs = [] - const outputErrors = [] - class MockNpm extends Npm { + constructor (opts) { + super({ + ...opts, + ...streams, + ...npmOpts, + }) + } + async exec (...args) { const [res, err] = await super.exec(...args).then((r) => [r]).catch(e => [null, e]) // This mimics how the exit handler flushes output for commands that have @@ -84,26 +89,9 @@ const getMockNpm = async (t, { mocks, init, load, npm: npmOpts }) => { } return res } - - // lib/npm.js tests needs this to actually test the function! - originalOutput (...args) { - super.output(...args) - } - - originalOutputError (...args) { - super.outputError(...args) - } - - output (...args) { - outputs.push(args) - } - - outputError (...args) { - outputErrors.push(args) - } } - const npm = init ? new MockNpm(npmOpts) : null + const npm = init ? new MockNpm() : null if (npm && load) { await npm.load() } @@ -111,12 +99,7 @@ const getMockNpm = async (t, { mocks, init, load, npm: npmOpts }) => { return { Npm: MockNpm, npm, - outputs, - outputErrors, - joinedOutput: () => outputs.map(o => o.join(' ')).join('\n'), - logMocks, - logs, - display, + ...logs, } } @@ -142,7 +125,6 @@ const setupMockNpm = async (t, { globals = {}, npm: npmOpts = {}, argv: rawArgv = [], - ...r } = {}) => { // easy to accidentally forget to pass in tap if (!(t instanceof tap.Test)) { @@ -213,6 +195,11 @@ const setupMockNpm = async (t, { // explicitly set in a test. 'fetch-retries': 0, cache: dirs.cache, + // This will give us all the loglevels including timing in a non-colorized way + // so we can easily assert their contents. Individual tests can overwrite these + // with my passing in configs if they need to test other forms of output. + loglevel: 'silly', + color: false, } const { argv, env, config } = Object.entries({ ...defaultConfigs, ...withDirs(_config) }) @@ -221,11 +208,13 @@ const setupMockNpm = async (t, { // and quoted with `"` so mock globals will ignore that it contains dots if (key.startsWith('//')) { acc.env[`process.env."npm_config_${key}"`] = value - } else { + } else if (value !== undefined) { const values = [].concat(value) - acc.argv.push(...values.flatMap(v => `--${key}=${v.toString()}`)) + acc.argv.push(...values.flatMap(v => v === '' ? `--${key}` : `--${key}=${v.toString()}`)) + } + if (value !== undefined) { + acc.config[key] = value } - acc.config[key] = value return acc }, { argv: [...rawArgv], env: {}, config: {} }) diff --git a/test/fixtures/sandbox.js b/test/fixtures/sandbox.js deleted file mode 100644 index 5be02fcf80c1e..0000000000000 --- a/test/fixtures/sandbox.js +++ /dev/null @@ -1,336 +0,0 @@ -const { createHook, executionAsyncId } = require('async_hooks') -const { EventEmitter } = require('events') -const { homedir, tmpdir } = require('os') -const { dirname, join } = require('path') -const { mkdir, rm } = require('fs/promises') -const mockLogs = require('./mock-logs') -const pkg = require('../../package.json') - -const chain = new Map() -const sandboxes = new Map() - -// keep a reference to the real process -const _process = process - -createHook({ - init: (asyncId, type, triggerAsyncId, resource) => { - // track parentage of asyncIds - chain.set(asyncId, triggerAsyncId) - }, - before: (asyncId) => { - // find the nearest parent id that has a sandbox - let parent = asyncId - while (chain.has(parent) && !sandboxes.has(parent)) { - parent = chain.get(parent) - } - - process = sandboxes.has(parent) - ? sandboxes.get(parent) - : _process - }, -}).enable() - -const _data = Symbol('sandbox.data') -const _dirs = Symbol('sandbox.dirs') -const _test = Symbol('sandbox.test') -const _mocks = Symbol('sandbox.mocks') -const _npm = Symbol('sandbox.npm') -const _parent = Symbol('sandbox.parent') -const _output = Symbol('sandbox.output') -const _proxy = Symbol('sandbox.proxy') -const _get = Symbol('sandbox.proxy.get') -const _set = Symbol('sandbox.proxy.set') -const _logs = Symbol('sandbox.logs') - -// we can't just replace these values everywhere because they're known to be -// very short strings that could be present all over the place, so we only -// replace them if they're located within quotes for now -const vagueRedactedDefaults = [ - 'editor', - 'shell', -] - -const normalize = (str) => str - .replace(/\r\n/g, '\n') // normalize line endings (for ini) - .replace(/[A-z]:\\/g, '\\') // turn windows roots to posix ones - .replace(/\\+/g, '/') // replace \ with / - -class Sandbox extends EventEmitter { - constructor (test, options = {}) { - super() - - this[_test] = test - this[_mocks] = options.mocks || {} - this[_data] = new Map() - this[_output] = [] - const tempDir = `${test.testdirName}-sandbox` - this[_dirs] = { - temp: tempDir, - global: options.global || join(tempDir, 'global'), - home: options.home || join(tempDir, 'home'), - project: options.project || join(tempDir, 'project'), - cache: options.cache || join(tempDir, 'cache'), - } - - this[_proxy] = new Proxy(_process, { - get: this[_get].bind(this), - set: this[_set].bind(this), - }) - this[_proxy].env = { ...options.env } - this[_proxy].argv = [] - - test.cleanSnapshot = this.cleanSnapshot.bind(this) - test.afterEach(() => this.reset()) - test.teardown(() => this.teardown()) - } - - get config () { - return this[_npm] && this[_npm].config - } - - get logs () { - return this[_logs] - } - - get global () { - return this[_dirs].global - } - - get home () { - return this[_dirs].home - } - - get project () { - return this[_dirs].project - } - - get cache () { - return this[_dirs].cache - } - - get process () { - return this[_proxy] - } - - get output () { - return this[_output].map((line) => line.join(' ')).join('\n') - } - - cleanSnapshot (snapshot) { - let clean = normalize(snapshot) - - const viewer = _process.platform === 'win32' - ? /"browser"([^:]+|$)/g - : /"man"([^:]+|$)/g - - // the global prefix is platform dependent - const realGlobalPrefix = _process.platform === 'win32' - ? dirname(_process.execPath) - : dirname(dirname(_process.execPath)) - - const cache = _process.platform === 'win32' - ? /\{HOME\}\/npm-cache(\r?\n|"|\/|$)/g - : /\{HOME\}\/\.npm(\n|"|\/|$)/g - - // and finally replace some paths we know could be present - clean = clean - .replace(viewer, '"{VIEWER}"$1') - .split(normalize(this[_proxy].execPath)).join('{EXECPATH}') - .split(normalize(_process.execPath)).join('{REALEXECPATH}') - .split(normalize(this.global)).join('{GLOBALPREFIX}') - .split(normalize(realGlobalPrefix)).join('{REALGLOBALREFIX}') - .split(normalize(this.project)).join('{LOCALPREFIX}') - .split(normalize(this.home)).join('{HOME}') - .replace(cache, '{CACHE}$1') - .split(normalize(dirname(dirname(__dirname)))).join('{NPMDIR}') - .split(normalize(tmpdir())).join('{TMP}') - .split(normalize(homedir())).join('{REALHOME}') - .split(this[_proxy].platform).join('{PLATFORM}') - .split(this[_proxy].arch).join('{ARCH}') - .replace(new RegExp(process.version, 'g'), '{NODE-VERSION}') - .replace(new RegExp(pkg.version, 'g'), '{NPM-VERSION}') - - // We do the defaults after everything else so that they don't cause the - // other cleaners to miss values we would have clobbered here. For - // instance if execPath is /home/user/.nvm/versions/node/1.0.0/bin/node, - // and we replaced the node version first, the real execPath we're trying - // to replace would no longer be represented, and be missed. - if (this[_npm]) { - // replace vague default config values that are present within quotes - // with placeholders - for (const name of vagueRedactedDefaults) { - const value = this[_npm].config.defaults[name] - clean = clean.split(`"${normalize(value)}"`).join(`"{${name.toUpperCase()}}"`) - } - } - - return clean - } - - // test.afterEach hook - reset () { - this.removeAllListeners() - this[_parent] = undefined - this[_output] = [] - this[_data].clear() - this[_proxy].env = {} - this[_proxy].argv = [] - this[_npm] = undefined - } - - // test.teardown hook - teardown () { - if (this[_parent]) { - const sandboxProcess = sandboxes.get(this[_parent]) - sandboxProcess.removeAllListeners('log') - sandboxes.delete(this[_parent]) - } - if (this[_npm]) { - this[_npm].unload() - } - return rm(this[_dirs].temp, { recursive: true, force: true }).catch(() => null) - } - - // proxy get handler - [_get] (target, prop, receiver) { - if (this[_data].has(prop)) { - return this[_data].get(prop) - } - - if (this[prop] !== undefined) { - return Reflect.get(this, prop, this) - } - - return Reflect.get(target, prop, receiver) - } - - // proxy set handler - [_set] (target, prop, value) { - if (prop === 'env') { - value = { - ...value, - HOME: this.home, - } - } - - if (prop === 'argv') { - value = [ - process.execPath, - join(dirname(process.execPath), 'npm'), - ...value, - ] - } - - return this[_data].set(prop, value) - } - - async run (command, argv = []) { - await Promise.all([ - mkdir(this.project, { recursive: true }), - mkdir(this.home, { recursive: true }), - mkdir(this.global, { recursive: true }), - ]) - - // attach the sandbox process now, doing it after the promise above is - // necessary to make sure that only async calls spawned as part of this - // call to run will receive the sandbox. if we attach it too early, we - // end up interfering with tap - this[_parent] = executionAsyncId() - this[_data].set('_asyncId', this[_parent]) - sandboxes.set(this[_parent], this[_proxy]) - process = this[_proxy] - - this[_proxy].argv = [ - '--prefix', this.project, - '--userconfig', join(this.home, '.npmrc'), - '--globalconfig', join(this.global, 'npmrc'), - '--cache', this.cache, - command, - ...argv, - ] - - const mockedLogs = mockLogs(this[_mocks]) - this[_logs] = mockedLogs.logs - const definitions = this[_test].mock('@npmcli/config/lib/definitions') - const Npm = this[_test].mock('../../lib/npm.js', { - '@npmcli/config/lib/definitions': definitions, - '../../lib/utils/update-notifier.js': async () => {}, - ...this[_mocks], - ...mockedLogs.logMocks, - }) - this.process.on('log', (l, ...args) => { - if (l !== 'pause' && l !== 'resume') { - this[_logs].push([l, ...args]) - } - }) - - this[_npm] = new Npm() - this[_npm].output = (...args) => this[_output].push(args) - await this[_npm].load() - - const cmd = this[_npm].argv.shift() - return this[_npm].exec(cmd, this[_npm].argv) - } - - async complete (command, argv, partial) { - if (!Array.isArray(argv)) { - partial = argv - argv = [] - } - - await Promise.all([ - mkdir(this.project, { recursive: true }), - mkdir(this.home, { recursive: true }), - mkdir(this.global, { recursive: true }), - ]) - - // attach the sandbox process now, doing it after the promise above is - // necessary to make sure that only async calls spawned as part of this - // call to run will receive the sandbox. if we attach it too early, we - // end up interfering with tap - this[_parent] = executionAsyncId() - this[_data].set('_asyncId', this[_parent]) - sandboxes.set(this[_parent], this[_proxy]) - process = this[_proxy] - - this[_proxy].argv = [ - '--prefix', this.project, - '--userconfig', join(this.home, '.npmrc'), - '--globalconfig', join(this.global, 'npmrc'), - '--cache', this.cache, - command, - ...argv, - ] - - const mockedLogs = mockLogs(this[_mocks]) - this[_logs] = mockedLogs.logs - const definitions = this[_test].mock('@npmcli/config/lib/definitions') - const Npm = this[_test].mock('../../lib/npm.js', { - '@npmcli/config/lib/definitions': definitions, - '../../lib/utils/update-notifier.js': async () => {}, - ...this[_mocks], - ...mockedLogs.logMocks, - }) - this.process.on('log', (l, ...args) => { - if (l !== 'pause' && l !== 'resume') { - this[_logs].push([l, ...args]) - } - }) - - this[_npm] = new Npm() - this[_npm].output = (...args) => this[_output].push(args) - await this[_npm].load() - - const Cmd = Npm.cmd(command) - return Cmd.completion({ - partialWord: partial, - conf: { - argv: { - remain: ['npm', command, ...argv], - }, - }, - }) - } -} - -module.exports = Sandbox diff --git a/test/lib/arborist-cmd.js b/test/lib/arborist-cmd.js index 44afe9763f620..79ff8c6c24601 100644 --- a/test/lib/arborist-cmd.js +++ b/test/lib/arborist-cmd.js @@ -212,7 +212,7 @@ t.test('location detection and audit', async (t) => { }) t.equal(npm.config.get('location'), 'user') t.equal(npm.config.get('audit'), true) - t.equal(logs.warn[0][0], 'config') - t.equal(logs.warn[0][1], 'includes both --global and --audit, which is currently unsupported.') + t.equal(logs.warn[0], + 'config includes both --global and --audit, which is currently unsupported.') }) }) diff --git a/test/lib/cli-entry.js b/test/lib/cli-entry.js index 22dca32f1a934..3a8d3321c4b64 100644 --- a/test/lib/cli-entry.js +++ b/test/lib/cli-entry.js @@ -12,62 +12,59 @@ const cliMock = async (t, opts) => { } exitHandlerMock.setNpm = _npm => npm = _npm - const { Npm, outputs, logMocks, logs } = await loadMockNpm(t, { ...opts, init: false }) + const { Npm, ...mock } = await loadMockNpm(t, { ...opts, init: false }) const cli = tmock(t, '{LIB}/cli-entry.js', { '{LIB}/npm.js': Npm, '{LIB}/utils/exit-handler.js': exitHandlerMock, - ...logMocks, }) return { + ...mock, Npm, cli: (p) => validateEngines(p, () => cli), - outputs, exitHandlerCalled: () => exitHandlerArgs, exitHandlerNpm: () => npm, - logs, - logsBy: (title) => logs.verbose.filter(([p]) => p === title).map(([p, ...rest]) => rest), } } t.test('print the version, and treat npm_g as npm -g', async t => { - const { logsBy, logs, cli, Npm, outputs, exitHandlerCalled } = await cliMock(t, { + const { logs, cli, Npm, outputs, exitHandlerCalled } = await cliMock(t, { globals: { 'process.argv': ['node', 'npm_g', '-v'] }, }) await cli(process) t.strictSame(process.argv, ['node', 'npm', '-g', '-v'], 'system process.argv was rewritten') - t.strictSame(logsBy('cli'), [['node npm']]) - t.strictSame(logsBy('title'), [['npm']]) - t.match(logsBy('argv'), [['"--global" "--version"']]) + t.strictSame(logs.verbose.byTitle('cli'), ['cli node npm']) + t.strictSame(logs.verbose.byTitle('title'), ['title npm']) + t.match(logs.verbose.byTitle('argv'), ['argv "--global" "--version"']) t.strictSame(logs.info, [ - ['using', 'npm@%s', Npm.version], - ['using', 'node@%s', process.version], + `using npm@${Npm.version}`, + `using node@${process.version}`, ]) t.equal(outputs.length, 1) - t.strictSame(outputs, [[Npm.version]]) + t.strictSame(outputs, [Npm.version]) t.strictSame(exitHandlerCalled(), []) }) t.test('calling with --versions calls npm version with no args', async t => { - const { logsBy, cli, outputs, exitHandlerCalled } = await cliMock(t, { + const { logs, cli, outputs, exitHandlerCalled } = await cliMock(t, { globals: { - 'process.argv': ['node', 'npm', 'install', 'or', 'whatever', '--versions'], + 'process.argv': ['node', 'npm', 'install', 'or', 'whatever', '--versions', '--json'], }, }) await cli(process) t.equal(process.title, 'npm install or whatever') - t.strictSame(logsBy('cli'), [['node npm']]) - t.strictSame(logsBy('title'), [['npm install or whatever']]) - t.match(logsBy('argv'), [['"install" "or" "whatever" "--versions"']]) + t.strictSame(logs.verbose.byTitle('cli'), ['cli node npm']) + t.strictSame(logs.verbose.byTitle('title'), ['title npm install or whatever']) + t.match(logs.verbose.byTitle('argv'), ['argv "install" "or" "whatever" "--versions"']) t.equal(outputs.length, 1) - t.match(outputs[0][0], { npm: String, node: String, v8: String }) + t.match(JSON.parse(outputs[0]), { npm: String, node: String, v8: String }) t.strictSame(exitHandlerCalled(), []) }) t.test('logged argv is sanitized', async t => { - const { logsBy, cli } = await cliMock(t, { + const { logs, cli } = await cliMock(t, { globals: { 'process.argv': [ 'node', @@ -81,13 +78,14 @@ t.test('logged argv is sanitized', async t => { await cli(process) t.equal(process.title, 'npm version') - t.strictSame(logsBy('cli'), [['node npm']]) - t.strictSame(logsBy('title'), [['npm version']]) - t.match(logsBy('argv'), [['"version" "--registry" "https://u:***@npmjs.org/password"']]) + t.strictSame(logs.verbose.byTitle('cli'), ['cli node npm']) + t.strictSame(logs.verbose.byTitle('title'), ['title npm version']) + t.match(logs.verbose.byTitle('argv'), + ['argv "version" "--registry" "https://u:***@npmjs.org/password"']) }) t.test('logged argv is sanitized with equals', async t => { - const { logsBy, cli } = await cliMock(t, { + const { logs, cli } = await cliMock(t, { globals: { 'process.argv': [ 'node', @@ -99,7 +97,7 @@ t.test('logged argv is sanitized with equals', async t => { }) await cli(process) - t.match(logsBy('argv'), [['"version" "--registry" "https://u:***@npmjs.org/"']]) + t.match(logs.verbose.byTitle('argv'), ['argv "version" "--registry" "https://u:***@npmjs.org/"']) }) t.test('print usage if no params provided', async t => { @@ -110,7 +108,7 @@ t.test('print usage if no params provided', async t => { }) await cli(process) - t.match(outputs[0][0], 'Usage:', 'outputs npm usage') + t.match(outputs[0], 'Usage:', 'outputs npm usage') t.match(exitHandlerCalled(), [], 'should call exitHandler with no args') t.ok(exitHandlerNpm(), 'exitHandler npm is set') t.match(process.exitCode, 1) @@ -124,8 +122,8 @@ t.test('print usage if non-command param provided', async t => { }) await cli(process) - t.match(outputs[0][0], 'Unknown command: "tset"') - t.match(outputs[0][0], 'Did you mean this?') + t.match(outputs[0], 'Unknown command: "tset"') + t.match(outputs[0], 'Did you mean this?') t.match(exitHandlerCalled(), [], 'should call exitHandler with no args') t.ok(exitHandlerNpm(), 'exitHandler npm is set') t.match(process.exitCode, 1) @@ -157,7 +155,7 @@ t.test('unsupported node version', async t => { }) await cli(process) t.match( - logs.warn[0][1], + logs.warn[0], /npm v.* does not support Node\.js 12\.6\.0\./ ) }) diff --git a/test/lib/commands/access.js b/test/lib/commands/access.js index 7aec33701297c..96f1bcd074282 100644 --- a/test/lib/commands/access.js +++ b/test/lib/commands/access.js @@ -130,8 +130,8 @@ t.test('list', t => { registry.getPackages({ team: '@npm:test-team', packages }) await npm.exec('access', ['list', 'packages', '@npm:test-team']) t.same(outputs, [ - ['@npmcli/other-package: read-write'], - ['@npmcli/test-package: read-only'], + '@npmcli/other-package: read-write', + '@npmcli/test-package: read-only', ]) }) @@ -146,8 +146,8 @@ t.test('list', t => { registry.getPackages({ team: 'npm', packages }) await npm.exec('access', ['list', 'packages']) t.same(outputs, [ - ['@npmcli/other-package: read-write'], - ['@npmcli/test-package: read-only'], + '@npmcli/other-package: read-write', + '@npmcli/test-package: read-only', ]) }) @@ -174,8 +174,8 @@ t.test('list', t => { registry.getCollaborators({ spec: '@npmcli/test-package', collaborators }) await npm.exec('access', ['list', 'collaborators', '@npmcli/test-package']) t.same(outputs, [ - ['github: read-only'], - ['npm: read-write'], + 'github: read-only', + 'npm: read-write', ]) }) @@ -188,7 +188,7 @@ t.test('list', t => { registry.getCollaborators({ spec: '@npmcli/test-package', collaborators }) await npm.exec('access', ['list', 'collaborators', '@npmcli/test-package', 'npm']) t.same(outputs, [ - ['npm: read-write'], + 'npm: read-write', ]) }) t.end() @@ -208,7 +208,7 @@ t.test('get', t => { }) registry.getVisibility({ spec: '@npmcli/test-package', visibility: { public: true } }) await npm.exec('access', ['get', 'status', '@npmcli/test-package']) - t.same(outputs, [['@npmcli/test-package: public']]) + t.same(outputs, ['@npmcli/test-package: public']) }) t.test('status implicit package', async t => { const { npm, outputs } = await loadMockNpm(t, { @@ -222,7 +222,7 @@ t.test('get', t => { }) registry.getVisibility({ spec: '@npmcli/test-package', visibility: { public: true } }) await npm.exec('access', ['get', 'status']) - t.same(outputs, [['@npmcli/test-package: public']]) + t.same(outputs, ['@npmcli/test-package: public']) }) t.test('status no package', async t => { const { npm } = await loadMockNpm(t) @@ -263,7 +263,7 @@ t.test('set', t => { registry.setAccess({ spec: '@npmcli/test-package', body: { access: 'public' } }) registry.getVisibility({ spec: '@npmcli/test-package', visibility: { public: true } }) await npm.exec('access', ['set', 'status=public', '@npmcli/test-package']) - t.same(outputs, [['@npmcli/test-package: public']]) + t.same(outputs, ['@npmcli/test-package: public']) }) t.test('status=private', async t => { const { npm, outputs } = await loadMockNpm(t) @@ -274,7 +274,7 @@ t.test('set', t => { registry.setAccess({ spec: '@npmcli/test-package', body: { access: 'restricted' } }) registry.getVisibility({ spec: '@npmcli/test-package', visibility: { public: false } }) await npm.exec('access', ['set', 'status=private', '@npmcli/test-package']) - t.same(outputs, [['@npmcli/test-package: private']]) + t.same(outputs, ['@npmcli/test-package: private']) }) t.test('status=invalid', async t => { const { npm } = await loadMockNpm(t) diff --git a/test/lib/commands/config.js b/test/lib/commands/config.js index b54096fd216f2..0806326e2e8e4 100644 --- a/test/lib/commands/config.js +++ b/test/lib/commands/config.js @@ -3,16 +3,49 @@ const fs = require('fs/promises') const ini = require('ini') const tspawk = require('../../fixtures/tspawk') const t = require('tap') +const { load: _loadMockNpm } = require('../../fixtures/mock-npm') +const { cleanCwd } = require('../../fixtures/clean-snapshot.js') const spawk = tspawk(t) -const Sandbox = require('../../fixtures/sandbox.js') +const replaceJsonOrIni = (key) => [ + new RegExp(`(\\s(?:${key} = |"${key}": )"?)[^"\\n,]+`, 'g'), + `$1{${key.toUpperCase()}}`, +] + +const replaceIniComment = (key) => [ + new RegExp(`(; ${key} = ).*`, 'g'), + `$1{${key.replaceAll(' ', '-').toUpperCase()}}`, +] + +t.cleanSnapshot = (s) => cleanCwd(s) + .replaceAll(...replaceIniComment('node version')) + .replaceAll(...replaceIniComment('npm version')) + .replaceAll(...replaceIniComment('node bin location')) + .replaceAll(...replaceJsonOrIni('npm-version')) + .replaceAll(...replaceJsonOrIni('viewer')) + .replaceAll(...replaceJsonOrIni('shell')) + .replaceAll(...replaceJsonOrIni('editor')) + .replaceAll(...replaceJsonOrIni('progress')) + .replaceAll(...replaceJsonOrIni('color')) + .replaceAll(...replaceJsonOrIni('cache')) + +const loadMockNpm = (t, opts = {}) => _loadMockNpm(t, { + ...opts, + config: { + ...opts.config, + // Reset configs that mock npm sets by default + 'fetch-retries': undefined, + loglevel: undefined, + color: undefined, + }, +}) t.test('config no args', async t => { - const sandbox = new Sandbox(t) + const { npm } = await loadMockNpm(t) await t.rejects( - sandbox.run('config', []), + npm.exec('config', []), { code: 'EUSAGE', }, @@ -21,10 +54,14 @@ t.test('config no args', async t => { }) t.test('config ignores workspaces', async t => { - const sandbox = new Sandbox(t) + const { npm } = await loadMockNpm(t, { + config: { + workspaces: true, + }, + }) await t.rejects( - sandbox.run('config', ['--workspaces']), + npm.exec('config'), { code: 'ENOWORKSPACES', }, @@ -33,74 +70,92 @@ t.test('config ignores workspaces', async t => { }) t.test('config list', async t => { - const temp = t.testdir({ - global: { - npmrc: 'globalloaded=yes', - }, - project: { + const { npm, joinedOutput } = await loadMockNpm(t, { + prefixDir: { '.npmrc': 'projectloaded=yes', }, - home: { + globalPrefixDir: { + etc: { + npmrc: 'globalloaded=yes', + }, + }, + homeDir: { '.npmrc': 'userloaded=yes', }, }) - const global = join(temp, 'global') - const project = join(temp, 'project') - const home = join(temp, 'home') - const sandbox = new Sandbox(t, { global, project, home }) - await sandbox.run('config', ['list']) + await npm.exec('config', ['list']) + + const output = joinedOutput() + + t.match(output, 'projectloaded = "yes"') + t.match(output, 'globalloaded = "yes"') + t.match(output, 'userloaded = "yes"') - t.matchSnapshot(sandbox.output, 'output matches snapshot') + t.matchSnapshot(output, 'output matches snapshot') }) t.test('config list --long', async t => { - const temp = t.testdir({ - global: { - npmrc: 'globalloaded=yes', - }, - project: { + const { npm, joinedOutput } = await loadMockNpm(t, { + prefixDir: { '.npmrc': 'projectloaded=yes', }, - home: { + globalPrefixDir: { + etc: { + npmrc: 'globalloaded=yes', + }, + }, + homeDir: { '.npmrc': 'userloaded=yes', }, + config: { + long: true, + }, }) - const global = join(temp, 'global') - const project = join(temp, 'project') - const home = join(temp, 'home') - const sandbox = new Sandbox(t, { global, project, home }) - await sandbox.run('config', ['list', '--long']) + await npm.exec('config', ['list']) + + const output = joinedOutput() - t.matchSnapshot(sandbox.output, 'output matches snapshot') + t.match(output, 'projectloaded = "yes"') + t.match(output, 'globalloaded = "yes"') + t.match(output, 'userloaded = "yes"') + + t.matchSnapshot(output, 'output matches snapshot') }) t.test('config list --json', async t => { - const temp = t.testdir({ - global: { - npmrc: 'globalloaded=yes', - }, - project: { + const { npm, joinedOutput } = await loadMockNpm(t, { + prefixDir: { '.npmrc': 'projectloaded=yes', }, - home: { + globalPrefixDir: { + etc: { + npmrc: 'globalloaded=yes', + }, + }, + homeDir: { '.npmrc': 'userloaded=yes', }, + config: { + json: true, + }, }) - const global = join(temp, 'global') - const project = join(temp, 'project') - const home = join(temp, 'home') - const sandbox = new Sandbox(t, { global, project, home }) - await sandbox.run('config', ['list', '--json']) + await npm.exec('config', ['list']) + + const output = joinedOutput() + + t.match(output, '"projectloaded": "yes",') + t.match(output, '"globalloaded": "yes",') + t.match(output, '"userloaded": "yes",') - t.matchSnapshot(sandbox.output, 'output matches snapshot') + t.matchSnapshot(output, 'output matches snapshot') }) t.test('config list with publishConfig', async t => { - const temp = t.testdir({ - project: { + const loadMockNpmWithPublishConfig = (t, opts) => loadMockNpm(t, { + prefixDir: { 'package.json': JSON.stringify({ publishConfig: { registry: 'https://some.registry', @@ -108,21 +163,43 @@ t.test('config list with publishConfig', async t => { }, }), }, + ...opts, }) - const project = join(temp, 'project') - const sandbox = new Sandbox(t, { project }) - await sandbox.run('config', ['list', '']) - await sandbox.run('config', ['list', '--global']) + t.test('local', async t => { + const { npm, joinedOutput } = await loadMockNpmWithPublishConfig(t) - t.matchSnapshot(sandbox.output, 'output matches snapshot') + await npm.exec('config', ['list']) + + const output = joinedOutput() + + t.match(output, 'registry = "https://some.registry"') + + t.matchSnapshot(output, 'output matches snapshot') + }) + + t.test('global', async t => { + const { npm, joinedOutput } = await loadMockNpmWithPublishConfig(t, { + config: { + global: true, + }, + }) + + await npm.exec('config', ['list']) + + const output = joinedOutput() + + t.notMatch(output, 'registry = "https://some.registry"') + + t.matchSnapshot(output, 'output matches snapshot') + }) }) t.test('config delete no args', async t => { - const sandbox = new Sandbox(t) + const { npm } = await loadMockNpm(t) await t.rejects( - sandbox.run('config', ['delete']), + npm.exec('config', ['delete']), { code: 'EUSAGE', }, @@ -132,14 +209,15 @@ t.test('config delete no args', async t => { t.test('config delete single key', async t => { // location defaults to user, so we work with a userconfig - const home = t.testdir({ - '.npmrc': 'access=public\nall=true', + const { npm, home } = await loadMockNpm(t, { + homeDir: { + '.npmrc': 'access=public\nall=true', + }, }) - const sandbox = new Sandbox(t, { home }) - await sandbox.run('config', ['delete', 'access']) + await npm.exec('config', ['delete', 'access']) - t.equal(sandbox.config.get('access'), null, 'acces should be defaulted') + t.equal(npm.config.get('access'), null, 'acces should be defaulted') const contents = await fs.readFile(join(home, '.npmrc'), { encoding: 'utf8' }) const rc = ini.parse(contents) @@ -147,15 +225,16 @@ t.test('config delete single key', async t => { }) t.test('config delete multiple keys', async t => { - const home = t.testdir({ - '.npmrc': 'access=public\nall=true\naudit=false', + const { npm, home } = await loadMockNpm(t, { + homeDir: { + '.npmrc': 'access=public\nall=true\naudit=false', + }, }) - const sandbox = new Sandbox(t, { home }) - await sandbox.run('config', ['delete', 'access', 'all']) + await npm.exec('config', ['delete', 'access', 'all']) - t.equal(sandbox.config.get('access'), null, 'access should be defaulted') - t.equal(sandbox.config.get('all'), false, 'all should be defaulted') + t.equal(npm.config.get('access'), null, 'access should be defaulted') + t.equal(npm.config.get('all'), false, 'all should be defaulted') const contents = await fs.readFile(join(home, '.npmrc'), { encoding: 'utf8' }) const rc = ini.parse(contents) @@ -164,76 +243,87 @@ t.test('config delete multiple keys', async t => { }) t.test('config delete key --location=global', async t => { - const global = t.testdir({ - npmrc: 'access=public\nall=true', + const { npm, globalPrefix } = await loadMockNpm(t, { + globalPrefixDir: { + etc: { + npmrc: 'access=public\nall=true', + }, + }, + config: { + location: 'global', + }, }) + await npm.exec('config', ['delete', 'access']) - const sandbox = new Sandbox(t, { global }) - await sandbox.run('config', ['delete', 'access', '--location=global']) + t.equal(npm.config.get('access', 'global'), undefined, 'access should be defaulted') - t.equal(sandbox.config.get('access', 'global'), undefined, 'access should be defaulted') - - const contents = await fs.readFile(join(global, 'npmrc'), { encoding: 'utf8' }) + const contents = await fs.readFile(join(globalPrefix, 'etc/npmrc'), { encoding: 'utf8' }) const rc = ini.parse(contents) t.not(rc.access, 'access is not set') }) t.test('config delete key --global', async t => { - const global = t.testdir({ - npmrc: 'access=public\nall=true', + const { npm, globalPrefix } = await loadMockNpm(t, { + globalPrefixDir: { + etc: { + npmrc: 'access=public\nall=true', + }, + }, + config: { + global: true, + }, }) - const sandbox = new Sandbox(t, { global }) - await sandbox.run('config', ['delete', 'access', '--global']) + await npm.exec('config', ['delete', 'access']) - t.equal(sandbox.config.get('access', 'global'), undefined, 'access should no longer be set') + t.equal(npm.config.get('access', 'global'), undefined, 'access should no longer be set') - const contents = await fs.readFile(join(global, 'npmrc'), { encoding: 'utf8' }) + const contents = await fs.readFile(join(globalPrefix, 'etc/npmrc'), { encoding: 'utf8' }) const rc = ini.parse(contents) t.not(rc.access, 'access is not set') }) t.test('config set invalid option', async t => { - const sandbox = new Sandbox(t) + const { npm } = await loadMockNpm(t) await t.rejects( - sandbox.run('config', ['set', 'nonexistantconfigoption', 'something']), + npm.exec('config', ['set', 'nonexistantconfigoption', 'something']), /not a valid npm option/ ) }) t.test('config set deprecated option', async t => { - const sandbox = new Sandbox(t) + const { npm } = await loadMockNpm(t) await t.rejects( - sandbox.run('config', ['set', 'shrinkwrap', 'true']), + npm.exec('config', ['set', 'shrinkwrap', 'true']), /deprecated/ ) }) t.test('config set nerf-darted option', async t => { - const sandbox = new Sandbox(t) - await sandbox.run('config', ['set', '//npm.pkg.github.com/:_authToken', '0xdeadbeef']) + const { npm } = await loadMockNpm(t) + await npm.exec('config', ['set', '//npm.pkg.github.com/:_authToken', '0xdeadbeef']) t.equal( - sandbox.config.get('//npm.pkg.github.com/:_authToken'), + npm.config.get('//npm.pkg.github.com/:_authToken'), '0xdeadbeef', 'nerf-darted config is set' ) }) t.test('config set scoped optoin', async t => { - const sandbox = new Sandbox(t) - await sandbox.run('config', ['set', '@npm:registry', 'https://registry.npmjs.org']) + const { npm } = await loadMockNpm(t) + await npm.exec('config', ['set', '@npm:registry', 'https://registry.npmjs.org']) t.equal( - sandbox.config.get('@npm:registry'), + npm.config.get('@npm:registry'), 'https://registry.npmjs.org', 'scoped config is set' ) }) t.test('config set no args', async t => { - const sandbox = new Sandbox(t) + const { npm } = await loadMockNpm(t) await t.rejects( - sandbox.run('config', ['set']), + npm.exec('config', ['set']), { code: 'EUSAGE', }, @@ -242,45 +332,45 @@ t.test('config set no args', async t => { }) t.test('config set key', async t => { - const home = t.testdir({ - '.npmrc': 'access=public', + const { npm, home } = await loadMockNpm(t, { + homeDir: { + '.npmrc': 'access=public', + }, }) - const sandbox = new Sandbox(t, { home }) + await npm.exec('config', ['set', 'access']) - await sandbox.run('config', ['set', 'access']) - - t.equal(sandbox.config.get('access'), null, 'set the value for access') + t.equal(npm.config.get('access'), null, 'set the value for access') await t.rejects(fs.stat(join(home, '.npmrc'), { encoding: 'utf8' }), 'removed empty config') }) t.test('config set key value', async t => { - const home = t.testdir({ - '.npmrc': 'access=public', + const { npm, home } = await loadMockNpm(t, { + homeDir: { + '.npmrc': 'access=public', + }, }) - const sandbox = new Sandbox(t, { home }) + await npm.exec('config', ['set', 'access', 'restricted']) - await sandbox.run('config', ['set', 'access', 'restricted']) - - t.equal(sandbox.config.get('access'), 'restricted', 'set the value for access') + t.equal(npm.config.get('access'), 'restricted', 'set the value for access') const contents = await fs.readFile(join(home, '.npmrc'), { encoding: 'utf8' }) const rc = ini.parse(contents) t.equal(rc.access, 'restricted', 'access is set to restricted') }) -t.test('config set key=value', async t => { - const home = t.testdir({ - '.npmrc': 'access=public', +t.test('config set key value with equals', async t => { + const { npm, home } = await loadMockNpm(t, { + homeDir: { + '.npmrc': 'access=public', + }, }) - const sandbox = new Sandbox(t, { home }) - - await sandbox.run('config', ['set', 'access=restricted']) + await npm.exec('config', ['set', 'access=restricted']) - t.equal(sandbox.config.get('access'), 'restricted', 'set the value for access') + t.equal(npm.config.get('access'), 'restricted', 'set the value for access') const contents = await fs.readFile(join(home, '.npmrc'), { encoding: 'utf8' }) const rc = ini.parse(contents) @@ -288,16 +378,17 @@ t.test('config set key=value', async t => { }) t.test('config set key1 value1 key2=value2 key3', async t => { - const home = t.testdir({ - '.npmrc': 'access=public\nall=true\naudit=true', + const { npm, home } = await loadMockNpm(t, { + homeDir: { + '.npmrc': 'access=public\nall=true\naudit=true', + }, }) - const sandbox = new Sandbox(t, { home }) - await sandbox.run('config', ['set', 'access', 'restricted', 'all=false', 'audit']) + await npm.exec('config', ['set', 'access', 'restricted', 'all=false', 'audit']) - t.equal(sandbox.config.get('access'), 'restricted', 'access was set') - t.equal(sandbox.config.get('all'), false, 'all was set') - t.equal(sandbox.config.get('audit'), true, 'audit was unset and restored to its default') + t.equal(npm.config.get('access'), 'restricted', 'access was set') + t.equal(npm.config.get('all'), false, 'all was set') + t.equal(npm.config.get('audit'), true, 'audit was unset and restored to its default') const contents = await fs.readFile(join(home, '.npmrc'), { encoding: 'utf8' }) const rc = ini.parse(contents) @@ -307,113 +398,120 @@ t.test('config set key1 value1 key2=value2 key3', async t => { }) t.test('config set invalid key logs warning', async t => { - const sandbox = new Sandbox(t) + const { npm, logs, home } = await loadMockNpm(t) // this doesn't reject, it only logs a warning - await sandbox.run('config', ['set', 'access=foo']) - t.match( - sandbox.logs.warn, - [['invalid config', 'access="foo"', `set in ${join(sandbox.home, '.npmrc')}`]], + await npm.exec('config', ['set', 'access=foo']) + t.equal(logs.warn[0], + `invalid config access="foo" set in ${join(home, '.npmrc')}`, 'logged warning' ) }) t.test('config set key=value --location=global', async t => { - const global = t.testdir({ - npmrc: 'access=public\nall=true', + const { npm, globalPrefix } = await loadMockNpm(t, { + globalPrefixDir: { + etc: { + npmrc: 'access=public\nall=true', + }, + }, + config: { + location: 'global', + }, }) - const sandbox = new Sandbox(t, { global }) - await sandbox.run('config', ['set', 'access=restricted', '--location=global']) + await npm.exec('config', ['set', 'access=restricted']) - t.equal(sandbox.config.get('access', 'global'), 'restricted', 'foo should be set') + t.equal(npm.config.get('access', 'global'), 'restricted', 'foo should be set') - const contents = await fs.readFile(join(global, 'npmrc'), { encoding: 'utf8' }) + const contents = await fs.readFile(join(globalPrefix, 'etc/npmrc'), { encoding: 'utf8' }) const rc = ini.parse(contents) t.equal(rc.access, 'restricted', 'access is set to restricted') }) t.test('config set key=value --global', async t => { - const global = t.testdir({ - npmrc: 'access=public\nall=true', + const { npm, globalPrefix } = await loadMockNpm(t, { + globalPrefixDir: { + etc: { + npmrc: 'access=public\nall=true', + }, + }, + config: { + global: true, + }, }) - const sandbox = new Sandbox(t, { global }) - await sandbox.run('config', ['set', 'access=restricted', '--global']) + await npm.exec('config', ['set', 'access=restricted']) - t.equal(sandbox.config.get('access', 'global'), 'restricted', 'access should be set') + t.equal(npm.config.get('access', 'global'), 'restricted', 'access should be set') - const contents = await fs.readFile(join(global, 'npmrc'), { encoding: 'utf8' }) + const contents = await fs.readFile(join(globalPrefix, 'etc/npmrc'), { encoding: 'utf8' }) const rc = ini.parse(contents) t.equal(rc.access, 'restricted', 'access is set to restricted') }) t.test('config get no args', async t => { - const sandbox = new Sandbox(t) + const { npm, joinedOutput, clearOutput } = await loadMockNpm(t) - await sandbox.run('config', ['get']) - const getOutput = sandbox.output + await npm.exec('config', ['get']) + const getOutput = joinedOutput() - sandbox.reset() - - await sandbox.run('config', ['list']) - const listOutput = sandbox.output + clearOutput() + await npm.exec('config', ['list']) + const listOutput = joinedOutput() t.equal(listOutput, getOutput, 'get with no args outputs list') }) t.test('config get single key', async t => { - const sandbox = new Sandbox(t) + const { npm, joinedOutput } = await loadMockNpm(t) - await sandbox.run('config', ['get', 'all']) - t.equal(sandbox.output, `${sandbox.config.get('all')}`, 'should get the value') + await npm.exec('config', ['get', 'all']) + t.equal(joinedOutput(), `${npm.config.get('all')}`, 'should get the value') }) t.test('config get multiple keys', async t => { - const sandbox = new Sandbox(t) + const { npm, joinedOutput } = await loadMockNpm(t) - await sandbox.run('config', ['get', 'yes', 'all']) - t.ok( - sandbox.output.includes(`yes=${sandbox.config.get('yes')}`), - 'outputs yes' - ) - t.ok( - sandbox.output.includes(`all=${sandbox.config.get('all')}`), - 'outputs all' - ) + await npm.exec('config', ['get', 'yes', 'all']) + t.equal(joinedOutput(), `yes=${npm.config.get('yes')}\nall=${npm.config.get('all')}`) }) t.test('config get private key', async t => { - const sandbox = new Sandbox(t) + const { npm } = await loadMockNpm(t) await t.rejects( - sandbox.run('config', ['get', '_authToken']), + npm.exec('config', ['get', '_authToken']), /_authToken option is protected/, 'rejects with protected string' ) await t.rejects( - sandbox.run('config', ['get', '//localhost:8080/:_password']), + npm.exec('config', ['get', '//localhost:8080/:_password']), /_password option is protected/, 'rejects with protected string' ) }) t.test('config edit', async t => { - const home = t.testdir({ - '.npmrc': 'foo=bar\nbar=baz', - }) - const EDITOR = 'vim' const editor = spawk.spawn(EDITOR).exit(0) - const sandbox = new Sandbox(t, { home, env: { EDITOR } }) - await sandbox.run('config', ['edit']) + const { npm, home } = await loadMockNpm(t, { + homeDir: { + '.npmrc': 'foo=bar\nbar=baz', + }, + config: { + editor: EDITOR, + }, + }) + + await npm.exec('config', ['edit']) t.ok(editor.called, 'editor was spawned') t.same( editor.calledWith.args, - [join(sandbox.home, '.npmrc')], + [join(home, '.npmrc')], 'editor opened the user config file' ) @@ -427,10 +525,14 @@ t.test('config edit - editor exits non-0', async t => { const EDITOR = 'vim' const editor = spawk.spawn(EDITOR).exit(1) - const sandbox = new Sandbox(t) - sandbox.process.env.EDITOR = EDITOR + const { npm, home } = await loadMockNpm(t, { + config: { + editor: EDITOR, + }, + }) + await t.rejects( - sandbox.run('config', ['edit']), + npm.exec('config', ['edit']), { message: 'editor process exited with code: 1', }, @@ -440,101 +542,102 @@ t.test('config edit - editor exits non-0', async t => { t.ok(editor.called, 'editor was spawned') t.same( editor.calledWith.args, - [join(sandbox.home, '.npmrc')], + [join(home, '.npmrc')], 'editor opened the user config file' ) }) t.test('config fix', (t) => { t.test('no problems', async (t) => { - const home = t.testdir({ - '.npmrc': '', + const { npm, joinedOutput } = await loadMockNpm(t, { + homeDir: { + '.npmrc': '', + }, }) - const sandbox = new Sandbox(t, { home }) - await sandbox.run('config', ['fix']) - t.equal(sandbox.output, '', 'printed nothing') + await npm.exec('config', ['fix']) + t.equal(joinedOutput(), '', 'printed nothing') }) t.test('repairs all configs by default', async (t) => { - const root = t.testdir({ - global: { - npmrc: '_authtoken=notatoken\n_authToken=afaketoken', + const { npm, home, globalPrefix, joinedOutput } = await loadMockNpm(t, { + globalPrefixDir: { + etc: { + npmrc: '_authtoken=notatoken\n_authToken=afaketoken', + }, }, - home: { + homeDir: { '.npmrc': '_authtoken=thisisinvalid\n_auth=beef', }, }) + const registry = `//registry.npmjs.org/` - const sandbox = new Sandbox(t, { - global: join(root, 'global'), - home: join(root, 'home'), - }) - await sandbox.run('config', ['fix']) + await npm.exec('config', ['fix']) // global config fixes - t.match(sandbox.output, '`_authtoken` deleted from global config', + t.match(joinedOutput(), '`_authtoken` deleted from global config', 'output has deleted global _authtoken') - t.match(sandbox.output, `\`_authToken\` renamed to \`${registry}:_authToken\` in global config`, + t.match(joinedOutput(), `\`_authToken\` renamed to \`${registry}:_authToken\` in global config`, 'output has renamed global _authToken') - t.not(sandbox.config.get('_authtoken', 'global'), '_authtoken is not set globally') - t.not(sandbox.config.get('_authToken', 'global'), '_authToken is not set globally') - t.equal(sandbox.config.get(`${registry}:_authToken`, 'global'), 'afaketoken', + t.not(npm.config.get('_authtoken', 'global'), '_authtoken is not set globally') + t.not(npm.config.get('_authToken', 'global'), '_authToken is not set globally') + t.equal(npm.config.get(`${registry}:_authToken`, 'global'), 'afaketoken', 'global _authToken was scoped') - const globalConfig = await fs.readFile(join(root, 'global', 'npmrc'), { encoding: 'utf8' }) + const globalConfig = await fs.readFile(join(globalPrefix, 'etc/npmrc'), { encoding: 'utf8' }) t.equal(globalConfig, `${registry}:_authToken=afaketoken\n`, 'global config was written') // user config fixes - t.match(sandbox.output, '`_authtoken` deleted from user config', + t.match(joinedOutput(), '`_authtoken` deleted from user config', 'output has deleted user _authtoken') - t.match(sandbox.output, `\`_auth\` renamed to \`${registry}:_auth\` in user config`, + t.match(joinedOutput(), `\`_auth\` renamed to \`${registry}:_auth\` in user config`, 'output has renamed user _auth') - t.not(sandbox.config.get('_authtoken', 'user'), '_authtoken is not set in user config') - t.not(sandbox.config.get('_auth'), '_auth is not set in user config') - t.equal(sandbox.config.get(`${registry}:_auth`, 'user'), 'beef', 'user _auth was scoped') - const userConfig = await fs.readFile(join(root, 'home', '.npmrc'), { encoding: 'utf8' }) + t.not(npm.config.get('_authtoken', 'user'), '_authtoken is not set in user config') + t.not(npm.config.get('_auth'), '_auth is not set in user config') + t.equal(npm.config.get(`${registry}:_auth`, 'user'), 'beef', 'user _auth was scoped') + const userConfig = await fs.readFile(join(home, '.npmrc'), { encoding: 'utf8' }) t.equal(userConfig, `${registry}:_auth=beef\n`, 'user config was written') }) t.test('repairs only the config specified by --location if asked', async (t) => { - const root = t.testdir({ - global: { - npmrc: '_authtoken=notatoken\n_authToken=afaketoken', + const { npm, home, globalPrefix, joinedOutput } = await loadMockNpm(t, { + globalPrefixDir: { + etc: { + npmrc: '_authtoken=notatoken\n_authToken=afaketoken', + }, }, - home: { + homeDir: { '.npmrc': '_authtoken=thisisinvalid\n_auth=beef', }, + config: { + location: 'user', + }, }) const registry = `//registry.npmjs.org/` - const sandbox = new Sandbox(t, { - global: join(root, 'global'), - home: join(root, 'home'), - }) - await sandbox.run('config', ['fix', '--location=user']) + await npm.exec('config', ['fix']) // global config should be untouched - t.notMatch(sandbox.output, '`_authtoken` deleted from global', + t.notMatch(joinedOutput(), '`_authtoken` deleted from global', 'output has deleted global _authtoken') - t.notMatch(sandbox.output, `\`_authToken\` renamed to \`${registry}:_authToken\` in global`, + t.notMatch(joinedOutput(), `\`_authToken\` renamed to \`${registry}:_authToken\` in global`, 'output has renamed global _authToken') - t.equal(sandbox.config.get('_authtoken', 'global'), 'notatoken', 'global _authtoken untouched') - t.equal(sandbox.config.get('_authToken', 'global'), 'afaketoken', 'global _authToken untouched') - t.not(sandbox.config.get(`${registry}:_authToken`, 'global'), 'global _authToken not scoped') - const globalConfig = await fs.readFile(join(root, 'global', 'npmrc'), { encoding: 'utf8' }) + t.equal(npm.config.get('_authtoken', 'global'), 'notatoken', 'global _authtoken untouched') + t.equal(npm.config.get('_authToken', 'global'), 'afaketoken', 'global _authToken untouched') + t.not(npm.config.get(`${registry}:_authToken`, 'global'), 'global _authToken not scoped') + const globalConfig = await fs.readFile(join(globalPrefix, 'etc/npmrc'), { encoding: 'utf8' }) t.equal(globalConfig, '_authtoken=notatoken\n_authToken=afaketoken', 'global config was not written') // user config fixes - t.match(sandbox.output, '`_authtoken` deleted from user', + t.match(joinedOutput(), '`_authtoken` deleted from user', 'output has deleted user _authtoken') - t.match(sandbox.output, `\`_auth\` renamed to \`${registry}:_auth\` in user`, + t.match(joinedOutput(), `\`_auth\` renamed to \`${registry}:_auth\` in user`, 'output has renamed user _auth') - t.not(sandbox.config.get('_authtoken', 'user'), '_authtoken is not set in user config') - t.not(sandbox.config.get('_auth', 'user'), '_auth is not set in user config') - t.equal(sandbox.config.get(`${registry}:_auth`, 'user'), 'beef', 'user _auth was scoped') - const userConfig = await fs.readFile(join(root, 'home', '.npmrc'), { encoding: 'utf8' }) + t.not(npm.config.get('_authtoken', 'user'), '_authtoken is not set in user config') + t.not(npm.config.get('_auth', 'user'), '_auth is not set in user config') + t.equal(npm.config.get(`${registry}:_auth`, 'user'), 'beef', 'user _auth was scoped') + const userConfig = await fs.readFile(join(home, '.npmrc'), { encoding: 'utf8' }) t.equal(userConfig, `${registry}:_auth=beef\n`, 'user config was written') }) @@ -542,15 +645,21 @@ t.test('config fix', (t) => { }) t.test('completion', async t => { - const sandbox = new Sandbox(t) - - let allKeys - const testComp = async (argv, expect) => { - t.match(await sandbox.complete('config', argv), expect, argv.join(' ')) - if (!allKeys) { - allKeys = Object.keys(sandbox.config.definitions) - } - sandbox.reset() + const { config, npm } = await loadMockNpm(t, { command: 'config' }) + + const allKeys = Object.keys(npm.config.definitions) + + const testComp = async (argv, expect, msg) => { + const options = Array.isArray(argv) ? { + conf: { + argv: { + remain: ['config', ...argv], + }, + }, + } : argv + options.conf.argv.remain.unshift('npm') + const res = await config.completion(options) + t.strictSame(res, expect, msg ?? argv.join(' ')) } await testComp([], ['get', 'set', 'delete', 'ls', 'rm', 'edit', 'fix', 'list']) @@ -564,10 +673,12 @@ t.test('completion', async t => { await testComp(['list'], []) await testComp(['ls'], []) - const getCommand = await sandbox.complete('get') - t.match(getCommand, allKeys, 'also works for just npm get') - sandbox.reset() + await testComp({ + conf: { argv: { remain: ['get'] } }, + }, allKeys, 'also works for just npm get') - const partial = await sandbox.complete('config', 'l') - t.match(partial, ['get', 'set', 'delete', 'ls', 'rm', 'edit'], 'and works on partials') + await testComp({ + partialWord: 'l', + conf: { argv: { remain: ['config'] } }, + }, ['get', 'set', 'delete', 'ls', 'rm', 'edit', 'fix'], 'and works on partials') }) diff --git a/test/lib/commands/dist-tag.js b/test/lib/commands/dist-tag.js index 918f658c6462a..5de9acb1da81f 100644 --- a/test/lib/commands/dist-tag.js +++ b/test/lib/commands/dist-tag.js @@ -88,12 +88,7 @@ const mockDist = async (t, { ...npmOpts } = {}) => { distTag: mock['dist-tag'], fetchOpts: () => fetchOpts, result: () => mock.joinedOutput(), - logs: () => { - const distLogs = mock.logs.filter(l => l[1].startsWith('dist-tag')) - return distLogs.map(([, ...parts]) => { - return parts.map(p => p.toString()).join(' ').trim() - }).join('\n').trim() - }, + joinedLogs: () => mock.logs.byTitle('dist-tag').join('\n').trim(), } } @@ -159,13 +154,13 @@ t.test('ls on named package', async t => { }) t.test('ls on missing package', async t => { - const { distTag, logs } = await mockDist(t) + const { distTag, joinedLogs } = await mockDist(t) await t.rejects( distTag.exec(['ls', 'foo']), distTag.usage ) t.matchSnapshot( - logs(), + joinedLogs(), 'should log no dist-tag found msg' ) }) @@ -245,8 +240,8 @@ t.test('workspaces', async t => { }) t.test('two args -- list, @scoped/pkg, logs a warning and ignores workspaces', async t => { - const { result, logs } = await mockWorkspaces(t, ['list', '@scoped/pkg']) - t.match(logs(), 'Ignoring workspaces for specified package', 'logs a warning') + const { result, joinedLogs } = await mockWorkspaces(t, ['list', '@scoped/pkg']) + t.match(joinedLogs(), 'Ignoring workspaces for specified package', 'logs a warning') t.matchSnapshot(result(), 'printed the expected output') }) @@ -266,7 +261,10 @@ t.test('workspaces', async t => { }, }) - t.match(logs(), 'dist-tag ls Couldn\'t get dist-tag data for workspace-d@*', 'logs the error') + const error = logs.error.byTitle('dist-tag ls')[0] + + t.match(error, 'Couldn\'t get dist-tag data for Result {') + t.match(error, `name: 'workspace-d',`) t.matchSnapshot(result(), 'printed the expected output') }) }) @@ -284,14 +282,14 @@ t.test('add new tag', async t => { }) t.test('add using valid semver range as name', async t => { - const { distTag, logs } = await mockDist(t) + const { distTag, joinedLogs } = await mockDist(t) await t.rejects( distTag.exec(['add', '@scoped/another@7.7.7', '1.0.0']), /Tag name must not be a valid SemVer range: 1.0.0/, 'should exit with semver range error' ) t.matchSnapshot( - logs(), + joinedLogs(), 'should return success msg' ) }) @@ -328,31 +326,31 @@ t.test('add invalid tag', async t => { }) t.test('set existing version', async t => { - const { distTag, logs } = await mockDist(t) + const { distTag, joinedLogs } = await mockDist(t) await distTag.exec(['set', '@scoped/another@0.6.0', 'b']) t.matchSnapshot( - logs(), + joinedLogs(), 'should log warn msg' ) }) t.test('remove existing tag', async t => { - const { distTag, result, logs, fetchOpts } = await mockDist(t) + const { distTag, result, joinedLogs, fetchOpts } = await mockDist(t) await distTag.exec(['rm', '@scoped/another', 'c']) const opts = fetchOpts() t.equal(opts.method, 'DELETE', 'should trigger request to remove tag') - t.matchSnapshot(logs(), 'should log remove info') + t.matchSnapshot(joinedLogs(), 'should log remove info') t.matchSnapshot(result(), 'should return success msg') }) t.test('remove non-existing tag', async t => { - const { distTag, logs } = await mockDist(t) + const { distTag, joinedLogs } = await mockDist(t) await t.rejects( distTag.exec(['rm', '@scoped/another', 'nonexistent']), /nonexistent is not a dist-tag on @scoped\/another/, 'should exit with error' ) - t.matchSnapshot(logs(), 'should log error msg') + t.matchSnapshot(joinedLogs(), 'should log error msg') }) t.test('remove missing pkg name', async t => { diff --git a/test/lib/commands/hook.js b/test/lib/commands/hook.js index 382bc177e7001..a93b0c99f5267 100644 --- a/test/lib/commands/hook.js +++ b/test/lib/commands/hook.js @@ -85,7 +85,7 @@ t.test('npm hook add', async t => { }, 'provided the correct arguments to libnpmhook' ) - t.strictSame(outputs[0], ['+ semver -> https://google.com'], 'prints the correct output') + t.strictSame(outputs[0], '+ semver -> https://google.com', 'prints the correct output') }) t.test('npm hook add - correct owner hook output', async t => { @@ -102,7 +102,7 @@ t.test('npm hook add - correct owner hook output', async t => { }, 'provided the correct arguments to libnpmhook' ) - t.strictSame(outputs[0], ['+ ~npm -> https://google.com'], 'prints the correct output') + t.strictSame(outputs[0], '+ ~npm -> https://google.com', 'prints the correct output') }) t.test('npm hook add - correct scope hook output', async t => { @@ -119,7 +119,7 @@ t.test('npm hook add - correct scope hook output', async t => { }, 'provided the correct arguments to libnpmhook' ) - t.strictSame(outputs[0], ['+ @npmcli -> https://google.com'], 'prints the correct output') + t.strictSame(outputs[0], '+ @npmcli -> https://google.com', 'prints the correct output') }) t.test('npm hook add - unicode output', async t => { @@ -142,7 +142,7 @@ t.test('npm hook add - unicode output', async t => { }, 'provided the correct arguments to libnpmhook' ) - t.strictSame(outputs[0], ['+ semver ➜ https://google.com'], 'prints the correct output') + t.strictSame(outputs[0], '+ semver ➜ https://google.com', 'prints the correct output') }) t.test('npm hook add - json output', async t => { @@ -166,7 +166,7 @@ t.test('npm hook add - json output', async t => { 'provided the correct arguments to libnpmhook' ) t.strictSame( - JSON.parse(outputs[0][0]), + JSON.parse(outputs[0]), { id: 1, name: '@npmcli', @@ -199,12 +199,12 @@ t.test('npm hook add - parseable output', async t => { ) t.strictSame( - outputs[0][0].split(/\t/), + outputs[0].split(/\t/), ['id', 'name', 'type', 'endpoint'], 'prints the correct parseable output headers' ) t.strictSame( - outputs[1][0].split(/\t/), + outputs[1].split(/\t/), ['1', '@npmcli', 'scope', 'https://google.com'], 'prints the correct parseable values' ) @@ -243,8 +243,8 @@ t.test('npm hook ls', async t => { }, 'received the correct arguments' ) - t.equal(outputs[0][0], 'You have 3 hooks configured.', 'prints the correct header') - const out = stripVTControlCharacters(outputs[1][0]) + t.equal(outputs[0], 'You have 3 hooks configured.', 'prints the correct header') + const out = stripVTControlCharacters(outputs[1]) t.match(out, /semver.*https:\/\/google.com.*\n.*\n.*never triggered/, 'prints package hook') t.match(out, /@npmcli.*https:\/\/google.com.*\n.*\n.*triggered just now/, 'prints scope hook') t.match(out, /~npm.*https:\/\/google.com.*\n.*\n.*never triggered/, 'prints owner hook') @@ -266,7 +266,7 @@ t.test('npm hook ls, no results', async t => { }, 'received the correct arguments' ) - t.equal(outputs[0][0], "You don't have any hooks configured yet.", 'prints the correct result') + t.equal(outputs[0], "You don't have any hooks configured yet.", 'prints the correct result') }) t.test('npm hook ls, single result', async t => { @@ -292,8 +292,8 @@ t.test('npm hook ls, single result', async t => { }, 'received the correct arguments' ) - t.equal(outputs[0][0], 'You have one hook configured.', 'prints the correct header') - const out = stripVTControlCharacters(outputs[1][0]) + t.equal(outputs[0], 'You have one hook configured.', 'prints the correct header') + const out = stripVTControlCharacters(outputs[1]) t.match(out, /semver.*https:\/\/google.com.*\n.*\n.*never triggered/, 'prints package hook') }) @@ -361,7 +361,7 @@ t.test('npm hook ls - parseable output', async t => { 'received the correct arguments' ) t.strictSame( - outputs.map(line => line[0].split(/\t/)), + outputs.map(line => line.split(/\t/)), [ ['id', 'name', 'type', 'endpoint', 'last_delivery'], ['1', 'semver', 'package', 'https://google.com', ''], @@ -404,7 +404,7 @@ t.test('npm hook rm', async t => { }, 'received the correct arguments' ) - t.strictSame(outputs[0], ['- semver X https://google.com'], 'printed the correct output') + t.strictSame(outputs[0], '- semver X https://google.com', 'printed the correct output') }) t.test('npm hook rm - unicode output', async t => { @@ -425,7 +425,7 @@ t.test('npm hook rm - unicode output', async t => { }, 'received the correct arguments' ) - t.strictSame(outputs[0], ['- semver ✘ https://google.com'], 'printed the correct output') + t.strictSame(outputs[0], '- semver ✘ https://google.com', 'printed the correct output') }) t.test('npm hook rm - silent output', async t => { @@ -496,7 +496,7 @@ t.test('npm hook rm - parseable output', async t => { 'received the correct arguments' ) t.strictSame( - outputs.map(line => line[0].split(/\t/)), + outputs.map(line => line.split(/\t/)), [ ['id', 'name', 'type', 'endpoint'], ['1', 'semver', 'package', 'https://google.com'], @@ -520,7 +520,7 @@ t.test('npm hook update', async t => { }, 'received the correct arguments' ) - t.strictSame(outputs[0], ['+ semver -> https://google.com'], 'printed the correct output') + t.strictSame(outputs[0], '+ semver -> https://google.com', 'printed the correct output') }) t.test('npm hook update - unicode', async t => { @@ -543,7 +543,7 @@ t.test('npm hook update - unicode', async t => { }, 'received the correct arguments' ) - t.strictSame(outputs[0], ['+ semver ➜ https://google.com'], 'printed the correct output') + t.strictSame(outputs[0], '+ semver ➜ https://google.com', 'printed the correct output') }) t.test('npm hook update - json output', async t => { @@ -599,7 +599,7 @@ t.test('npm hook update - parseable output', async t => { 'received the correct arguments' ) t.strictSame( - outputs.map(line => line[0].split(/\t/)), + outputs.map(line => line.split(/\t/)), [ ['id', 'name', 'type', 'endpoint'], ['1', 'semver', 'package', 'https://google.com'], diff --git a/test/lib/commands/init.js b/test/lib/commands/init.js index cb708303f405a..6dd23560bf8fa 100644 --- a/test/lib/commands/init.js +++ b/test/lib/commands/init.js @@ -238,8 +238,7 @@ t.test('npm init cancel', async t => { await npm.exec('init', []) - t.equal(logs.warn[0][0], 'init', 'should have init title') - t.equal(logs.warn[0][1], 'canceled', 'should log canceled') + t.equal(logs.warn[0], 'init canceled', 'should have init title and canceled') }) t.test('npm init error', async t => { @@ -335,7 +334,7 @@ t.test('workspaces', async t => { 'should exit with missing package.json file error' ) - t.equal(logs.warn[0][0], 'Missing package.json. Try with `--include-workspace-root`.') + t.equal(logs.warn[0], 'init Missing package.json. Try with `--include-workspace-root`.') }) await t.test('bad package.json when settting workspace', async t => { diff --git a/test/lib/commands/logout.js b/test/lib/commands/logout.js index 881003729ab4a..3087c8bb1e61d 100644 --- a/test/lib/commands/logout.js +++ b/test/lib/commands/logout.js @@ -18,8 +18,8 @@ t.test('token logout - user config', async t => { mockRegistry.logout('@foo/') await npm.exec('logout', []) t.equal( - logs.verbose.find(l => l[0] === 'logout')[1], - 'clearing token for https://registry.npmjs.org/', + logs.verbose.byTitle('logout')[0], + 'logout clearing token for https://registry.npmjs.org/', 'should log message with correct registry' ) const userRc = await fs.readFile(join(home, '.npmrc'), 'utf-8') @@ -45,8 +45,8 @@ t.test('token scoped logout - user config', async t => { mockRegistry.logout('@bar/') await npm.exec('logout', []) t.equal( - logs.verbose.find(l => l[0] === 'logout')[1], - 'clearing token for https://diff-registry.npmjs.com/', + logs.verbose.byTitle('logout')[0], + 'logout clearing token for https://diff-registry.npmjs.com/', 'should log message with correct registry' ) @@ -67,8 +67,8 @@ t.test('user/pass logout - user config', async t => { await npm.exec('logout', []) t.equal( - logs.verbose.find(l => l[0] === 'logout')[1], - 'clearing user credentials for https://registry.npmjs.org/', + logs.verbose.byTitle('logout')[0], + 'logout clearing user credentials for https://registry.npmjs.org/', 'should log message with correct registry' ) @@ -106,8 +106,8 @@ t.test('ignore invalid scoped registry config', async t => { await npm.exec('logout', []) t.equal( - logs.verbose.find(l => l[0] === 'logout')[1], - 'clearing token for https://registry.npmjs.org/', + logs.verbose.byTitle('logout')[0], + 'logout clearing token for https://registry.npmjs.org/', 'should log message with correct registry' ) const userRc = await fs.readFile(join(home, '.npmrc'), 'utf-8') @@ -135,8 +135,8 @@ t.test('token logout - project config', async t => { await npm.exec('logout', []) t.equal( - logs.verbose.find(l => l[0] === 'logout')[1], - 'clearing token for https://registry.npmjs.org/', + logs.verbose.byTitle('logout')[0], + 'logout clearing token for https://registry.npmjs.org/', 'should log message with correct registry' ) const userRc = await fs.readFile(join(home, '.npmrc'), 'utf-8') @@ -145,8 +145,8 @@ t.test('token logout - project config', async t => { 'other-config=true', ].join('\n'), 'leaves user config alone') t.equal( - logs.verbose.find(l => l[0] === 'logout')[1], - 'clearing token for https://registry.npmjs.org/', + logs.verbose.byTitle('logout')[0], + 'logout clearing token for https://registry.npmjs.org/', 'should log message with correct registry' ) const projectRc = await fs.readFile(join(prefix, '.npmrc'), 'utf-8') diff --git a/test/lib/commands/org.js b/test/lib/commands/org.js index 0c343f028d6dc..576a16d19303d 100644 --- a/test/lib/commands/org.js +++ b/test/lib/commands/org.js @@ -92,7 +92,7 @@ t.test('npm org add', async t => { 'received the correct arguments' ) t.equal( - outputs[0][0], + outputs[0], 'Added username as developer to orgname. You now have 1 member in this org.', 'printed the correct output' ) @@ -142,7 +142,7 @@ t.test('npm org add - more users', async t => { 'received the correct arguments' ) t.equal( - outputs[0][0], + outputs[0], 'Added username as developer to orgname. You now have 5 members in this org.', 'printed the correct output' ) @@ -198,7 +198,7 @@ t.test('npm org add - parseable output', async t => { 'received the correct arguments' ) t.strictSame( - outputs.map(line => line[0].split(/\t/)), + outputs.map(line => line.split(/\t/)), [ ['org', 'orgsize', 'user', 'role'], ['orgname', '1', 'username', 'developer'], @@ -251,7 +251,7 @@ t.test('npm org rm', async t => { 'libnpmorg.ls received the correct args' ) t.equal( - outputs[0][0], + outputs[0], 'Successfully removed username from orgname. You now have 0 members in this org.', 'printed the correct output' ) @@ -301,7 +301,7 @@ t.test('npm org rm - one user left', async t => { 'libnpmorg.ls received the correct args' ) t.equal( - outputs[0][0], + outputs[0], 'Successfully removed username from orgname. You now have 1 member in this org.', 'printed the correct output' ) @@ -370,7 +370,7 @@ t.test('npm org rm - parseable output', async t => { 'libnpmorg.ls received the correct args' ) t.strictSame( - outputs.map(line => line[0].split(/\t/)), + outputs.map(line => line.split(/\t/)), [ ['user', 'org', 'userCount', 'deleted'], ['username', 'orgname', '0', 'true'], @@ -427,7 +427,7 @@ t.test('npm org ls', async t => { }, 'receieved the correct args' ) - const out = stripVTControlCharacters(outputs[0][0]) + const out = stripVTControlCharacters(outputs[0]) t.match(out, /one.*developer/, 'contains the developer member') t.match(out, /two.*admin/, 'contains the admin member') t.match(out, /three.*owner/, 'contains the owner member') @@ -452,7 +452,7 @@ t.test('npm org ls - user filter', async t => { }, 'receieved the correct args' ) - const out = stripVTControlCharacters(outputs[0][0]) + const out = stripVTControlCharacters(outputs[0]) t.match(out, /username.*admin/, 'contains the filtered member') t.notMatch(out, /missing.*admin/, 'does not contain other members') }) @@ -533,7 +533,7 @@ t.test('npm org ls - parseable output', async t => { 'receieved the correct args' ) t.strictSame( - outputs.map(line => line[0].split(/\t/)), + outputs.map(line => line.split(/\t/)), [ ['user', 'role'], ['one', 'developer'], diff --git a/test/lib/commands/owner.js b/test/lib/commands/owner.js index 9329e8985e60c..ec774d1647048 100644 --- a/test/lib/commands/owner.js +++ b/test/lib/commands/owner.js @@ -123,7 +123,7 @@ t.test('owner ls fails to retrieve packument', async t => { }) registry.nock.get(`/${spec.escapedName}`).reply(404) await t.rejects(npm.exec('owner', ['ls'])) - t.match(logs.error, [['owner ls', "Couldn't get owner data", '@npmcli/test-package']]) + t.match(logs.error.byTitle('owner ls'), [`owner ls Couldn't get owner data @npmcli/test-package`]) }) t.test('owner ls ', async t => { @@ -240,8 +240,8 @@ t.test('owner add already an owner', async t => { await npm.exec('owner', ['add', username, packageName]) t.equal(joinedOutput(), '') t.match( - logs.info, - [['owner add', 'Already a package owner: test-user-a ']] + logs.info.byTitle('owner add'), + [`Already a package owner: test-user-a `] ) }) @@ -256,7 +256,7 @@ t.test('owner add fails to retrieve user', async t => { }) registry.couchuser({ username, responseCode: 404, body: {} }) await t.rejects(npm.exec('owner', ['add', username, packageName])) - t.match(logs.error, [['owner mutate', `Error getting user data for ${username}`]]) + t.match(logs.error.byTitle('owner mutate'), [`Error getting user data for ${username}`]) }) t.test('owner add fails to PUT updates', async t => { @@ -380,7 +380,7 @@ t.test('owner rm not a current owner', async t => { registry.couchuser({ username }) await registry.package({ manifest }) await npm.exec('owner', ['rm', username, packageName]) - t.match(logs.info, [['owner rm', `Not a package owner: ${username}`]]) + t.match(logs.info.byTitle('owner rm'), [`Not a package owner: ${username}`]) }) t.test('owner rm cwd package', async t => { diff --git a/test/lib/commands/pack.js b/test/lib/commands/pack.js index baec163c7b34d..93d4da22d31c2 100644 --- a/test/lib/commands/pack.js +++ b/test/lib/commands/pack.js @@ -17,8 +17,8 @@ t.test('should pack current directory with no arguments', async t => { }) await npm.exec('pack', []) const filename = 'test-package-1.0.0.tgz' - t.strictSame(outputs, [[filename]]) - t.matchSnapshot(logs.notice.map(([, m]) => m), 'logs pack contents') + t.strictSame(outputs, [filename]) + t.matchSnapshot(logs.notice, 'logs pack contents') t.ok(fs.statSync(path.resolve(npm.prefix, filename))) }) @@ -35,7 +35,7 @@ t.test('follows pack-destination config', async t => { }) await npm.exec('pack', []) const filename = 'test-package-1.0.0.tgz' - t.strictSame(outputs, [[filename]]) + t.strictSame(outputs, [filename]) t.ok(fs.statSync(path.resolve(npm.prefix, 'tar-destination', filename))) }) @@ -50,7 +50,7 @@ t.test('should pack given directory for scoped package', async t => { }) await npm.exec('pack', []) const filename = 'npm-test-package-1.0.0.tgz' - t.strictSame(outputs, [[filename]]) + t.strictSame(outputs, [filename]) t.ok(fs.statSync(path.resolve(npm.prefix, filename))) }) @@ -67,7 +67,7 @@ t.test('should log output as valid json', async t => { await npm.exec('pack', []) const filename = 'test-package-1.0.0.tgz' t.matchSnapshot(outputs.map(JSON.parse), 'outputs as json') - t.matchSnapshot(logs.notice.map(([, m]) => m), 'logs pack contents') + t.matchSnapshot(logs.notice, 'logs pack contents') t.ok(fs.statSync(path.resolve(npm.prefix, filename))) }) @@ -84,7 +84,7 @@ t.test('should log scoped package output as valid json', async t => { await npm.exec('pack', []) const filename = 'myscope-test-package-1.0.0.tgz' t.matchSnapshot(outputs.map(JSON.parse), 'outputs as json') - t.matchSnapshot(logs.notice.map(([, m]) => m), 'logs pack contents') + t.matchSnapshot(logs.notice, 'logs pack contents') t.ok(fs.statSync(path.resolve(npm.prefix, filename))) }) @@ -100,8 +100,8 @@ t.test('dry run', async t => { }) await npm.exec('pack', []) const filename = 'test-package-1.0.0.tgz' - t.strictSame(outputs, [[filename]]) - t.matchSnapshot(logs.notice.map(([, m]) => m), 'logs pack contents') + t.strictSame(outputs, [filename]) + t.matchSnapshot(logs.notice, 'logs pack contents') t.throws(() => fs.statSync(path.resolve(npm.prefix, filename))) }) @@ -142,8 +142,8 @@ t.test('foreground-scripts defaults to true', async t => { ['\n> test-fg-scripts@0.0.0 postpack\n> echo postpack!\n'], ], 'prepack and postpack log to stdout') - t.strictSame(outputs, [[filename]]) - t.matchSnapshot(logs.notice.map(([, m]) => m), 'logs pack contents') + t.strictSame(outputs, [filename]) + t.matchSnapshot(logs.notice, 'logs pack contents') t.throws(() => fs.statSync(path.resolve(npm.prefix, filename))) }) @@ -181,8 +181,8 @@ t.test('foreground-scripts can still be set to false', async t => { caughtLogs, [], 'prepack and postpack do not log to stdout') - t.strictSame(outputs, [[filename]]) - t.matchSnapshot(logs.notice.map(([, m]) => m), 'logs pack contents') + t.strictSame(outputs, [filename]) + t.matchSnapshot(logs.notice, 'logs pack contents') t.throws(() => fs.statSync(path.resolve(npm.prefix, filename))) }) @@ -235,24 +235,24 @@ t.test('workspaces', async t => { t.test('all workspaces', async t => { const { npm, outputs } = await loadWorkspaces(t) await npm.exec('pack', []) - t.strictSame(outputs, [['workspace-a-1.0.0.tgz'], ['workspace-b-1.0.0.tgz']]) + t.strictSame(outputs, ['workspace-a-1.0.0.tgz', 'workspace-b-1.0.0.tgz']) }) t.test('all workspaces, `.` first arg', async t => { const { npm, outputs } = await loadWorkspaces(t) await npm.exec('pack', ['.']) - t.strictSame(outputs, [['workspace-a-1.0.0.tgz'], ['workspace-b-1.0.0.tgz']]) + t.strictSame(outputs, ['workspace-a-1.0.0.tgz', 'workspace-b-1.0.0.tgz']) }) t.test('one workspace', async t => { const { npm, outputs } = await loadWorkspaces(t) await npm.exec('pack', ['workspace-a']) - t.strictSame(outputs, [['workspace-a-1.0.0.tgz']]) + t.strictSame(outputs, ['workspace-a-1.0.0.tgz']) }) t.test('specific package', async t => { const { npm, outputs } = await loadWorkspaces(t) await npm.exec('pack', [npm.prefix]) - t.strictSame(outputs, [['workspaces-test-1.0.0.tgz']]) + t.strictSame(outputs, ['workspaces-test-1.0.0.tgz']) }) }) diff --git a/test/lib/commands/ping.js b/test/lib/commands/ping.js index 77201955ff2a8..7f90ea394f9ae 100644 --- a/test/lib/commands/ping.js +++ b/test/lib/commands/ping.js @@ -10,7 +10,10 @@ t.test('no details', async t => { }) registry.ping() await npm.exec('ping', []) - t.match(logs.notice, [['PING', 'https://registry.npmjs.org/'], ['PONG', /[0-9]+ms/]]) + t.match(logs.notice, [ + 'PING https://registry.npmjs.org/', + /PONG [0-9]+ms/, + ]) t.equal(joinedOutput(), '') }) @@ -20,12 +23,12 @@ t.test('with details', async t => { tap: t, registry: npm.config.get('registry'), }) - registry.ping({ body: { test: true } }) + registry.ping({ body: { test: true, test2: true } }) await npm.exec('ping', []) t.match(logs.notice, [ - ['PING', 'https://registry.npmjs.org/'], - ['PONG', /[0-9]+ms/], - ['PONG', '{\n "test": true\n}'], + `PING https://registry.npmjs.org/`, + /PONG [0-9]+ms/, + `PONG {\nPONG "test": true,\nPONG "test2": true\nPONG }`, ]) t.match(joinedOutput(), '') }) @@ -40,7 +43,10 @@ t.test('valid json', async t => { }) registry.ping() await npm.exec('ping', []) - t.match(logs.notice, [['PING', 'https://registry.npmjs.org/'], ['PONG', /[0-9]+ms/]]) + t.match(logs.notice, [ + 'PING https://registry.npmjs.org/', + /PONG [0-9]+ms/, + ]) t.match(JSON.parse(joinedOutput()), { registry: npm.config.get('registry'), time: /[0-9]+/, @@ -58,7 +64,10 @@ t.test('invalid json', async t => { }) registry.ping({ body: '{not: real"json]' }) await npm.exec('ping', []) - t.match(logs.notice, [['PING', 'https://registry.npmjs.org/'], ['PONG', /[0-9]+ms/]]) + t.match(logs.notice, [ + 'PING https://registry.npmjs.org/', + /PONG [0-9]+ms/, + ]) t.match(JSON.parse(joinedOutput()), { registry: npm.config.get('registry'), time: /[0-9]+/, diff --git a/test/lib/commands/profile.js b/test/lib/commands/profile.js index 784523f7ccd8a..c6cf2a071dcfa 100644 --- a/test/lib/commands/profile.js +++ b/test/lib/commands/profile.js @@ -473,8 +473,8 @@ t.test('profile set ', async t => { await profile.exec(['set', 'password']) t.equal( - logs.warn[0][1], - 'Passwords do not match, please try again.', + logs.warn.byTitle('profile')[0], + 'profile Passwords do not match, please try again.', 'should log password mismatch message' ) diff --git a/test/lib/commands/query.js b/test/lib/commands/query.js index 5292c50e1d365..0907a9d0f4206 100644 --- a/test/lib/commands/query.js +++ b/test/lib/commands/query.js @@ -258,7 +258,7 @@ t.test('expect entries', t => { npm.config.set('expect-results', false) await npm.exec('query', ['#a']) t.not(joinedOutput(), '[]', 'has entries') - t.same(logs.warn, [['query', 'Expected no results, got 1']]) + t.same(logs.warn.byTitle('query'), ['query Expected no results, got 1']) t.ok(process.exitCode, 'exits with code') }) t.test('false, no entries', async t => { @@ -286,7 +286,7 @@ t.test('expect entries', t => { npm.config.set('expect-results', true) await npm.exec('query', ['#b']) t.equal(joinedOutput(), '[]', 'does not have entries') - t.same(logs.warn, [['query', 'Expected results, got 0']]) + t.same(logs.warn.byTitle('query'), ['query Expected results, got 0']) t.ok(process.exitCode, 'exits with code') }) t.test('count, matches', async t => { @@ -305,7 +305,7 @@ t.test('expect entries', t => { npm.config.set('expect-result-count', 1) await npm.exec('query', ['#b']) t.equal(joinedOutput(), '[]', 'does not have entries') - t.same(logs.warn, [['query', 'Expected 1 result, got 0']]) + t.same(logs.warn.byTitle('query'), ['query Expected 1 result, got 0']) t.ok(process.exitCode, 'exits with code') }) t.test('count 3, does not match', async t => { @@ -315,7 +315,7 @@ t.test('expect entries', t => { npm.config.set('expect-result-count', 3) await npm.exec('query', ['#b']) t.equal(joinedOutput(), '[]', 'does not have entries') - t.same(logs.warn, [['query', 'Expected 3 results, got 0']]) + t.same(logs.warn.byTitle('query'), ['query Expected 3 results, got 0']) t.ok(process.exitCode, 'exits with code') }) t.end() diff --git a/test/lib/commands/run-script.js b/test/lib/commands/run-script.js index 24f51400e8dfc..a110037c8031c 100644 --- a/test/lib/commands/run-script.js +++ b/test/lib/commands/run-script.js @@ -30,7 +30,7 @@ const mockRs = async (t, { windows = false, runScript, ...opts } = {}) => { ...mock, RUN_SCRIPTS: () => RUN_SCRIPTS, runScript: mock['run-script'], - cleanLogs: () => mock.logs.error.flat().map(v => v.toString()).map(cleanCwd), + cleanLogs: () => mock.logs.error.map(cleanCwd), } } @@ -428,14 +428,14 @@ t.test('list scripts', async t => { t.strictSame( output, [ - ['Lifecycle scripts included in x@1.2.3:'], - [' test\n exit 2'], - [' start\n node server.js'], - [' stop\n node kill-server.js'], - ['\navailable via `npm run-script`:'], - [' preenv\n echo before the env'], - [' postenv\n echo after the env'], - [''], + 'Lifecycle scripts included in x@1.2.3:', + ' test\n exit 2', + ' start\n node server.js', + ' stop\n node kill-server.js', + '\navailable via `npm run-script`:', + ' preenv\n echo before the env', + ' postenv\n echo after the env', + '', ], 'basic report' ) @@ -447,17 +447,17 @@ t.test('list scripts', async t => { }) t.test('warn json', async t => { const outputs = await mockList(t, { json: true }) - t.strictSame(outputs, [[JSON.stringify(scripts, 0, 2)]], 'json report') + t.strictSame(outputs, [JSON.stringify(scripts, 0, 2)], 'json report') }) t.test('parseable', async t => { const outputs = await mockList(t, { parseable: true }) t.strictSame(outputs, [ - ['test:exit 2'], - ['start:node server.js'], - ['stop:node kill-server.js'], - ['preenv:echo before the env'], - ['postenv:echo after the env'], + 'test:exit 2', + 'start:node server.js', + 'stop:node kill-server.js', + 'preenv:echo before the env', + 'postenv:echo after the env', ]) }) }) @@ -489,9 +489,9 @@ t.test('list scripts, only commands', async t => { await runScript.exec([]) t.strictSame(outputs, [ - ['Lifecycle scripts included in x@1.2.3:'], - [' preversion\n echo doing the version dance'], - [''], + 'Lifecycle scripts included in x@1.2.3:', + ' preversion\n echo doing the version dance', + '', ]) }) @@ -508,9 +508,9 @@ t.test('list scripts, only non-commands', async t => { await runScript.exec([]) t.strictSame(outputs, [ - ['Scripts available in x@1.2.3 via `npm run-script`:'], - [' glorp\n echo doing the glerp glop'], - [''], + 'Scripts available in x@1.2.3 via `npm run-script`:', + ' glorp\n echo doing the glerp glop', + '', ]) }) @@ -594,113 +594,109 @@ t.test('workspaces', async t => { t.test('list all scripts', async t => { const { outputs } = await mockWorkspaces(t) t.strictSame(outputs, [ - ['Scripts available in a@1.0.0 via `npm run-script`:'], - [' glorp\n echo a doing the glerp glop'], - [''], - ['Scripts available in b@2.0.0 via `npm run-script`:'], - [' glorp\n echo b doing the glerp glop'], - [''], - ['Lifecycle scripts included in c@1.0.0:'], - [' test\n exit 0'], - [' posttest\n echo posttest'], - ['\navailable via `npm run-script`:'], - [' lorem\n echo c lorem'], - [''], - ['Lifecycle scripts included in d@1.0.0:'], - [' test\n exit 0'], - [' posttest\n echo posttest'], - [''], - ['Lifecycle scripts included in e:'], - [' test\n exit 0'], - [' start\n echo start something'], - [''], + 'Scripts available in a@1.0.0 via `npm run-script`:', + ' glorp\n echo a doing the glerp glop', + '', + 'Scripts available in b@2.0.0 via `npm run-script`:', + ' glorp\n echo b doing the glerp glop', + '', + 'Lifecycle scripts included in c@1.0.0:', + ' test\n exit 0', + ' posttest\n echo posttest', + '\navailable via `npm run-script`:', + ' lorem\n echo c lorem', + '', + 'Lifecycle scripts included in d@1.0.0:', + ' test\n exit 0', + ' posttest\n echo posttest', + '', + 'Lifecycle scripts included in e:', + ' test\n exit 0', + ' start\n echo start something', + '', ]) }) t.test('list regular scripts, filtered by name', async t => { const { outputs } = await mockWorkspaces(t, { workspaces: ['a', 'b'] }) t.strictSame(outputs, [ - ['Scripts available in a@1.0.0 via `npm run-script`:'], - [' glorp\n echo a doing the glerp glop'], - [''], - ['Scripts available in b@2.0.0 via `npm run-script`:'], - [' glorp\n echo b doing the glerp glop'], - [''], + 'Scripts available in a@1.0.0 via `npm run-script`:', + ' glorp\n echo a doing the glerp glop', + '', + 'Scripts available in b@2.0.0 via `npm run-script`:', + ' glorp\n echo b doing the glerp glop', + '', ]) }) t.test('list regular scripts, filtered by path', async t => { const { outputs } = await mockWorkspaces(t, { workspaces: ['./packages/a'] }) t.strictSame(outputs, [ - ['Scripts available in a@1.0.0 via `npm run-script`:'], - [' glorp\n echo a doing the glerp glop'], - [''], + 'Scripts available in a@1.0.0 via `npm run-script`:', + ' glorp\n echo a doing the glerp glop', + '', ]) }) t.test('list regular scripts, filtered by parent folder', async t => { const { outputs } = await mockWorkspaces(t, { workspaces: ['./packages'] }) t.strictSame(outputs, [ - ['Scripts available in a@1.0.0 via `npm run-script`:'], - [' glorp\n echo a doing the glerp glop'], - [''], - ['Scripts available in b@2.0.0 via `npm run-script`:'], - [' glorp\n echo b doing the glerp glop'], - [''], - ['Lifecycle scripts included in c@1.0.0:'], - [' test\n exit 0'], - [' posttest\n echo posttest'], - ['\navailable via `npm run-script`:'], - [' lorem\n echo c lorem'], - [''], - ['Lifecycle scripts included in d@1.0.0:'], - [' test\n exit 0'], - [' posttest\n echo posttest'], - [''], - ['Lifecycle scripts included in e:'], - [' test\n exit 0'], - [' start\n echo start something'], - [''], + 'Scripts available in a@1.0.0 via `npm run-script`:', + ' glorp\n echo a doing the glerp glop', + '', + 'Scripts available in b@2.0.0 via `npm run-script`:', + ' glorp\n echo b doing the glerp glop', + '', + 'Lifecycle scripts included in c@1.0.0:', + ' test\n exit 0', + ' posttest\n echo posttest', + '\navailable via `npm run-script`:', + ' lorem\n echo c lorem', + '', + 'Lifecycle scripts included in d@1.0.0:', + ' test\n exit 0', + ' posttest\n echo posttest', + '', + 'Lifecycle scripts included in e:', + ' test\n exit 0', + ' start\n echo start something', + '', ]) }) t.test('list all scripts with colors', async t => { const { outputs } = await mockWorkspaces(t, { color: 'always' }) t.strictSame(outputs, [ - [ - /* eslint-disable-next-line max-len */ - '\u001b[1mScripts\u001b[22m available in \x1B[32ma@1.0.0\x1B[39m via `\x1B[34mnpm run-script\x1B[39m`:', - ], - [' glorp\n \x1B[2mecho a doing the glerp glop\x1B[22m'], - [''], - [ - /* eslint-disable-next-line max-len */ - '\u001b[1mScripts\u001b[22m available in \x1B[32mb@2.0.0\x1B[39m via `\x1B[34mnpm run-script\x1B[39m`:', - ], - [' glorp\n \x1B[2mecho b doing the glerp glop\x1B[22m'], - [''], - ['\x1B[0m\x1B[1mLifecycle scripts\x1B[22m\x1B[0m included in \x1B[32mc@1.0.0\x1B[39m:'], - [' test\n \x1B[2mexit 0\x1B[22m'], - [' posttest\n \x1B[2mecho posttest\x1B[22m'], - ['\navailable via `\x1B[34mnpm run-script\x1B[39m`:'], - [' lorem\n \x1B[2mecho c lorem\x1B[22m'], - [''], - ['\x1B[0m\x1B[1mLifecycle scripts\x1B[22m\x1B[0m included in \x1B[32md@1.0.0\x1B[39m:'], - [' test\n \x1B[2mexit 0\x1B[22m'], - [' posttest\n \x1B[2mecho posttest\x1B[22m'], - [''], - ['\x1B[0m\x1B[1mLifecycle scripts\x1B[22m\x1B[0m included in \x1B[32me\x1B[39m:'], - [' test\n \x1B[2mexit 0\x1B[22m'], - [' start\n \x1B[2mecho start something\x1B[22m'], - [''], + /* eslint-disable-next-line max-len */ + '\u001b[1mScripts\u001b[22m available in \x1B[32ma@1.0.0\x1B[39m via `\x1B[34mnpm run-script\x1B[39m`:', + ' glorp\n \x1B[2mecho a doing the glerp glop\x1B[22m', + '', + /* eslint-disable-next-line max-len */ + '\u001b[1mScripts\u001b[22m available in \x1B[32mb@2.0.0\x1B[39m via `\x1B[34mnpm run-script\x1B[39m`:', + ' glorp\n \x1B[2mecho b doing the glerp glop\x1B[22m', + '', + '\x1B[0m\x1B[1mLifecycle scripts\x1B[22m\x1B[0m included in \x1B[32mc@1.0.0\x1B[39m:', + ' test\n \x1B[2mexit 0\x1B[22m', + ' posttest\n \x1B[2mecho posttest\x1B[22m', + '\navailable via `\x1B[34mnpm run-script\x1B[39m`:', + ' lorem\n \x1B[2mecho c lorem\x1B[22m', + '', + '\x1B[0m\x1B[1mLifecycle scripts\x1B[22m\x1B[0m included in \x1B[32md@1.0.0\x1B[39m:', + ' test\n \x1B[2mexit 0\x1B[22m', + ' posttest\n \x1B[2mecho posttest\x1B[22m', + '', + '\x1B[0m\x1B[1mLifecycle scripts\x1B[22m\x1B[0m included in \x1B[32me\x1B[39m:', + ' test\n \x1B[2mexit 0\x1B[22m', + ' start\n \x1B[2mecho start something\x1B[22m', + '', ]) }) t.test('list all scripts --json', async t => { const { outputs } = await mockWorkspaces(t, { json: true }) t.strictSame(outputs, [ - [ - '{\n' + + + '{\n' + ' "a": {\n' + ' "glorp": "echo a doing the glerp glop"\n' + ' },\n' + @@ -722,22 +718,22 @@ t.test('workspaces', async t => { ' },\n' + ' "noscripts": {}\n' + '}', - ], + ]) }) t.test('list all scripts --parseable', async t => { const { outputs } = await mockWorkspaces(t, { parseable: true }) t.strictSame(outputs, [ - ['a:glorp:echo a doing the glerp glop'], - ['b:glorp:echo b doing the glerp glop'], - ['c:test:exit 0'], - ['c:posttest:echo posttest'], - ['c:lorem:echo c lorem'], - ['d:test:exit 0'], - ['d:posttest:echo posttest'], - ['e:test:exit 0'], - ['e:start:echo start something'], + 'a:glorp:echo a doing the glerp glop', + 'b:glorp:echo b doing the glerp glop', + 'c:test:exit 0', + 'c:posttest:echo posttest', + 'c:lorem:echo c lorem', + 'd:test:exit 0', + 'd:posttest:echo posttest', + 'e:test:exit 0', + 'e:start:echo start something', ]) }) diff --git a/test/lib/commands/search.js b/test/lib/commands/search.js index 596c849909229..56d0437c18f93 100644 --- a/test/lib/commands/search.js +++ b/test/lib/commands/search.js @@ -140,7 +140,7 @@ t.test('empty search results --json', async t => { registry.search({ results: [] }) await npm.exec('search', ['foo']) - t.equal(joinedOutput(), '\n[]\n', 'should have expected empty square brackets') + t.equal(joinedOutput(), '\n[]', 'should have expected empty square brackets') }) t.test('search api response error', async t => { diff --git a/test/lib/commands/shrinkwrap.js b/test/lib/commands/shrinkwrap.js index 604a7db7a0b35..c5909a3ceaeac 100644 --- a/test/lib/commands/shrinkwrap.js +++ b/test/lib/commands/shrinkwrap.js @@ -24,9 +24,8 @@ t.formatSnapshot = obj => // Run shrinkwrap against a specified prefixDir with config items // and make some assertions that should always be true. Sets // the results on t.context for use in child tests -const shrinkwrap = async (t, prefixDir = {}, config = {}, mocks = {}) => { +const shrinkwrap = async (t, prefixDir = {}, config = {}) => { const { npm, logs } = await loadMockNpm(t, { - mocks, config, prefixDir, }) @@ -37,13 +36,13 @@ const shrinkwrap = async (t, prefixDir = {}, config = {}, mocks = {}) => { const oldFile = resolve(npm.prefix, 'package-lock.json') t.notOk(fs.existsSync(oldFile), 'package-lock is always deleted') - t.same(logs.warn, [], 'no warnings') t.teardown(() => delete t.context) t.context = { localPrefix: prefixDir, config, shrinkwrap: JSON.parse(fs.readFileSync(newFile)), - logs: logs.notice.map(([, m]) => m), + logs: logs.notice, + warn: logs.warn, } } @@ -107,6 +106,8 @@ const NOTICES = { ], UPDATED: (v = '') => [`npm-shrinkwrap.json updated to version ${v}`], SAME: () => [`npm-shrinkwrap.json up to date`], + CONVERTING: (current, next) => + [`Converting lock file (npm-shrinkwrap.json) from v${current} -> v${next}`], } t.test('with nothing', t => @@ -114,10 +115,12 @@ t.test('with nothing', t => ancient: { shrinkwrap: { lockfileVersion: 3 }, logs: NOTICES.CREATED(3), + warn: [], }, ancientUpgrade: { shrinkwrap: { lockfileVersion: 3 }, logs: NOTICES.CREATED(3), + warn: [], }, }) ) @@ -127,22 +130,27 @@ t.test('with package-lock.json', t => ancient: { shrinkwrap: { lockfileVersion: 3 }, logs: NOTICES.RENAMED(3), + warn: NOTICES.CONVERTING(1, 3), }, ancientUpgrade: { shrinkwrap: { lockfileVersion: 3 }, logs: NOTICES.RENAMED(3), + warn: NOTICES.CONVERTING(1, 3), }, existing: { shrinkwrap: { lockfileVersion: 2 }, logs: NOTICES.RENAMED(), + warn: [], }, existingUpgrade: { shrinkwrap: { lockfileVersion: 3 }, logs: NOTICES.RENAMED(3), + warn: NOTICES.CONVERTING(2, 3), }, existingDowngrade: { shrinkwrap: { lockfileVersion: 1 }, logs: NOTICES.RENAMED(1), + warn: NOTICES.CONVERTING(2, 1), }, }) ) @@ -152,22 +160,27 @@ t.test('with npm-shrinkwrap.json', t => ancient: { shrinkwrap: { lockfileVersion: 3 }, logs: NOTICES.UPDATED(3), + warn: NOTICES.CONVERTING(1, 3), }, ancientUpgrade: { shrinkwrap: { lockfileVersion: 3 }, logs: NOTICES.UPDATED(3), + warn: NOTICES.CONVERTING(1, 3), }, existing: { shrinkwrap: { lockfileVersion: 2 }, logs: NOTICES.SAME(), + warn: [], }, existingUpgrade: { shrinkwrap: { lockfileVersion: 3 }, logs: NOTICES.UPDATED(3), + warn: NOTICES.CONVERTING(2, 3), }, existingDowngrade: { shrinkwrap: { lockfileVersion: 1 }, logs: NOTICES.UPDATED(1), + warn: NOTICES.CONVERTING(2, 1), }, }) ) @@ -177,22 +190,27 @@ t.test('with hidden lockfile', t => ancient: { shrinkwrap: { lockfileVersion: 1 }, logs: NOTICES.CREATED(), + warn: [], }, ancientUpgrade: { shrinkwrap: { lockfileVersion: 3 }, logs: NOTICES.CREATED(), + warn: NOTICES.CONVERTING(1, 3), }, existing: { shrinkwrap: { lockfileVersion: 2 }, logs: NOTICES.CREATED(), + warn: [], }, existingUpgrade: { shrinkwrap: { lockfileVersion: 3 }, logs: NOTICES.CREATED(3), + warn: NOTICES.CONVERTING(2, 3), }, existingDowngrade: { shrinkwrap: { lockfileVersion: 1 }, logs: NOTICES.CREATED(1), + warn: NOTICES.CONVERTING(2, 1), }, }) ) diff --git a/test/lib/commands/stars.js b/test/lib/commands/stars.js index d92ced950291f..fc38ca77ac781 100644 --- a/test/lib/commands/stars.js +++ b/test/lib/commands/stars.js @@ -18,7 +18,7 @@ const mockStars = async (t, { npmFetch = noop, exec = true, ...opts }) => { return { ...mock, result: mock.stars.output, - logs: () => mock.logs.filter(l => l[1] === 'stars').map(l => l[2]), + logs: () => mock.logs.byTitle('stars'), } } @@ -87,7 +87,7 @@ t.test('unauthorized request', async t => { t.strictSame( logs(), - ['auth is required to look up your username'], + ['stars auth is required to look up your username'], 'should warn auth required msg' ) @@ -121,7 +121,7 @@ t.test('no pkg starred', async t => { t.strictSame( logs(), - ['user has not starred any packages'], + ['stars user has not starred any packages'], 'should warn no starred packages msg' ) }) diff --git a/test/lib/commands/update.js b/test/lib/commands/update.js index f42fb8a4146b0..e84e2c3142141 100644 --- a/test/lib/commands/update.js +++ b/test/lib/commands/update.js @@ -64,10 +64,8 @@ t.test('update --depth=', async t => { config: { depth: 1 }, }) - const [title, msg] = logs.warn[0] - t.equal(title, 'update', 'should print expected title') t.match( - msg, + logs.warn.byTitle('update')[0], /The --depth option no longer has any effect/, 'should print expected warning message' ) diff --git a/test/lib/commands/version.js b/test/lib/commands/version.js index 8aa6c088bfc9b..755caae444310 100644 --- a/test/lib/commands/version.js +++ b/test/lib/commands/version.js @@ -36,11 +36,7 @@ t.test('node@1', async t => { t.strictSame( result(), - [{ - 'test-version-no-args': '3.2.1', - node: '1.0.0', - npm: '1.0.0', - }], + "{ 'test-version-no-args': '3.2.1', npm: '1.0.0', node: '1.0.0' }", 'should output expected values for various versions in npm' ) }) @@ -75,10 +71,7 @@ t.test('node@1', async t => { t.strictSame( result(), - [{ - npm: '1.0.0', - node: '1.0.0', - }], + `{ npm: '1.0.0', node: '1.0.0' }`, 'should not have package name on returning object' ) }) @@ -93,7 +86,7 @@ t.test('empty versions', async t => { }) await version.exec([]) - t.same(result(), ['{\n "npm": "1.0.0"\n}'], 'should return json stringified result') + t.same(result(), '{\n "npm": "1.0.0"\n}', 'should return json stringified result') }) t.test('with one arg', async t => { @@ -104,7 +97,7 @@ t.test('empty versions', async t => { }) await version.exec(['major']) - t.same(result(), ['v4.0.0'], 'outputs the new version prefixed by the tagVersionPrefix') + t.same(result(), 'v4.0.0', 'outputs the new version prefixed by the tagVersionPrefix') }) t.test('workspaces', async t => { @@ -139,14 +132,12 @@ t.test('empty versions', async t => { await version.exec([]) t.same( result(), - [ - { - 'workspaces-test': '1.0.0', - 'workspace-a': '1.0.0', - 'workspace-b': '1.0.0', - npm: '1.0.0', - }, - ], + `{ + 'workspace-a': '1.0.0', + 'workspace-b': '1.0.0', + 'workspaces-test': '1.0.0', + npm: '1.0.0' +}`, 'outputs includes main package and workspace versions' ) }) @@ -184,13 +175,7 @@ t.test('empty versions', async t => { await version.exec([]) t.same( result(), - [ - { - 'workspaces-test': '1.0.0', - 'workspace-a': '1.0.0', - npm: '1.0.0', - }, - ], + "{ 'workspace-a': '1.0.0', 'workspaces-test': '1.0.0', npm: '1.0.0' }", 'outputs includes main package and requested workspace versions' ) }) @@ -230,13 +215,7 @@ t.test('empty versions', async t => { await version.exec([]) t.same( result(), - [ - { - 'workspaces-test': '1.0.0', - 'workspace-a': '1.0.0', - npm: '1.0.0', - }, - ], + "{ 'workspace-a': '1.0.0', 'workspaces-test': '1.0.0', npm: '1.0.0' }", 'outputs includes main package and valid workspace versions' ) }) @@ -271,7 +250,7 @@ t.test('empty versions', async t => { await version.exec(['major']) t.same( - outputs.map(o => o[0]).slice(0, 4), + outputs.slice(0, 4), ['workspace-a', 'v2.0.0', 'workspace-b', 'v2.0.0'], 'outputs the new version for only the workspaces prefixed by the tagVersionPrefix' ) @@ -316,7 +295,7 @@ t.test('empty versions', async t => { await version.exec(['major']) t.same( - outputs.map(o => o[0]).slice(0, 4), + outputs.slice(0, 4), ['workspace-a', 'v2.0.0', 'workspace-b', 'v2.0.0'], 'outputs the new version for only the workspaces prefixed by the tagVersionPrefix' ) @@ -372,7 +351,7 @@ t.test('empty versions', async t => { await version.exec(['major']) t.same( - outputs.map(o => o[0]).slice(0, 4), + outputs.slice(0, 4), ['workspace-a', 'v2.0.0', 'workspace-b', 'v2.0.0'], 'outputs the new version for only the workspaces prefixed by the tagVersionPrefix' ) diff --git a/test/lib/commands/view.js b/test/lib/commands/view.js index 92c7fe47bda06..0bbba8b2bda6a 100644 --- a/test/lib/commands/view.js +++ b/test/lib/commands/view.js @@ -282,81 +282,81 @@ const loadMockNpm = async function (t, opts = {}) { } t.test('package from git', async t => { - const { view, outputs } = await loadMockNpm(t, { config: { unicode: false } }) + const { view, joinedOutput } = await loadMockNpm(t, { config: { unicode: false } }) await view.exec(['https://github.com/npm/green']) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('deprecated package with license, bugs, repository and other fields', async t => { - const { view, outputs } = await loadMockNpm(t, { config: { unicode: false } }) + const { view, joinedOutput } = await loadMockNpm(t, { config: { unicode: false } }) await view.exec(['green@1.0.0']) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('deprecated package with unicode', async t => { - const { view, outputs } = await loadMockNpm(t, { config: { unicode: true } }) + const { view, joinedOutput } = await loadMockNpm(t, { config: { unicode: true } }) await view.exec(['green@1.0.0']) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('package with more than 25 deps', async t => { - const { view, outputs } = await loadMockNpm(t, { config: { unicode: false } }) + const { view, joinedOutput } = await loadMockNpm(t, { config: { unicode: false } }) await view.exec(['black@1.0.0']) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('package with maintainers info as object', async t => { - const { view, outputs } = await loadMockNpm(t, { config: { unicode: false } }) + const { view, joinedOutput } = await loadMockNpm(t, { config: { unicode: false } }) await view.exec(['pink@1.0.0']) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('package with homepage', async t => { - const { view, outputs } = await loadMockNpm(t, { config: { unicode: false } }) + const { view, joinedOutput } = await loadMockNpm(t, { config: { unicode: false } }) await view.exec(['orange@1.0.0']) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('package with invalid version', async t => { - const { view, outputs } = await loadMockNpm(t, { config: { unicode: false } }) + const { view, joinedOutput } = await loadMockNpm(t, { config: { unicode: false } }) await view.exec(['orange', 'versions']) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('package with no versions', async t => { - const { view, outputs } = await loadMockNpm(t, { config: { unicode: false } }) + const { view, joinedOutput } = await loadMockNpm(t, { config: { unicode: false } }) await view.exec(['brown']) - t.equal(outputs.join('\n'), '', 'no info to display') + t.equal(joinedOutput(), '', 'no info to display') }) t.test('package with no repo or homepage', async t => { - const { view, outputs } = await loadMockNpm(t, { config: { unicode: false } }) + const { view, joinedOutput } = await loadMockNpm(t, { config: { unicode: false } }) await view.exec(['blue@1.0.0']) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('package with semver range', async t => { - const { view, outputs } = await loadMockNpm(t, { config: { unicode: false } }) + const { view, joinedOutput } = await loadMockNpm(t, { config: { unicode: false } }) await view.exec(['blue@^1.0.0']) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('package with no modified time', async t => { - const { view, outputs } = await loadMockNpm(t, { config: { unicode: false } }) + const { view, joinedOutput } = await loadMockNpm(t, { config: { unicode: false } }) await view.exec(['cyan@1.0.0']) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('package with --json and semver range', async t => { - const { view, outputs } = await loadMockNpm(t, { config: { json: true } }) + const { view, joinedOutput } = await loadMockNpm(t, { config: { json: true } }) await view.exec(['cyan@^1.0.0']) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('package with --json and no versions', async t => { - const { view, outputs } = await loadMockNpm(t, { config: { json: true } }) + const { view, joinedOutput } = await loadMockNpm(t, { config: { json: true } }) await view.exec(['brown']) - t.equal(outputs.join('\n'), '', 'no info to display') + t.equal(joinedOutput(), '', 'no info to display') }) t.test('package in cwd', async t => { @@ -368,76 +368,76 @@ t.test('package in cwd', async t => { } t.test('specific version', async t => { - const { view, outputs } = await loadMockNpm(t, { prefixDir }) + const { view, joinedOutput } = await loadMockNpm(t, { prefixDir }) await view.exec(['.@1.0.0']) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('non-specific version', async t => { - const { view, outputs } = await loadMockNpm(t, { prefixDir }) + const { view, joinedOutput } = await loadMockNpm(t, { prefixDir }) await view.exec(['.']) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('directory', async t => { - const { view, outputs } = await loadMockNpm(t, { prefixDir }) + const { view, joinedOutput } = await loadMockNpm(t, { prefixDir }) await view.exec(['./blue']) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) }) t.test('specific field names', async t => { - const { view, outputs } = await loadMockNpm(t, { config: { color: false } }) - t.afterEach(() => outputs.length = 0) + const { view, joinedOutput, clearOutput } = await loadMockNpm(t, { config: { color: false } }) + t.afterEach(() => clearOutput()) t.test('readme', async t => { await view.exec(['yellow@1.0.0', 'readme']) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('several fields', async t => { await view.exec(['yellow@1.0.0', 'name', 'version', 'foo[bar]']) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('several fields with several versions', async t => { await view.exec(['yellow@1.x.x', 'author']) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('nested field with brackets', async t => { await view.exec(['orange@1.0.0', 'dist[shasum]']) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('maintainers with email', async t => { await view.exec(['yellow@1.0.0', 'maintainers', 'name']) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('maintainers with url', async t => { await view.exec(['pink@1.0.0', 'maintainers']) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('unknown nested field ', async t => { await view.exec(['yellow@1.0.0', 'dist.foobar']) - t.equal(outputs.join('\n'), '', 'no info to display') + t.equal(joinedOutput(), '', 'no info to display') }) t.test('array field - 1 element', async t => { await view.exec(['purple@1.0.0', 'maintainers.name']) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('array field - 2 elements', async t => { await view.exec(['yellow@1.x.x', 'maintainers.name']) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('fields with empty values', async t => { await view.exec(['yellow', 'empty']) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) }) @@ -507,84 +507,84 @@ t.test('workspaces', async t => { } t.test('all workspaces', async t => { - const { view, outputs } = await loadMockNpm(t, { + const { view, joinedOutput } = await loadMockNpm(t, { prefixDir, config: { unicode: false, workspaces: true }, }) await view.exec([]) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('one specific workspace', async t => { - const { view, outputs } = await loadMockNpm(t, { + const { view, joinedOutput } = await loadMockNpm(t, { prefixDir, config: { unicode: false, workspace: ['green'] }, }) await view.exec([]) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('all workspaces --json', async t => { - const { view, outputs } = await loadMockNpm(t, { + const { view, joinedOutput } = await loadMockNpm(t, { prefixDir, config: { unicode: false, workspaces: true, json: true }, }) await view.exec([]) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('all workspaces single field', async t => { - const { view, outputs } = await loadMockNpm(t, { + const { view, joinedOutput } = await loadMockNpm(t, { prefixDir, config: { unicode: false, workspaces: true }, }) await view.exec(['.', 'name']) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('all workspaces nonexistent field', async t => { - const { view, outputs } = await loadMockNpm(t, { + const { view, joinedOutput } = await loadMockNpm(t, { prefixDir, config: { unicode: false, workspaces: true }, }) await view.exec(['.', 'foo']) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('all workspaces nonexistent field --json', async t => { - const { view, outputs } = await loadMockNpm(t, { + const { view, joinedOutput } = await loadMockNpm(t, { prefixDir, config: { unicode: false, workspaces: true, json: true }, }) await view.exec(['.', 'foo']) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('all workspaces single field --json', async t => { - const { view, outputs } = await loadMockNpm(t, { + const { view, joinedOutput } = await loadMockNpm(t, { prefixDir, config: { unicode: false, workspaces: true, json: true }, }) await view.exec(['.', 'name']) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('single workspace --json', async t => { - const { view, outputs } = await loadMockNpm(t, { + const { view, joinedOutput } = await loadMockNpm(t, { prefixDir, config: { unicode: false, workspace: ['green'], json: true }, }) await view.exec([]) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) }) t.test('remote package name', async t => { - const { view, logs, outputs } = await loadMockNpm(t, { + const { view, logs, joinedOutput } = await loadMockNpm(t, { prefixDir, config: { unicode: false, workspaces: true }, }) await view.exec(['pink']) - t.matchSnapshot(outputs.join('\n')) + t.matchSnapshot(joinedOutput()) t.matchSnapshot(logs.warn, 'should have warning of ignoring workspaces') }) }) diff --git a/test/lib/load-all-commands.js b/test/lib/load-all-commands.js index d3846434489ce..9fa6995cfb1ad 100644 --- a/test/lib/load-all-commands.js +++ b/test/lib/load-all-commands.js @@ -72,8 +72,8 @@ t.test('load each command', async t => { // usage t.match(impl.usage, cmd, 'usage contains the command') await npm.exec(cmd, []) - t.match(outputs[0][0], impl.usage, 'usage is what is output') - t.match(outputs[0][0], ctor.describeUsage, 'usage is what is output') + t.match(outputs[0], impl.usage, 'usage is what is output') + t.match(outputs[0], ctor.describeUsage, 'usage is what is output') t.notOk(impl.describeUsage, 'describe usage is only static') }) } diff --git a/test/lib/npm.js b/test/lib/npm.js index e9300ecfa6bd1..ad776fc65b573 100644 --- a/test/lib/npm.js +++ b/test/lib/npm.js @@ -52,6 +52,9 @@ t.test('npm.load', async t => { otherDirs: { newCache: {}, }, + config: { + timing: true, + }, }) t.equal(npm.loaded, true) @@ -62,8 +65,9 @@ t.test('npm.load', async t => { t.match(npm, { flatOptions: {}, }) - t.match(logs.timing.filter(([p]) => p === 'npm:load'), [ - ['npm:load', /Completed in [0-9.]+ms/], + + t.match(logs.timing.filter((p) => /^npm:load/.test(p)), [ + /npm:load.* Completed in [0-9.]+ms/, ]) mockGlobals(t, { process: { platform: 'posix' } }) @@ -109,15 +113,12 @@ t.test('npm.load', async t => { await t.test('forceful loading', async t => { const { logs } = await loadMockNpm(t, { - globals: { - 'process.argv': [...process.argv, '--force', '--color', 'always'], + config: { + force: true, }, }) t.match(logs.warn, [ - [ - 'using --force', - 'Recommended protections disabled.', - ], + 'using --force Recommended protections disabled.', ]) }) @@ -127,33 +128,39 @@ t.test('npm.load', async t => { prefixDir: { bin: t.fixture('symlink', dirname(process.execPath)), }, + config: { + timing: true, + usage: '', + scope: 'foo', + }, + argv: [ + 'token', + 'revoke', + 'blergggg', + ], globals: (dirs) => ({ 'process.env.PATH': resolve(dirs.prefix, 'bin'), 'process.argv': [ node, process.argv[1], - '--usage', - '--scope=foo', - 'token', - 'revoke', - 'blergggg', ], }), }) t.equal(npm.config.get('scope'), '@foo', 'added the @ sign to scope') + t.match([ - ...logs.timing.filter(([p]) => p === 'npm:load:whichnode'), + ...logs.timing.filter((p) => p.startsWith('npm:load:whichnode')), ...logs.verbose, - ...logs.timing.filter(([p]) => p === 'npm:load'), + ...logs.timing.filter((p) => p.startsWith('npm:load')), ], [ - ['npm:load:whichnode', /Completed in [0-9.]+ms/], - ['node symlink', resolve(prefix, 'bin', node)], - ['title', 'npm token revoke blergggg'], - ['argv', '"--usage" "--scope" "foo" "token" "revoke" "blergggg"'], - ['logfile', /logs-max:\d+ dir:.*/], - ['logfile', /.*-debug-0.log/], - ['npm:load', /Completed in [0-9.]+ms/], + /npm:load:whichnode Completed in [0-9.]+ms/, + `node symlink ${resolve(prefix, 'bin', node)}`, + /title npm token revoke blergggg/, + /argv "token" "revoke" "blergggg".*"--usage" "--scope" "foo"/, + /logfile logs-max:\d+ dir:.*/, + /logfile .*-debug-0.log/, + /npm:load:.* Completed in [0-9.]+ms/, ]) t.equal(process.execPath, resolve(prefix, 'bin', node)) @@ -165,7 +172,7 @@ t.test('npm.load', async t => { t.equal(npm.flatOptions.npmCommand, 'll', 'npmCommand flatOption set') const ll = Npm.cmd('ll') - t.same(outputs, [[ll.describeUsage]], 'print usage') + t.same(outputs, [ll.describeUsage], 'print usage') npm.config.set('usage', false) outputs.length = 0 @@ -176,24 +183,11 @@ t.test('npm.load', async t => { 'does not change npm.command when another command is called') t.match(logs, [ - [ - 'error', - 'arg', - 'Argument starts with non-ascii dash, this is probably invalid:', - '\u2010not-a-dash', - ], - [ - 'timing', - 'command:config', - /Completed in [0-9.]+ms/, - ], - [ - 'timing', - 'command:get', - /Completed in [0-9.]+ms/, - ], + 'error arg Argument starts with non-ascii dash, this is probably invalid: \u2010not-a-dash', + /timing command:config Completed in [0-9.]+ms/, + /timing command:get Completed in [0-9.]+ms/, ]) - t.same(outputs, [['scope=@foo\n\u2010not-a-dash=undefined']]) + t.same(outputs, ['scope=@foo\n\u2010not-a-dash=undefined']) }) await t.test('--no-workspaces with --workspace', async t => { @@ -214,14 +208,9 @@ t.test('npm.load', async t => { workspaces: ['./packages/*'], }), }, - globals: { - 'process.argv': [ - process.execPath, - process.argv[1], - '--color', 'false', - '--workspaces', 'false', - '--workspace', 'a', - ], + config: { + workspaces: false, + workspace: 'a', }, }) await t.rejects( @@ -231,7 +220,7 @@ t.test('npm.load', async t => { }) await t.test('workspace-aware configs and commands', async t => { - const { npm, outputs } = await loadMockNpm(t, { + const { npm, joinedOutput } = await loadMockNpm(t, { prefixDir: { packages: { a: { @@ -255,13 +244,8 @@ t.test('npm.load', async t => { workspaces: ['./packages/*'], }), }, - globals: { - 'process.argv': [ - process.execPath, - process.argv[1], - '--color', 'false', - '--workspaces', 'true', - ], + config: { + workspaces: true, }, }) @@ -269,18 +253,7 @@ t.test('npm.load', async t => { t.equal(npm.command, 'run-script', 'npm.command set to canonical name') - t.match( - outputs, - [ - ['Lifecycle scripts included in a@1.0.0:'], - [' test\n echo test a'], - [''], - ['Lifecycle scripts included in b@1.0.0:'], - [' test\n echo test b'], - [''], - ], - 'should exec workspaces version of commands' - ) + t.matchSnapshot(joinedOutput(), 'should exec workspaces version of commands') }) await t.test('workspaces in global mode', async t => { @@ -308,16 +281,9 @@ t.test('npm.load', async t => { workspaces: ['./packages/*'], }), }, - globals: { - 'process.argv': [ - process.execPath, - process.argv[1], - '--color', - 'false', - '--workspaces', - '--global', - 'true', - ], + config: { + workspaces: true, + global: true, }, }) @@ -331,15 +297,11 @@ t.test('npm.load', async t => { t.test('set process.title', async t => { t.test('basic title setting', async t => { const { npm } = await loadMockNpm(t, { - globals: { - 'process.argv': [ - process.execPath, - process.argv[1], - '--usage', - '--scope=foo', - 'ls', - ], + config: { + usage: true, + scope: 'foo', }, + argv: ['ls'], }) t.equal(npm.title, 'npm ls') t.equal(process.title, 'npm ls') @@ -347,17 +309,11 @@ t.test('set process.title', async t => { t.test('do not expose token being revoked', async t => { const { npm } = await loadMockNpm(t, { - globals: { - 'process.argv': [ - process.execPath, - process.argv[1], - '--usage', - '--scope=foo', - 'token', - 'revoke', - `npm_${'a'.repeat(36)}`, - ], + config: { + usage: true, + scope: 'foo', }, + argv: ['token', 'revoke', `npm_${'a'.repeat(36)}`], }) t.equal(npm.title, 'npm token revoke npm_***') t.equal(process.title, 'npm token revoke npm_***') @@ -365,17 +321,11 @@ t.test('set process.title', async t => { t.test('do show *** unless a token is actually being revoked', async t => { const { npm } = await loadMockNpm(t, { - globals: { - 'process.argv': [ - process.execPath, - process.argv[1], - '--usage', - '--scope=foo', - 'token', - 'revoke', - 'notatoken', - ], + config: { + usage: true, + scope: 'foo', }, + argv: ['token', 'revoke', 'notatoken'], }) t.equal(npm.title, 'npm token revoke notatoken') t.equal(process.title, 'npm token revoke notatoken') @@ -443,7 +393,11 @@ t.test('cache dir', async t => { t.test('timings', async t => { t.test('gets/sets timers', async t => { - const { npm, logs } = await loadMockNpm(t, { load: false }) + const { npm, logs } = await loadMockNpm(t, { + config: { + timing: true, + }, + }) process.emit('time', 'foo') process.emit('time', 'bar') t.match(npm.unfinishedTimers.get('foo'), Number, 'foo timer is a number') @@ -453,16 +407,18 @@ t.test('timings', async t => { process.emit('timeEnd', 'baz') // npm timer is started by default process.emit('timeEnd', 'npm') - t.match(logs.timing, [ - ['foo', /Completed in [0-9]+ms/], - ['bar', /Completed in [0-9]+ms/], - ['npm', /Completed in [0-9]+ms/], + t.match(logs.timing.byTitle('foo'), [ + /Completed in [0-9]+ms/, + ]) + t.match(logs.timing.byTitle('bar'), [ + /Completed in [0-9]+ms/, + ]) + t.match(logs.timing.byTitle('npm'), [ + /Completed in [0-9]+ms/, + ]) + t.match(logs.silly, [ + `timing Tried to end timer that doesn't exist: baz`, ]) - t.match(logs.silly, [[ - 'timing', - "Tried to end timer that doesn't exist:", - 'baz', - ]]) t.notOk(npm.unfinishedTimers.has('foo'), 'foo timer is gone') t.notOk(npm.unfinishedTimers.has('bar'), 'bar timer is gone') t.match(npm.finishedTimers, { foo: Number, bar: Number, npm: Number }) @@ -513,42 +469,20 @@ t.test('timings', async t => { for (const [config, expectedDisplay, expectedTiming] of timingDisplay) { const msg = `${JSON.stringify(config)}, display:${expectedDisplay}, timing:${expectedTiming}` await t.test(`timing display: ${msg}`, async t => { - const { display } = await loadMockNpm(t, { config }) - t.equal(!!display.length, expectedDisplay, 'display') - t.equal(!!display.timing.length, expectedTiming, 'timing display') + const { logs } = await loadMockNpm(t, { config }) + t.equal(!!logs.length, expectedDisplay, 'display') + t.equal(!!logs.timing.length, expectedTiming, 'timing display') }) } }) -t.test('output clears progress and console.logs cleaned messages', async t => { - t.plan(4) - let showingProgress = true - const logs = [] - const errors = [] - const { npm } = await loadMockNpm(t, { - load: false, - mocks: { - npmlog: { - clearProgress: () => showingProgress = false, - showProgress: () => showingProgress = true, - }, - }, - globals: { - 'console.log': (...args) => { - t.equal(showingProgress, false, 'should not be showing progress right now') - logs.push(args) - }, - 'console.error': (...args) => { - t.equal(showingProgress, false, 'should not be showing progress right now') - errors.push(args) - }, - }, - }) - npm.originalOutput('hello\x00world') - npm.originalOutputError('error\x00world') +t.test('outputs cleaned messages', async t => { + const { outputs, outputErrors, npm } = await loadMockNpm(t) + npm.output('hello\x00world') + npm.outputError('error\x00world') - t.match(logs, [['hello^@world']]) - t.match(errors, [['error^@world']]) + t.match(outputs, ['hello^@world']) + t.match(outputErrors, ['error^@world']) }) t.test('aliases and typos', async t => { @@ -580,13 +514,8 @@ t.test('explicit workspace rejection', async t => { workspaces: ['./packages/a'], }), }, - globals: { - 'process.argv': [ - process.execPath, - process.argv[1], - '--color', 'false', - '--workspace', './packages/a', - ], + config: { + workspace: './packages/a', }, }) await t.rejects( @@ -614,13 +543,8 @@ t.test('implicit workspace rejection', async t => { }), }, chdir: ({ prefix }) => join(prefix, 'packages', 'a'), - globals: { - 'process.argv': [ - process.execPath, - process.argv[1], - '--color', 'false', - '--workspace', './packages/a', - ], + config: { + workspace: './packages/a', }, }) await t.rejects( @@ -648,13 +572,6 @@ t.test('implicit workspace accept', async t => { }), }, chdir: ({ prefix }) => join(prefix, 'packages', 'a'), - globals: { - 'process.argv': [ - process.execPath, - process.argv[1], - '--color', 'false', - ], - }, }) await t.rejects(mock.npm.exec('org', []), /.*Usage/) }) diff --git a/test/lib/utils/audit-error.js b/test/lib/utils/audit-error.js index f6be56a152f71..9d6192fbc31be 100644 --- a/test/lib/utils/audit-error.js +++ b/test/lib/utils/audit-error.js @@ -1,11 +1,9 @@ const t = require('tap') -const mockLogs = require('../../fixtures/mock-logs') const mockNpm = require('../../fixtures/mock-npm') const tmock = require('../../fixtures/tmock') const auditError = async (t, { command, error, ...config } = {}) => { - const { logs, logMocks } = mockLogs() - const mockAuditError = tmock(t, '{LIB}/utils/audit-error', logMocks) + const mockAuditError = tmock(t, '{LIB}/utils/audit-error') const mock = await mockNpm(t, { command, @@ -23,7 +21,7 @@ const auditError = async (t, { command, error, ...config } = {}) => { return { ...res, - logs: logs.warn.filter((l) => l[0] === 'audit'), + logs: mock.logs.warn.byTitle('audit'), output: mock.joinedOutput(), } } @@ -80,7 +78,7 @@ t.test('error, audit command, not json', async t => { t.ok(error, 'throws error') t.match(output, 'body error text', 'some output') - t.strictSame(logs, [['audit', 'message']], 'some warnings') + t.strictSame(logs, ['audit message'], 'some warnings') }) t.test('error, audit command, json', async t => { @@ -117,5 +115,5 @@ t.test('error, audit command, json', async t => { ' }\n' + '}' , 'some output') - t.strictSame(logs, [['audit', 'message']], 'some warnings') + t.strictSame(logs, ['audit message'], 'some warnings') }) diff --git a/test/lib/utils/display.js b/test/lib/utils/display.js index 2b9db0e672510..9f6b77259feba 100644 --- a/test/lib/utils/display.js +++ b/test/lib/utils/display.js @@ -1,161 +1,143 @@ const t = require('tap') -const log = require('../../../lib/utils/log-shim') -const mockLogs = require('../../fixtures/mock-logs') -const mockGlobals = require('@npmcli/mock-globals') const tmock = require('../../fixtures/tmock') -const util = require('util') +const mockLogs = require('../../fixtures/mock-logs') +const { inspect } = require('util') -const mockDisplay = (t, mocks) => { - const { logs, logMocks } = mockLogs(mocks) - const Display = tmock(t, '{LIB}/utils/display', { - ...mocks, - ...logMocks, +const mockDisplay = async (t, { mocks, load } = {}) => { + const { Chalk } = await import('chalk') + const log = require('proc-log') + const logs = mockLogs() + const Display = tmock(t, '{LIB}/utils/display', mocks) + const display = new Display(logs.streams) + display.load({ + loglevel: 'silly', + chalk: new Chalk({ level: 0 }), + heading: 'npm', + ...load, }) - const display = new Display() t.teardown(() => display.off()) - return { display, logs } + return { + display, + log, + ...logs.logs, + } } -t.test('setup', async (t) => { - const { display } = mockDisplay(t) - - display.load({ timing: true, loglevel: 'notice' }) - t.equal(log.level, 'notice') - - display.load({ timing: false, loglevel: 'notice' }) - t.equal(log.level, 'notice') - - display.load({ color: true }) - t.equal(log.useColor(), true) - - display.load({ unicode: true }) - t.equal(log.gauge._theme.hasUnicode, true) +t.test('can log cleanly', async (t) => { + const explains = [] + const { log, logs } = await mockDisplay(t, { + mocks: { + '{LIB}/utils/explain-eresolve.js': { + explain: (...args) => { + explains.push(args) + return 'explanation' + }, + }, + }, + }) - display.load({ unicode: false }) - t.equal(log.gauge._theme.hasUnicode, false) + log.error('', 'test\x00message') + t.match(logs.error, ['test^@message']) - mockGlobals(t, { 'process.stderr.isTTY': true }) - display.load({ progress: true }) - t.equal(log.progressEnabled, true) + log.warn('ERESOLVE', 'hello', { some: 'object' }) + t.match(logs.warn, ['ERESOLVE hello']) + t.match(explains, [[{ some: 'object' }, Function, 2]]) }) -t.test('can log cleanly', async (t) => { - const explains = [] - const { display, logs } = mockDisplay(t, { - npmlog: { - error: (...args) => logs.push(['error', ...args]), - warn: (...args) => logs.push(['warn', ...args]), - }, - '{LIB}/utils/explain-eresolve.js': { - explain: (...args) => { - explains.push(args) - return 'explanation' - }, +t.test('can do progress', async (t) => { + const { log, logs } = await mockDisplay(t, { + load: { + progress: true, + loglevel: 'error', }, }) - display.log('error', 'test\x00message') - t.match(logs.error, [['test^@message']]) + log.silly('', 'this would go to progress') - display.log('warn', 'ERESOLVE', 'hello', { some: 'object' }) - t.match(logs.warn, [['ERESOLVE', 'hello']]) - t.match(explains, [[{ some: 'object' }, null, 2]]) + t.strictSame(logs, [], 'no logs were shown normally') }) t.test('handles log throwing', async (t) => { - const errors = [] - mockGlobals(t, { - 'console.error': (...args) => errors.push(args), - }) - const { display } = mockDisplay(t, { - npmlog: { - verbose: () => { - throw new Error('verbose') - }, - }, - '{LIB}/utils/explain-eresolve.js': { - explain: () => { - throw new Error('explain') + const { log, logs } = await mockDisplay(t, { + mocks: { + '{LIB}/utils/explain-eresolve.js': { + explain: () => { + throw new Error('explain') + }, }, }, }) - display.log('warn', 'ERESOLVE', 'hello', { some: 'object' }) - t.match(errors, [ - [/attempt to log .* crashed/, Error('explain'), Error('verbose')], - ]) -}) + log.warn('ERESOLVE', 'hello', { some: 'object' }) -class CustomObj { - [util.inspect.custom] () { - return this.inspected - } -} + t.match(logs.verbose[0], + `attempt to log crashed ERESOLVE hello { some: 'object' } Error: explain`) +}) t.test('Display.clean', async (t) => { - const Display = require('../../../lib/utils/display') - const customNaN = new CustomObj() - const customNull = new CustomObj() - const customNumber = new CustomObj() - const customObject = new CustomObj() - const customString = new CustomObj() - const customUndefined = new CustomObj() - customNaN.inspected = NaN - customNull.inspected = null - customNumber.inspected = 477 - customObject.inspected = { custom: 'rend\x00ering' } - customString.inspected = 'custom\x00rendering' - customUndefined.inspected = undefined - t.test('strings', async (t) => { - const tests = [ - [477, '477'], - [null, 'null'], - [NaN, 'NaN'], - [true, 'true'], - [undefined, 'undefined'], - ['🚀', '🚀'], - // Cover the bounds of each range and a few characters from inside each range - // \x00 through \x1f - ['hello\x00world', 'hello^@world'], - ['hello\x07world', 'hello^Gworld'], - ['hello\x1bworld', 'hello^[world'], - ['hello\x1eworld', 'hello^^world'], - ['hello\x1fworld', 'hello^_world'], - // \x7f is C0 - ['hello\x7fworld', 'hello^?world'], - // \x80 through \x9f - ['hello\x80world', 'hello^@world'], - ['hello\x87world', 'hello^Gworld'], - ['hello\x9eworld', 'hello^^world'], - ['hello\x9fworld', 'hello^_world'], - // Allowed C0 - ['hello\tworld', 'hello\tworld'], - ['hello\nworld', 'hello\nworld'], - ['hello\vworld', 'hello\vworld'], - ['hello\rworld', 'hello\rworld'], - // Allowed SGR - ['hello\x1b[38;5;254mworld', 'hello\x1b[38;5;254mworld'], - ['hello\x1b[mworld', 'hello\x1b[mworld'], - // Unallowed CSI / OSC - ['hello\x1b[2Aworld', 'hello^[[2Aworld'], - ['hello\x9b[2Aworld', 'hello^[[2Aworld'], - ['hello\x9decho goodbye\x9cworld', 'hello^]echo goodbye^\\world'], - // This is done twice to ensure we define inspect.custom as writable - [{ test: 'object' }, "{ test: 'object' }"], - [{ test: 'object' }, "{ test: 'object' }"], - // Make sure custom util.inspect doesn't bypass our cleaning - [customNaN, 'NaN'], - [customNull, 'null'], - [customNumber, '477'], - [customObject, "{ custom: 'rend\\x00ering' }"], - [customString, 'custom^@rendering'], - [customUndefined, 'undefined'], - // UTF-16 form of 8-bit C1 - ['hello\xc2\x9bworld', 'hello\xc2^[world'], - ] - for (const [dirty, clean] of tests) { - const cleaned = Display.clean(dirty) - t.equal(util.format(cleaned), clean) + const { display, outputs, clearOutput } = await mockDisplay(t) + + class CustomObj { + #inspected + + constructor (val) { + this.#inspected = val } - }) + + [inspect.custom] () { + return this.#inspected + } + } + + const tests = [ + [477, '477'], + [null, 'null'], + [NaN, 'NaN'], + [true, 'true'], + [undefined, 'undefined'], + ['🚀', '🚀'], + // Cover the bounds of each range and a few characters from inside each range + // \x00 through \x1f + ['hello\x00world', 'hello^@world'], + ['hello\x07world', 'hello^Gworld'], + ['hello\x1bworld', 'hello^[world'], + ['hello\x1eworld', 'hello^^world'], + ['hello\x1fworld', 'hello^_world'], + // \x7f is C0 + ['hello\x7fworld', 'hello^?world'], + // \x80 through \x9f + ['hello\x80world', 'hello^@world'], + ['hello\x87world', 'hello^Gworld'], + ['hello\x9eworld', 'hello^^world'], + ['hello\x9fworld', 'hello^_world'], + // Allowed C0 + ['hello\tworld', 'hello\tworld'], + ['hello\nworld', 'hello\nworld'], + ['hello\vworld', 'hello\vworld'], + ['hello\rworld', 'hello\rworld'], + // Allowed SGR + ['hello\x1b[38;5;254mworld', 'hello\x1b[38;5;254mworld'], + ['hello\x1b[mworld', 'hello\x1b[mworld'], + // Unallowed CSI / OSC + ['hello\x1b[2Aworld', 'hello^[[2Aworld'], + ['hello\x9b[2Aworld', 'hello^[[2Aworld'], + ['hello\x9decho goodbye\x9cworld', 'hello^]echo goodbye^\\world'], + // This is done twice to ensure we define inspect.custom as writable + [{ test: 'object' }, "{ test: 'object' }"], + // Make sure custom util.inspect doesn't bypass our cleaning + [new CustomObj(NaN), 'NaN'], + [new CustomObj(null), 'null'], + [new CustomObj(477), '477'], + [new CustomObj({ custom: 'rend\x00ering' }), "{ custom: 'rend\\x00ering' }"], + [new CustomObj('custom\x00rendering'), 'custom^@rendering'], + [new CustomObj(undefined), 'undefined'], + // UTF-16 form of 8-bit C1 + ['hello\xc2\x9bworld', 'hello\xc2^[world'], + ] + + for (const [dirty, clean] of tests) { + display.output(dirty) + t.equal(outputs[0], clean) + clearOutput() + } }) diff --git a/test/lib/utils/exit-handler.js b/test/lib/utils/exit-handler.js index b48f96d581775..597792da73e63 100644 --- a/test/lib/utils/exit-handler.js +++ b/test/lib/utils/exit-handler.js @@ -1,10 +1,8 @@ const t = require('tap') -const os = require('os') const fs = require('fs') const fsMiniPass = require('fs-minipass') const { join, resolve } = require('path') const EventEmitter = require('events') -const { format } = require('../../../lib/utils/log-file') const { load: loadMockNpm } = require('../../fixtures/mock-npm') const mockGlobals = require('@npmcli/mock-globals') const { cleanCwd, cleanDate } = require('../../fixtures/clean-snapshot') @@ -129,7 +127,9 @@ const err = (message = '', options = {}, noStack = false) => { } t.test('handles unknown error with logs and debug file', async (t) => { - const { exitHandler, debugFile, logs } = await mockExitHandler(t) + const { exitHandler, debugFile, logs } = await mockExitHandler(t, { + config: { loglevel: 'silly', timing: true }, + }) await exitHandler(err('Unknown error', 'ECODE')) // force logfile cleaning logs to happen since those are purposefully not awaited @@ -145,7 +145,7 @@ t.test('handles unknown error with logs and debug file', async (t) => { let skippedLogs = 0 logs.forEach((logItem, i) => { - const logLines = format(i, ...logItem).trim().split(os.EOL) + const logLines = logItem.split('\n').map(l => `${i} ${l}`) for (const line of logLines) { if (line.includes('logfile') && line.includes('cleaning')) { skippedLogs++ @@ -157,9 +157,9 @@ t.test('handles unknown error with logs and debug file', async (t) => { t.equal(logs.length - skippedLogs, parseInt(lastLog) + 1) t.match(logs.error, [ - ['code', 'ECODE'], - ['ERR SUMMARY', 'Unknown error'], - ['ERR DETAIL', 'Unknown error'], + 'code ECODE', + 'ERR SUMMARY Unknown error', + 'ERR DETAIL Unknown error', ]) t.match(fileLogs, /\d+ error code ECODE/) t.match(fileLogs, /\d+ error ERR SUMMARY Unknown error/) @@ -173,10 +173,7 @@ t.test('exit handler never called - loglevel silent', async (t) => { config: { loglevel: 'silent' }, }) process.emit('exit', 1) - t.match(logs.error, [ - ['', /Exit handler never called/], - ['', /error with npm itself/], - ]) + t.strictSame(logs.error, []) t.strictSame(errors, [''], 'logs one empty string to console.error') }) @@ -185,8 +182,8 @@ t.test('exit handler never called - loglevel notice', async (t) => { process.emit('exit', 1) t.equal(process.exitCode, 1) t.match(logs.error, [ - ['', /Exit handler never called/], - ['', /error with npm itself/], + 'Exit handler never called!', + /error with npm itself/, ]) t.strictSame(errors, ['', ''], 'logs two empty strings to console.error') }) @@ -195,10 +192,7 @@ t.test('exit handler never called - no npm', async (t) => { const { logs, errors } = await mockExitHandler(t, { init: false }) process.emit('exit', 1) t.equal(process.exitCode, 1) - t.match(logs.error, [ - ['', /Exit handler never called/], - ['', /error with npm itself/], - ]) + t.strictSame(logs.error, []) t.strictSame(errors, [''], 'logs one empty string to console.error') }) @@ -282,10 +276,10 @@ t.test('output buffer without json', async (t) => { t.equal(process.exitCode, 1) t.same( outputs, - [['output_data'], ['more_data']], + ['output_data', 'more_data'], 'should output expected output' ) - t.match(logs.error, [['code', 'EBADTHING']]) + t.match(logs.error, ['code EBADTHING']) }) t.test('throw a non-error obj', async (t) => { @@ -298,7 +292,7 @@ t.test('throw a non-error obj', async (t) => { t.equal(process.exitCode, 1) t.match(logs.error, [ - ['weird error', { code: 'ESOMETHING', message: 'foo bar' }], + "weird error { code: 'ESOMETHING', message: 'foo bar' }", ]) }) @@ -309,7 +303,7 @@ t.test('throw a string error', async (t) => { t.equal(process.exitCode, 1) t.match(logs.error, [ - ['', 'foo bar'], + 'foo bar', ]) }) @@ -320,7 +314,7 @@ t.test('update notification', async (t) => { await exitHandler() t.match(logs.notice, [ - ['', 'you should update npm!'], + 'you should update npm!', ]) }) @@ -335,9 +329,7 @@ t.test('npm.config not ready', async (t) => { t.match(errors, [ /Error: Exit prior to config file resolving./, ], 'should exit with config error msg') - t.match(logs.verbose, [ - ['stack', /Error: Exit prior to config file resolving./], - ], 'should exit with config error msg') + t.strictSame(logs, [], 'no logs if it doesnt load') }) t.test('no logs dir', async (t) => { @@ -346,10 +338,9 @@ t.test('no logs dir', async (t) => { }) await exitHandler(new Error()) - t.match(logs.error.filter(([t]) => t === ''), [ - ['', 'Log files were not written due to the config logs-max=0'], - ]) - t.match(logs.filter(([_, task]) => task === 'npm.load.mkdirplogs'), []) + t.match(logs.error[2], + 'Log files were not written due to the config logs-max=0') + t.match(logs.filter((l) => l.includes('npm.load.mkdirplogs')), []) }) t.test('timers fail to write', async (t) => { @@ -380,7 +371,7 @@ t.test('timers fail to write', async (t) => { await exitHandler(new Error()) - t.match(logs.error.filter(([t]) => t === ''), [['', `error writing to the directory`]]) + t.match(logs.error[2], `error writing to the directory`) }) t.test('log files fail to write', async (t) => { @@ -408,7 +399,7 @@ t.test('log files fail to write', async (t) => { await exitHandler(new Error()) - t.match(logs.error.filter(([t]) => t === ''), [['', `error writing to the directory`]]) + t.match(logs.error[2], `error writing to the directory`) }) t.test('files from error message', async (t) => { @@ -424,9 +415,7 @@ t.test('files from error message', async (t) => { const errorFileName = logFiles.find(f => f.endsWith('error-file.txt')) const errorFile = fs.readFileSync(join(cache, '_logs', errorFileName)).toString() - const [log] = logs.error.filter(([t]) => t === '') - - t.match(log[1], /For a full report see:\n.*-error-file\.txt/) + t.match(logs[2], /For a full report see:\n.*-error-file\.txt/) t.match(errorFile, '# error file content') t.match(errorFile, 'Log files:') }) @@ -453,14 +442,12 @@ t.test('files from error message with error', async (t) => { await exitHandler(err('Error message')) - const [log] = logs.warn.filter(([t]) => t === '') - - t.match(log[1], /Could not write error message to.*error-file\.txt.*err/) + t.match(logs.warn[0], /Could not write error message to.*error-file\.txt.*err/) }) t.test('timing with no error', async (t) => { const { exitHandler, timingFile, npm, logs } = await mockExitHandler(t, { - config: { timing: true }, + config: { timing: true, loglevel: 'info' }, }) await exitHandler() @@ -468,7 +455,7 @@ t.test('timing with no error', async (t) => { t.equal(process.exitCode, 0) - const msg = logs.info.filter(([t]) => t === '')[0][1] + const msg = logs.info[1] t.match(msg, /A complete log of this run can be found in:/) t.match(msg, /Timing info written to:/) @@ -492,6 +479,18 @@ t.test('timing with no error', async (t) => { }) }) +t.test('timing message hidden by loglevel', async (t) => { + const { exitHandler, logs } = await mockExitHandler(t, { + config: { timing: true, loglevel: 'notice' }, + }) + + await exitHandler() + + t.equal(process.exitCode, 0) + + t.strictSame(logs.info, [], 'no log message') +}) + t.test('unfinished timers', async (t) => { const { exitHandler, timingFile, npm } = await mockExitHandler(t, { config: { timing: true }, @@ -526,7 +525,7 @@ t.test('uses code from errno', async (t) => { await exitHandler(err('Error with errno', { errno: 127 })) t.equal(process.exitCode, 127) - t.match(logs.error, [['errno', 127]]) + t.match(logs.error, ['errno 127']) }) t.test('uses code from number', async (t) => { @@ -534,7 +533,7 @@ t.test('uses code from number', async (t) => { await exitHandler(err('Error with code type number', 404)) t.equal(process.exitCode, 404) - t.match(logs.error, [['code', 404]]) + t.match(logs.error, ['code 404']) }) t.test('uses all err special properties', async t => { @@ -548,11 +547,13 @@ t.test('uses all err special properties', async t => { await exitHandler(err('Error with code type number', properties)) t.equal(process.exitCode, 1) - t.match(logs.error, keys.map((k) => [k, `${k}-hey`]), 'all special keys get logged') + t.match(logs.error, keys.map((k) => `${k} ${k}-hey`), 'all special keys get logged') }) t.test('verbose logs replace info on err props', async t => { - const { exitHandler, logs } = await mockExitHandler(t) + const { exitHandler, logs } = await mockExitHandler(t, { + config: { loglevel: 'verbose' }, + }) const keys = ['type', 'stack', 'pkgid'] const properties = keys.reduce((acc, k) => { @@ -563,8 +564,8 @@ t.test('verbose logs replace info on err props', async t => { await exitHandler(err('Error with code type number', properties)) t.equal(process.exitCode, 1) t.match( - logs.verbose.filter(([p]) => !['logfile', 'title', 'argv'].includes(p)), - keys.map((k) => [k, `${k}-https://user:***@registry.npmjs.org/`]), + logs.verbose.filter(l => !/^(logfile|title|argv)/.test(l)), + keys.map((k) => `${k} ${k}-https://user:***@registry.npmjs.org/`), 'all special keys get replaced' ) }) @@ -584,10 +585,7 @@ t.test('defaults to log error msg if stack is missing when unloaded', async (t) await exitHandler(err('Error with no stack', { code: 'ENOSTACK', errno: 127 }, true)) t.equal(process.exitCode, 127) t.same(errors, ['Error with no stack'], 'should use error msg') - t.match(logs.error, [ - ['code', 'ENOSTACK'], - ['errno', 127], - ]) + t.strictSame(logs.error, []) }) t.test('exits uncleanly when only emitting exit event', async (t) => { @@ -595,36 +593,40 @@ t.test('exits uncleanly when only emitting exit event', async (t) => { process.emit('exit') - t.match(logs.error, [['', 'Exit handler never called!']]) + t.match(logs.error, ['Exit handler never called!']) t.equal(process.exitCode, 1, 'exitCode coerced to 1') }) t.test('do no fancy handling for shellouts', async t => { - const { exitHandler, logs } = await mockExitHandler(t, { + const mockShelloutExit = (t) => mockExitHandler(t, { command: 'exec', exec: true, argv: ['-c', 'exit'], + config: { + timing: false, + }, }) - const loudNoises = () => - logs.filter(([level]) => ['warn', 'error'].includes(level)) - t.test('shellout with a numeric error code', async t => { + const { exitHandler, logs } = await mockShelloutExit(t) await exitHandler(err('', 5)) t.equal(process.exitCode, 5, 'got expected exit code') - t.strictSame(loudNoises(), [], 'no noisy warnings') + t.strictSame(logs.error, [], 'no noisy warnings') + t.strictSame(logs.warn, [], 'no noisy warnings') }) t.test('shellout without a numeric error code (something in npm)', async t => { + const { exitHandler, logs } = await mockShelloutExit(t) await exitHandler(err('', 'banana stand')) t.equal(process.exitCode, 1, 'got expected exit code') // should log some warnings and errors, because something weird happened - t.strictNotSame(loudNoises(), [], 'bring the noise') + t.strictNotSame(logs.error, [], 'bring the noise') }) t.test('shellout with code=0 (extra weird?)', async t => { + const { exitHandler, logs } = await mockShelloutExit(t) await exitHandler(Object.assign(new Error(), { code: 0 })) t.equal(process.exitCode, 1, 'got expected exit code') - t.strictNotSame(loudNoises(), [], 'bring the noise') + t.strictNotSame(logs.error, [], 'bring the noise') }) }) diff --git a/test/lib/utils/log-shim.js b/test/lib/utils/log-shim.js deleted file mode 100644 index 7c8fb7ce3c956..0000000000000 --- a/test/lib/utils/log-shim.js +++ /dev/null @@ -1,101 +0,0 @@ -const t = require('tap') -const tmock = require('../../fixtures/tmock') - -const makeShim = (mocks) => tmock(t, '{LIB}/utils/log-shim.js', mocks) - -const loggers = [ - 'notice', - 'error', - 'warn', - 'info', - 'verbose', - 'http', - 'silly', - 'pause', - 'resume', -] - -t.test('has properties', (t) => { - const shim = makeShim() - - t.match(shim, { - level: String, - levels: {}, - gauge: {}, - stream: {}, - heading: undefined, - enableColor: Function, - disableColor: Function, - enableUnicode: Function, - disableUnicode: Function, - enableProgress: Function, - disableProgress: Function, - ...loggers.reduce((acc, l) => { - acc[l] = Function - return acc - }, {}), - }) - - t.match(Object.keys(shim).sort(), [ - 'level', - 'heading', - 'levels', - 'gauge', - 'stream', - 'tracker', - 'useColor', - 'enableColor', - 'disableColor', - 'enableUnicode', - 'disableUnicode', - 'enableProgress', - 'disableProgress', - 'progressEnabled', - 'clearProgress', - 'showProgress', - 'newItem', - 'newGroup', - ...loggers, - ].sort()) - - t.end() -}) - -t.test('works with npmlog/proclog proxy', t => { - const procLog = { silly: () => 'SILLY' } - const npmlog = { level: 'woo', enableColor: () => true } - const shim = makeShim({ npmlog, 'proc-log': procLog }) - - t.equal(shim.level, 'woo', 'can get a property') - - npmlog.level = 'hey' - t.strictSame( - [shim.level, npmlog.level], - ['hey', 'hey'], - 'can get a property after update on npmlog' - ) - - shim.level = 'test' - t.strictSame( - [shim.level, npmlog.level], - ['test', 'test'], - 'can get a property after update on shim' - ) - - t.ok(shim.enableColor(), 'can call method on shim to call npmlog') - t.equal(shim.silly(), 'SILLY', 'can call method on proclog') - t.notOk(shim.LEVELS, 'only includes levels from npmlog') - t.throws(() => shim.gauge = 100, 'cant set getters properies') - - t.end() -}) - -t.test('works with npmlog/proclog proxy', t => { - const shim = makeShim() - - loggers.forEach((k) => { - t.doesNotThrow(() => shim[k]('test')) - }) - - t.end() -}) diff --git a/test/lib/utils/pulse-till-done.js b/test/lib/utils/pulse-till-done.js deleted file mode 100644 index 3b3f4b2f2253e..0000000000000 --- a/test/lib/utils/pulse-till-done.js +++ /dev/null @@ -1,35 +0,0 @@ -const t = require('tap') -const tmock = require('../../fixtures/tmock') - -let pulseStarted = null - -const pulseTillDone = tmock(t, '{LIB}/utils/pulse-till-done.js', { - npmlog: { - gauge: { - pulse: () => { - if (pulseStarted) { - pulseStarted() - } - }, - }, - }, -}) - -t.test('pulses (with promise)', async (t) => { - t.teardown(() => { - pulseStarted = null - }) - - let resolver - const promise = new Promise(resolve => { - resolver = resolve - }) - - const result = pulseTillDone.withPromise(promise) - // wait until the gauge has fired at least once - await new Promise(resolve => { - pulseStarted = resolve - }) - resolver('value') - t.resolveMatch(result, 'value', 'returned the resolved promise') -}) diff --git a/test/lib/utils/read-user-info.js b/test/lib/utils/read-user-info.js index a1c2f980cf745..da771ccdf4a98 100644 --- a/test/lib/utils/read-user-info.js +++ b/test/lib/utils/read-user-info.js @@ -28,10 +28,6 @@ const npmUserValidate = { let logMsg = null const readUserInfo = tmock(t, '{LIB}/utils/read-user-info.js', { read, - npmlog: { - clearProgress: () => {}, - showProgress: () => {}, - }, 'proc-log': { warn: (msg) => logMsg = msg, }, diff --git a/test/lib/utils/tar.js b/test/lib/utils/tar.js index 274bad95c0af3..9653e6058492f 100644 --- a/test/lib/utils/tar.js +++ b/test/lib/utils/tar.js @@ -16,7 +16,7 @@ const mockTar = ({ notice }) => tmock(t, '{LIB}/utils/tar.js', { const printLogs = (tarball, options) => { const logs = [] const { logTar } = mockTar({ - notice: (...args) => args.map(el => logs.push(el)), + notice: (...args) => logs.push(...args), }) logTar(tarball, options) return logs.join('\n') diff --git a/test/lib/utils/timers.js b/test/lib/utils/timers.js index 74df6c28cd361..31f73b5aca408 100644 --- a/test/lib/utils/timers.js +++ b/test/lib/utils/timers.js @@ -1,25 +1,25 @@ const t = require('tap') const { resolve, join } = require('path') const fs = require('graceful-fs') -const mockLogs = require('../../fixtures/mock-logs') +const { format } = require('util') const tmock = require('../../fixtures/tmock') const mockTimers = (t, options) => { - const { logs, logMocks } = mockLogs() + const logs = { + warn: [], + silly: [], + } const Timers = tmock(t, '{LIB}/utils/timers', { - ...logMocks, + 'proc-log': { + warn: (...args) => logs.warn.push(args.map((a) => format(a)).join(' ')), + silly: (...args) => logs.silly.push(args.map((a) => format(a)).join(' ')), + }, }) const timers = new Timers(options) t.teardown(() => timers.off()) return { timers, logs } } -t.test('getters', async (t) => { - const { timers } = mockTimers(t) - t.match(timers.unfinished, new Map()) - t.match(timers.finished, {}) -}) - t.test('listens/stops on process', async (t) => { const { timers } = mockTimers(t) process.emit('time', 'foo') @@ -65,7 +65,7 @@ t.test('initial listener', async (t) => { t.test('finish unstarted timer', async (t) => { const { logs } = mockTimers(t) process.emit('timeEnd', 'foo') - t.match(logs.silly, [['timing', /^Tried to end timer/, 'foo']]) + t.match(logs.silly, ["timing Tried to end timer that doesn't exist: foo"]) }) t.test('writes file', async (t) => { @@ -92,7 +92,7 @@ t.test('fails to write file', async (t) => { timers.load({ path: join(dir, 'does', 'not', 'exist') }) timers.writeFile() - t.match(logs.warn, [['timing', 'could not write timing file']]) + t.match(logs.warn, ['timing could not write timing file:']) t.equal(timers.file, null) }) @@ -102,6 +102,7 @@ t.test('no dir and no file', async (t) => { timers.load() timers.writeFile() - t.strictSame(logs, []) + t.strictSame(logs.warn, []) + t.strictSame(logs.silly, []) t.equal(timers.file, null) }) diff --git a/workspaces/arborist/lib/shrinkwrap.js b/workspaces/arborist/lib/shrinkwrap.js index e6525ffe67b65..275043d1208b7 100644 --- a/workspaces/arborist/lib/shrinkwrap.js +++ b/workspaces/arborist/lib/shrinkwrap.js @@ -1145,6 +1145,7 @@ class Shrinkwrap { throw new Error('run load() before saving data') } + // This must be called before the lockfile conversion check below since it sets properties as part of `commit()` const json = this.toString(options) if ( !this.hiddenLockfile @@ -1155,6 +1156,7 @@ class Shrinkwrap { `Converting lock file (${relative(process.cwd(), this.filename)}) from v${this.originalLockfileVersion} -> v${this.lockfileVersion}` ) } + return Promise.all([ writeFile(this.filename, json).catch(er => { if (this.hiddenLockfile) { diff --git a/workspaces/arborist/lib/tracker.js b/workspaces/arborist/lib/tracker.js index 5acb32a5a7cfd..4a754d995dfcd 100644 --- a/workspaces/arborist/lib/tracker.js +++ b/workspaces/arborist/lib/tracker.js @@ -1,12 +1,12 @@ -const npmlog = require('npmlog') +const proggy = require('proggy') module.exports = cls => class Tracker extends cls { #progress = new Map() - #setProgress - constructor (options = {}) { - super(options) - this.#setProgress = !!options.progress + #createTracker (key, name) { + const tracker = new proggy.Tracker(name ?? key) + tracker.on('done', () => this.#progress.delete(key)) + this.#progress.set(key, tracker) } addTracker (section, subsection = null, key = null) { @@ -26,22 +26,17 @@ module.exports = cls => class Tracker extends cls { this.#onError(`Tracker "${section}" already exists`) } else if (!hasTracker && subsection === null) { // 1. no existing tracker, no subsection - // Create a new tracker from npmlog - // starts progress bar - if (this.#setProgress && this.#progress.size === 0) { - npmlog.enableProgress() - } - - this.#progress.set(section, npmlog.newGroup(section)) + // Create a new progress tracker + this.#createTracker(section) } else if (!hasTracker && subsection !== null) { // 2. no parent tracker and subsection this.#onError(`Parent tracker "${section}" does not exist`) } else if (!hasTracker || !hasSubtracker) { // 3. existing parent tracker, no subsection tracker - // Create a new subtracker in this.#progress from parent tracker - this.#progress.set(`${section}:${key}`, - this.#progress.get(section).newGroup(`${section}:${subsection}`) - ) + // Create a new subtracker and update parents + const parentTracker = this.#progress.get(section) + parentTracker.update(parentTracker.value, parentTracker.total + 1) + this.#createTracker(`${section}:${key}`, `${section}:${subsection}`) } // 4. existing parent tracker, existing subsection tracker // skip it @@ -70,32 +65,22 @@ module.exports = cls => class Tracker extends cls { this.finishTracker(section, key) } } - // remove parent tracker this.#progress.get(section).finish() - this.#progress.delete(section) - - // remove progress bar if all - // trackers are finished - if (this.#setProgress && this.#progress.size === 0) { - npmlog.disableProgress() - } } else if (!hasTracker && subsection === null) { // 1. no existing parent tracker, no subsection this.#onError(`Tracker "${section}" does not exist`) } else if (!hasTracker || hasSubtracker) { // 2. subtracker exists // Finish subtracker and remove from this.#progress + const parentTracker = this.#progress.get(section) + parentTracker.update(parentTracker.value + 1) this.#progress.get(`${section}:${key}`).finish() - this.#progress.delete(`${section}:${key}`) } // 3. existing parent tracker, no subsection } #onError (msg) { - if (this.#setProgress) { - npmlog.disableProgress() - } throw new Error(msg) } } diff --git a/workspaces/arborist/package.json b/workspaces/arborist/package.json index 3a92e669d4bb6..d4350b1adaf11 100644 --- a/workspaces/arborist/package.json +++ b/workspaces/arborist/package.json @@ -26,10 +26,10 @@ "npm-package-arg": "^11.0.1", "npm-pick-manifest": "^9.0.0", "npm-registry-fetch": "^16.2.0", - "npmlog": "^7.0.1", "pacote": "^17.0.4", "parse-conflict-json": "^3.0.0", "proc-log": "^3.0.0", + "proggy": "^2.0.0", "promise-all-reject-late": "^1.0.0", "promise-call-limit": "^3.0.1", "read-package-json-fast": "^3.0.2", diff --git a/workspaces/libnpmdiff/lib/format-diff.js b/workspaces/libnpmdiff/lib/format-diff.js index 211386cb5390e..8db110fbea186 100644 --- a/workspaces/libnpmdiff/lib/format-diff.js +++ b/workspaces/libnpmdiff/lib/format-diff.js @@ -1,5 +1,3 @@ -const EOL = '\n' - const colorizeDiff = require('@npmcli/disparity-colors') const jsDiff = require('diff') @@ -35,7 +33,7 @@ const formatDiff = ({ files, opts = {}, refs, versions }) => { } if (opts.diffNameOnly) { - res += `${filename}${EOL}` + res += `${filename}\n` continue } @@ -43,7 +41,7 @@ const formatDiff = ({ files, opts = {}, refs, versions }) => { let headerLength = 0 const header = str => { headerLength++ - patch += `${str}${EOL}` + patch += `${str}\n` } // manually build a git diff-compatible header diff --git a/workspaces/libnpmexec/lib/index.js b/workspaces/libnpmexec/lib/index.js index 6f548b943e2e6..af4d6e738779a 100644 --- a/workspaces/libnpmexec/lib/index.js +++ b/workspaces/libnpmexec/lib/index.js @@ -6,7 +6,6 @@ const ciInfo = require('ci-info') const crypto = require('crypto') const log = require('proc-log') const npa = require('npm-package-arg') -const npmlog = require('npmlog') const pacote = require('pacote') const { read } = require('read') const semver = require('semver') @@ -264,7 +263,6 @@ const exec = async (opts) => { const prompt = `Need to install the following packages:\n${ addList }Ok to proceed? ` - npmlog.clearProgress() const confirm = await read({ prompt, default: 'y' }) if (confirm.trim().toLowerCase().charAt(0) !== 'y') { throw new Error('canceled') diff --git a/workspaces/libnpmexec/lib/run-script.js b/workspaces/libnpmexec/lib/run-script.js index 89dcf2e653036..65fabfc480b8c 100644 --- a/workspaces/libnpmexec/lib/run-script.js +++ b/workspaces/libnpmexec/lib/run-script.js @@ -1,7 +1,6 @@ const ciInfo = require('ci-info') const runScript = require('@npmcli/run-script') const readPackageJson = require('read-package-json-fast') -const npmlog = require('npmlog') const log = require('proc-log') const noTTY = require('./no-tty.js') @@ -21,8 +20,7 @@ const run = async ({ // do the fakey runScript dance // still should work if no package.json in cwd - const realPkg = await readPackageJson(`${path}/package.json`) - .catch(() => ({})) + const realPkg = await readPackageJson(`${path}/package.json`).catch(() => ({})) const pkg = { ...realPkg, scripts: { @@ -31,41 +29,35 @@ const run = async ({ }, } - npmlog.disableProgress() - - try { - if (script === scriptShell) { - if (!noTTY()) { - if (ciInfo.isCI) { - return log.warn('exec', 'Interactive mode disabled in CI environment') - } + if (script === scriptShell) { + if (!noTTY()) { + if (ciInfo.isCI) { + return log.warn('exec', 'Interactive mode disabled in CI environment') + } - locationMsg = locationMsg || ` at location:\n${flatOptions.chalk.dim(runPath)}` + const { chalk } = flatOptions - output(`${ - flatOptions.chalk.reset('\nEntering npm script environment') - }${ - flatOptions.chalk.reset(locationMsg) - }${ - flatOptions.chalk.bold('\nType \'exit\' or ^D when finished\n') - }`) - } + output(`${ + chalk.reset('\nEntering npm script environment') + }${ + chalk.reset(locationMsg || ` at location:\n${chalk.dim(runPath)}`) + }${ + chalk.bold('\nType \'exit\' or ^D when finished\n') + }`) } - return await runScript({ - ...flatOptions, - pkg, - banner: false, - // we always run in cwd, not --prefix - path: runPath, - binPaths, - event: 'npx', - args, - stdio: 'inherit', - scriptShell, - }) - } finally { - npmlog.enableProgress() } + return runScript({ + ...flatOptions, + pkg, + banner: false, + // we always run in cwd, not --prefix + path: runPath, + binPaths, + event: 'npx', + args, + stdio: 'inherit', + scriptShell, + }) } module.exports = run diff --git a/workspaces/libnpmexec/package.json b/workspaces/libnpmexec/package.json index 39f12270e35a7..ac7d4afbccec1 100644 --- a/workspaces/libnpmexec/package.json +++ b/workspaces/libnpmexec/package.json @@ -63,7 +63,6 @@ "@npmcli/run-script": "^7.0.2", "ci-info": "^4.0.0", "npm-package-arg": "^11.0.1", - "npmlog": "^7.0.1", "pacote": "^17.0.4", "proc-log": "^3.0.0", "read": "^3.0.1", diff --git a/workspaces/libnpmexec/test/prompt.js b/workspaces/libnpmexec/test/prompt.js index 637827ef5e71e..d1f4ec48e6b98 100644 --- a/workspaces/libnpmexec/test/prompt.js +++ b/workspaces/libnpmexec/test/prompt.js @@ -5,136 +5,60 @@ const fs = require('fs/promises') const { setup, createPkg, merge } = require('./fixtures/setup.js') t.test('prompt, accepts', async t => { - t.test('with clearProgress function', async t => { - const { pkg, package, fixtures } = createPkg({ - name: '@npmcli/create-index', - version: '1.0.0', - }) - const { exec, path, registry } = setup(t, { - testdir: fixtures, - mocks: { - 'ci-info': { isCI: false }, - '../../lib/no-tty.js': () => false, - npmlog: { - clearProgress () { - t.ok(true, 'should call clearProgress function') - }, - disableProgress () {}, - enableProgress () {}, - }, - read: { read: async () => 'y' }, - }, - }) - - await package({ registry, path }) - - await exec({ - args: ['@npmcli/create-index'], - yes: undefined, - }) - - const installedDir = `npxCache/e7ce50d8d2d8ec11/node_modules/${pkg.name}/package.json` - t.ok(await fs.stat(resolve(path, installedDir)).then(f => f.isFile())) + const { pkg, package, fixtures } = createPkg({ + name: '@npmcli/create-index', + version: '1.0.0', + }) + const { exec, path, registry } = setup(t, { + testdir: fixtures, + mocks: { + 'ci-info': { isCI: false }, + '../../lib/no-tty.js': () => false, + read: { read: async () => 'y' }, + }, }) - t.test('without clearProgress function', async t => { - const { pkg, package, fixtures } = createPkg({ - name: '@npmcli/create-index', - version: '1.0.0', - }) - const { exec, path, registry } = setup(t, { - testdir: fixtures, - mocks: { - 'ci-info': { isCI: false }, - '../../lib/no-tty.js': () => false, - read: { read: async () => 'y' }, - }, - }) - - await package({ registry, path }) - - await exec({ - args: ['@npmcli/create-index'], - yes: undefined, - }) + await package({ registry, path }) - const installedDir = `npxCache/e7ce50d8d2d8ec11/node_modules/${pkg.name}/package.json` - t.ok(await fs.stat(resolve(path, installedDir)).then(f => f.isFile())) + await exec({ + args: ['@npmcli/create-index'], + yes: undefined, }) + + const installedDir = `npxCache/e7ce50d8d2d8ec11/node_modules/${pkg.name}/package.json` + t.ok(await fs.stat(resolve(path, installedDir)).then(f => f.isFile())) }) t.test('prompt, refuses', async t => { - t.test('with clearProgress function', async t => { - t.plan(3) - - const { pkg, package, fixtures } = createPkg({ - name: '@npmcli/create-index', - version: '1.0.0', - }) - const { exec, path, registry } = setup(t, { - testdir: fixtures, - mocks: { - 'ci-info': { isCI: false }, - npmlog: { - clearProgress () { - t.ok(true, 'should call clearProgress function') - }, - disableProgess () {}, - }, - read: { read: async () => 'n' }, - '../../lib/no-tty.js': () => false, - }, - }) - - await package({ registry, path, times: 1, tarballs: [] }) - - await t.rejects( - exec({ - args: ['@npmcli/create-index'], - yes: undefined, - }), - /canceled/, - 'should throw with canceled error' - ) - - const installedDir = `npxCache/e7ce50d8d2d8ec11/node_modules/${pkg.name}/package.json` - t.rejects( - () => fs.stat(resolve(path, installedDir)), - { code: 'ENOENT' } - ) + const { pkg, package, fixtures } = createPkg({ + name: '@npmcli/create-index', + version: '1.0.0', + }) + const { exec, path, registry } = setup(t, { + testdir: fixtures, + mocks: { + 'ci-info': { isCI: false }, + read: { read: async () => 'n' }, + '../../lib/no-tty.js': () => false, + }, }) - t.test('without clearProgress function', async t => { - const { pkg, package, fixtures } = createPkg({ - name: '@npmcli/create-index', - version: '1.0.0', - }) - const { exec, path, registry } = setup(t, { - testdir: fixtures, - mocks: { - 'ci-info': { isCI: false }, - read: { read: async () => 'n' }, - '../../lib/no-tty.js': () => false, - }, - }) + await package({ registry, path, times: 1, tarballs: [] }) - await package({ registry, path, times: 1, tarballs: [] }) - - await t.rejects( - exec({ - args: ['@npmcli/create-index'], - yes: undefined, - }), - /canceled/, - 'should throw with canceled error' - ) - - const installedDir = `npxCache/e7ce50d8d2d8ec11/node_modules/${pkg.name}/package.json` - t.rejects( - () => fs.stat(resolve(path, installedDir)), - { code: 'ENOENT' } - ) - }) + await t.rejects( + exec({ + args: ['@npmcli/create-index'], + yes: undefined, + }), + /canceled/, + 'should throw with canceled error' + ) + + const installedDir = `npxCache/e7ce50d8d2d8ec11/node_modules/${pkg.name}/package.json` + t.rejects( + () => fs.stat(resolve(path, installedDir)), + { code: 'ENOENT' } + ) }) t.test('prompt, -n', async t => { diff --git a/workspaces/libnpmexec/test/run-script.js b/workspaces/libnpmexec/test/run-script.js index b3289c6b15c4b..e7c83466334fd 100644 --- a/workspaces/libnpmexec/test/run-script.js +++ b/workspaces/libnpmexec/test/run-script.js @@ -16,33 +16,6 @@ const mockRunScript = async (t, mocks, { level = 0 } = {}) => { }) } -t.test('disable, enable log progress', async t => { - t.plan(3) - - const path = t.testdir({ - 'package.json': JSON.stringify({ - name: 'pkg', - }), - }) - const runScript = await mockRunScript(t, { - 'ci-info': { isCI: false }, - '@npmcli/run-script': async () => { - t.ok('should call run-script') - }, - '../lib/no-tty.js': () => false, - npmlog: { - disableProgress () { - t.ok('should disable progress') - }, - enableProgress () { - t.ok('should enable progress') - }, - }, - }) - - await runScript({ path }) -}) - t.test('no package.json', async t => { t.plan(1)