diff options
author | Gar <gar+gh@danger.computer> | 2021-11-04 20:21:00 +0300 |
---|---|---|
committer | Gar <gar+gh@danger.computer> | 2021-11-05 00:45:18 +0300 |
commit | 225645420cf3d13bc0b0d591f7f7bf21a9c24e47 (patch) | |
tree | 107797bef3206793cda93d7dad97f3ab54ef3cd8 /lib | |
parent | de45f90eebbf51205748ed3f09fbeab6cc000b3e (diff) |
chore: update to latest eslint and linting rules
This brings us in line with the rest of the linting rules we are wanting
to use on the npm cli repos.
There were several hundred over-length lines and instead of editing them
all by hand I piped the failing file through `prettier` and back through
`eslint` just to save some time and energy. This means there may be
some quirks in the linting those files have, but we can fix those if we
see them and they bother us.
Other than that there were about 50 lines that are legitimately
over-length, all are now explicitly overridden. Many are tests that
could be snapshots.
PR-URL: https://github.com/npm/cli/pull/3995
Credit: @wraithgar
Close: #3995
Reviewed-by: @lukekarrys
Diffstat (limited to 'lib')
88 files changed, 1724 insertions, 1101 deletions
diff --git a/lib/auth/legacy.js b/lib/auth/legacy.js index 8659446dc..2da82e361 100644 --- a/lib/auth/legacy.js +++ b/lib/auth/legacy.js @@ -40,10 +40,11 @@ const login = async (npm, opts) => { opts ) } catch (err) { - if (err.code === 'EOTP') + if (err.code === 'EOTP') { newUser = await requestOTP() - else + } else { throw err + } } return newUser @@ -58,20 +59,20 @@ const login = async (npm, opts) => { opts.creds.username && opts.creds.password && opts.creds.email) - if (err.code === 'EOTP') + if (err.code === 'EOTP') { res = await requestOTP() - else if (needsMoreInfo) + } else if (needsMoreInfo) { throw err - else { + } else { // TODO: maybe this needs to check for err.code === 'E400' instead? res = await addNewUser() } } const newCreds = {} - if (res && res.token) + if (res && res.token) { newCreds.token = res.token - else { + } else { newCreds.username = opts.creds.username newCreds.password = opts.creds.password newCreds.email = opts.creds.email diff --git a/lib/auth/sso.js b/lib/auth/sso.js index 56cff3c06..6fcfc30e5 100644 --- a/lib/auth/sso.js +++ b/lib/auth/sso.js @@ -25,8 +25,9 @@ const pollForSession = ({ registry, token, opts }) => { return sleep(opts.ssoPollFrequency).then(() => { return pollForSession({ registry, token, opts }) }) - } else + } else { throw err + } } ) } @@ -41,8 +42,9 @@ const login = async (npm, { creds, registry, scope }) => { const opts = { ...npm.flatOptions, creds, registry, scope } const { ssoType } = opts - if (!ssoType) + if (!ssoType) { throw new Error('Missing option: sso-type') + } // We're reusing the legacy login endpoint, so we need some dummy // stuff here to pass validation. They're never used. @@ -57,10 +59,12 @@ const login = async (npm, { creds, registry, scope }) => { opts => profile.loginCouch(auth.username, auth.password, opts) ) - if (!token) + if (!token) { throw new Error('no SSO token returned') - if (!sso) + } + if (!sso) { throw new Error('no SSO URL returned by services') + } await openUrl(npm, sso, 'to complete your login please visit') diff --git a/lib/base-command.js b/lib/base-command.js index c5fce6fd8..ad261b514 100644 --- a/lib/base-command.js +++ b/lib/base-command.js @@ -19,17 +19,22 @@ class BaseCommand { get usage () { let usage = `npm ${this.constructor.name}\n\n` - if (this.constructor.description) + if (this.constructor.description) { usage = `${usage}${this.constructor.description}\n\n` + } usage = `${usage}Usage:\n` - if (!this.constructor.usage) + if (!this.constructor.usage) { usage = `${usage}npm ${this.constructor.name}` - else - usage = `${usage}${this.constructor.usage.map(u => `npm ${this.constructor.name} ${u}`).join('\n')}` + } else { + usage = `${usage}${this.constructor.usage + .map(u => `npm ${this.constructor.name} ${u}`) + .join('\n')}` + } - if (this.constructor.params) + if (this.constructor.params) { usage = `${usage}\n\nOptions:\n${this.wrappedParams}` + } // Mostly this just appends aliases, this could be more clear usage = usageUtil(this.constructor.name, usage) @@ -43,7 +48,7 @@ class BaseCommand { for (const param of this.constructor.params) { const usage = `[${ConfigDefinitions[param].usage}]` - if (line.length && (line.length + usage.length) > this.wrapWidth) { + if (line.length && line.length + usage.length > this.wrapWidth) { results = [results, line].filter(Boolean).join('\n') line = '' } @@ -54,23 +59,24 @@ class BaseCommand { } usageError (prefix = '') { - if (prefix) + if (prefix) { prefix += '\n\n' + } return Object.assign(new Error(`\nUsage: ${prefix}${this.usage}`), { code: 'EUSAGE', }) } async execWorkspaces (args, filters) { - throw Object.assign( - new Error('This command does not support workspaces.'), - { code: 'ENOWORKSPACES' } - ) + throw Object.assign(new Error('This command does not support workspaces.'), { + code: 'ENOWORKSPACES', + }) } async setWorkspaces (filters) { - if (this.isArboristCmd) + if (this.isArboristCmd) { this.includeWorkspaceRoot = false + } const ws = await getWorkspaces(filters, { path: this.npm.localPrefix, diff --git a/lib/cli.js b/lib/cli.js index 0e6301517..9dcd9d04d 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -1,13 +1,10 @@ // Separated out for easier unit testing -module.exports = async (process) => { +module.exports = async process => { // set it here so that regardless of what happens later, we don't // leak any private CLI configs to other programs process.title = 'npm' - const { - checkForBrokenNode, - checkForUnsupportedNode, - } = require('../lib/utils/unsupported.js') + const { checkForBrokenNode, checkForUnsupportedNode } = require('../lib/utils/unsupported.js') checkForBrokenNode() @@ -25,8 +22,9 @@ module.exports = async (process) => { // if npm is called as "npmg" or "npm_g", then // run in global mode. - if (process.argv[1][process.argv[1].length - 1] === 'g') + if (process.argv[1][process.argv[1].length - 1] === 'g') { process.argv.splice(1, 1, 'npm', '-g') + } const replaceInfo = require('../lib/utils/replace-info.js') log.verbose('cli', replaceInfo(process.argv)) @@ -70,7 +68,8 @@ module.exports = async (process) => { if (err.code === 'EUNKNOWNCOMMAND') { const didYouMean = require('./utils/did-you-mean.js') const suggestions = await didYouMean(npm, npm.localPrefix, cmd) - npm.output(`Unknown command: "${cmd}"${suggestions}\n\nTo see a list of supported npm commands, run:\n npm help`) + npm.output(`Unknown command: "${cmd}"${suggestions}\n`) + npm.output('To see a list of supported npm commands, run:\n npm help') process.exitCode = 1 return exitHandler() } diff --git a/lib/commands/access.js b/lib/commands/access.js index 15e51a450..df783c35f 100644 --- a/lib/commands/access.js +++ b/lib/commands/access.js @@ -52,15 +52,17 @@ class Access extends BaseCommand { async completion (opts) { const argv = opts.conf.argv.remain - if (argv.length === 2) + if (argv.length === 2) { return subcommands + } switch (argv[2]) { case 'grant': - if (argv.length === 3) + if (argv.length === 3) { return ['read-only', 'read-write'] - else + } else { return [] + } case 'public': case 'restricted': @@ -77,11 +79,13 @@ class Access extends BaseCommand { } async exec ([cmd, ...args]) { - if (!cmd) + if (!cmd) { throw this.usageError('Subcommand is required.') + } - if (!subcommands.includes(cmd) || !this[cmd]) + if (!subcommands.includes(cmd) || !this[cmd]) { throw this.usageError(`${cmd} is not a recognized subcommand.`) + } return this[cmd](args, this.npm.flatOptions) } @@ -95,11 +99,13 @@ class Access extends BaseCommand { } async grant ([perms, scopeteam, pkg], opts) { - if (!perms || (perms !== 'read-only' && perms !== 'read-write')) + if (!perms || (perms !== 'read-only' && perms !== 'read-write')) { throw this.usageError('First argument must be either `read-only` or `read-write`.') + } - if (!scopeteam) + if (!scopeteam) { throw this.usageError('`<scope:team>` argument is required.') + } const [, scope, team] = scopeteam.match(/^@?([^:]+):(.*)$/) || [] @@ -115,8 +121,9 @@ class Access extends BaseCommand { } async revoke ([scopeteam, pkg], opts) { - if (!scopeteam) + if (!scopeteam) { throw this.usageError('`<scope:team>` argument is required.') + } const [, scope, team] = scopeteam.match(/^@?([^:]+):(.*)$/) || [] @@ -152,8 +159,9 @@ class Access extends BaseCommand { } async lsPackages ([owner], opts) { - if (!owner) + if (!owner) { owner = await getIdentity(this.npm, opts) + } const pkgs = await libaccess.lsPackages(owner, opts) @@ -183,9 +191,9 @@ class Access extends BaseCommand { } async getPackage (name, requireScope) { - if (name && name.trim()) + if (name && name.trim()) { return name.trim() - else { + } else { try { const pkg = await readPackageJson(path.resolve(this.npm.prefix, 'package.json')) name = pkg.name @@ -194,14 +202,16 @@ class Access extends BaseCommand { throw new Error( 'no package name passed to command and no package.json found' ) - } else + } else { throw err + } } - if (requireScope && !name.match(/^@[^/]+\/.*$/)) + if (requireScope && !name.match(/^@[^/]+\/.*$/)) { throw this.usageError('This command is only available for scoped packages.') - else + } else { return name + } } } } diff --git a/lib/commands/adduser.js b/lib/commands/adduser.js index 6136eb726..aa3d8a336 100644 --- a/lib/commands/adduser.js +++ b/lib/commands/adduser.js @@ -54,8 +54,9 @@ class AddUser extends BaseCommand { if (scope) { const scopedRegistry = this.npm.config.get(`${scope}:registry`) const cliRegistry = this.npm.config.get('registry', 'cli') - if (scopedRegistry && !cliRegistry) + if (scopedRegistry && !cliRegistry) { return scopedRegistry + } } return registry } @@ -63,8 +64,9 @@ class AddUser extends BaseCommand { getAuthType ({ authType }) { const type = authTypes[authType] - if (!type) + if (!type) { throw new Error('no such auth module') + } return type } @@ -72,8 +74,9 @@ class AddUser extends BaseCommand { async updateConfig ({ newCreds, registry, scope }) { this.npm.config.delete('_token', 'user') // prevent legacy pollution this.npm.config.setCredentialsByURI(registry, newCreds) - if (scope) + if (scope) { this.npm.config.set(scope + ':registry', registry, 'user') + } await this.npm.config.save('user') } } diff --git a/lib/commands/audit.js b/lib/commands/audit.js index d05633ab0..ebc9f65c5 100644 --- a/lib/commands/audit.js +++ b/lib/commands/audit.js @@ -36,8 +36,9 @@ class Audit extends ArboristWorkspaceCmd { async completion (opts) { const argv = opts.conf.argv.remain - if (argv.length === 2) + if (argv.length === 2) { return ['fix'] + } switch (argv[2]) { case 'fix': @@ -60,9 +61,9 @@ class Audit extends ArboristWorkspaceCmd { const arb = new Arborist(opts) const fix = args[0] === 'fix' await arb.audit({ fix }) - if (fix) + if (fix) { await reifyFinish(this.npm, arb) - else { + } else { // will throw if there's an error, because this is an audit command auditError(this.npm, arb.auditReport) const result = auditReport(arb.auditReport, opts) diff --git a/lib/commands/bin.js b/lib/commands/bin.js index 9a894f3bb..68559e413 100644 --- a/lib/commands/bin.js +++ b/lib/commands/bin.js @@ -17,8 +17,9 @@ class Bin extends BaseCommand { async exec (args) { const b = this.npm.bin this.npm.output(b) - if (this.npm.config.get('global') && !envPath.includes(b)) + if (this.npm.config.get('global') && !envPath.includes(b)) { console.error('(not in PATH env variable)') + } } } module.exports = Bin diff --git a/lib/commands/bugs.js b/lib/commands/bugs.js index 863a7ffec..ecf50f32e 100644 --- a/lib/commands/bugs.js +++ b/lib/commands/bugs.js @@ -23,8 +23,9 @@ class Bugs extends BaseCommand { } async exec (args) { - if (!args || !args.length) + if (!args || !args.length) { args = ['.'] + } await Promise.all(args.map(pkg => this.getBugs(pkg))) } @@ -39,20 +40,24 @@ class Bugs extends BaseCommand { getBugsUrl (mani) { if (mani.bugs) { - if (typeof mani.bugs === 'string') + if (typeof mani.bugs === 'string') { return mani.bugs + } - if (typeof mani.bugs === 'object' && mani.bugs.url) + if (typeof mani.bugs === 'object' && mani.bugs.url) { return mani.bugs.url + } - if (typeof mani.bugs === 'object' && mani.bugs.email) + if (typeof mani.bugs === 'object' && mani.bugs.email) { return `mailto:${mani.bugs.email}` + } } // try to get it from the repo, if possible const info = hostedFromMani(mani) - if (info) + if (info) { return info.bugs() + } // just send them to the website, hopefully that has some info! return `https://www.npmjs.com/package/${mani.name}` diff --git a/lib/commands/cache.js b/lib/commands/cache.js index b4a932d1b..9a089c562 100644 --- a/lib/commands/cache.js +++ b/lib/commands/cache.js @@ -12,8 +12,10 @@ const localeCompare = require('@isaacs/string-locale-compare')('en') const searchCachePackage = async (path, spec, cacheKeys) => { const parsed = npa(spec) - if (parsed.rawSpec !== '' && parsed.type === 'tag') + if (parsed.rawSpec !== '' && parsed.type === 'tag') { throw new Error(`Cannot list cache keys for a tagged package.`) + } + /* eslint-disable-next-line max-len */ const searchMFH = new RegExp(`^make-fetch-happen:request-cache:.*(?<!/[@a-zA-Z]+)/${parsed.name}/-/(${parsed.name}[^/]+.tgz)$`) const searchPack = new RegExp(`^make-fetch-happen:request-cache:.*/${parsed.escapedName}$`) const results = new Set() @@ -26,13 +28,15 @@ const searchCachePackage = async (path, spec, cacheKeys) => { const noExt = filename.slice(0, -4) const noScope = `${parsed.name.split('/').pop()}-` const ver = noExt.slice(noScope.length) - if (semver.satisfies(ver, parsed.rawSpec)) + if (semver.satisfies(ver, parsed.rawSpec)) { results.add(key) + } continue } // is this key a packument? - if (!searchPack.test(key)) + if (!searchPack.test(key)) { continue + } results.add(key) let packument, details @@ -43,16 +47,19 @@ const searchCachePackage = async (path, spec, cacheKeys) => { // if we couldn't parse the packument, abort continue } - if (!packument.versions || typeof packument.versions !== 'object') + if (!packument.versions || typeof packument.versions !== 'object') { continue + } // assuming this is a packument for (const ver of Object.keys(packument.versions)) { if (semver.satisfies(ver, parsed.rawSpec)) { - if (packument.versions[ver].dist - && typeof packument.versions[ver].dist === 'object' - && packument.versions[ver].dist.tarball !== undefined - && cacheKeys.has(`make-fetch-happen:request-cache:${packument.versions[ver].dist.tarball}`)) + if (packument.versions[ver].dist && + typeof packument.versions[ver].dist === 'object' && + packument.versions[ver].dist.tarball !== undefined && + cacheKeys.has(`make-fetch-happen:request-cache:${packument.versions[ver].dist.tarball}`) + ) { results.add(`make-fetch-happen:request-cache:${packument.versions[ver].dist.tarball}`) + } } } } @@ -90,8 +97,9 @@ class Cache extends BaseCommand { async completion (opts) { const argv = opts.conf.argv.remain - if (argv.length === 2) + if (argv.length === 2) { return ['add', 'clean', 'verify', 'ls', 'delete'] + } // TODO - eventually... switch (argv[2]) { @@ -162,8 +170,9 @@ class Cache extends BaseCommand { // npm cache add <folder>... async add (args) { log.silly('cache add', 'args', args) - if (args.length === 0) + if (args.length === 0) { throw this.usageError('First argument to `add` is required') + } return Promise.all(args.map(spec => { log.silly('cache add', 'spec', spec) @@ -185,9 +194,16 @@ class Cache extends BaseCommand { const stats = await cacache.verify(cache) this.npm.output(`Cache verified and compressed (${prefix})`) this.npm.output(`Content verified: ${stats.verifiedContent} (${stats.keptSize} bytes)`) - stats.badContentCount && this.npm.output(`Corrupted content removed: ${stats.badContentCount}`) - stats.reclaimedCount && this.npm.output(`Content garbage-collected: ${stats.reclaimedCount} (${stats.reclaimedSize} bytes)`) - stats.missingContent && this.npm.output(`Missing content: ${stats.missingContent}`) + if (stats.badContentCount) { + this.npm.output(`Corrupted content removed: ${stats.badContentCount}`) + } + if (stats.reclaimedCount) { + /* eslint-disable-next-line max-len */ + this.npm.output(`Content garbage-collected: ${stats.reclaimedCount} (${stats.reclaimedSize} bytes)`) + } + if (stats.missingContent) { + this.npm.output(`Missing content: ${stats.missingContent}`) + } this.npm.output(`Index entries: ${stats.totalEntries}`) this.npm.output(`Finished in ${stats.runTime.total / 1000}s`) } @@ -201,8 +217,9 @@ class Cache extends BaseCommand { const results = new Set() for (const spec of specs) { const keySet = await searchCachePackage(cachePath, spec, cacheKeys) - for (const key of keySet) + for (const key of keySet) { results.add(key) + } } [...results].sort(localeCompare).forEach(key => this.npm.output(key)) return diff --git a/lib/commands/completion.js b/lib/commands/completion.js index fbbde0df7..bce6c3619 100644 --- a/lib/commands/completion.js +++ b/lib/commands/completion.js @@ -57,8 +57,9 @@ class Completion extends BaseCommand { // completion for the completion command async completion (opts) { - if (opts.w > 2) + if (opts.w > 2) { return + } const { resolve } = require('path') const [bashExists, zshExists] = await Promise.all([ @@ -66,11 +67,13 @@ class Completion extends BaseCommand { fileExists(resolve(process.env.HOME, '.zshrc')), ]) const out = [] - if (zshExists) + if (zshExists) { out.push(['>>', '~/.zshrc']) + } - if (bashExists) + if (bashExists) { out.push(['>>', '~/.bashrc']) + } return out } @@ -88,8 +91,9 @@ class Completion extends BaseCommand { // if the COMP_* isn't in the env, then just dump the script. if (COMP_CWORD === undefined || COMP_LINE === undefined || - COMP_POINT === undefined) + COMP_POINT === undefined) { return dumpScript() + } // ok we're actually looking at the envs and outputting the suggestions // get the partial line and partial word, @@ -106,8 +110,9 @@ class Completion extends BaseCommand { // figure out where in that last word the point is. const partialWordRaw = args[w] let i = partialWordRaw.length - while (partialWordRaw.substr(0, i) !== partialLine.substr(-1 * i) && i > 0) + while (partialWordRaw.substr(0, i) !== partialLine.substr(-1 * i) && i > 0) { i-- + } const partialWord = unescape(partialWordRaw.substr(0, i)) partialWords.push(partialWord) @@ -126,8 +131,9 @@ class Completion extends BaseCommand { } if (partialWords.slice(0, -1).indexOf('--') === -1) { - if (word.charAt(0) === '-') + if (word.charAt(0) === '-') { return this.wrap(opts, configCompl(opts)) + } if (words[w - 1] && words[w - 1].charAt(0) === '-' && @@ -151,8 +157,9 @@ class Completion extends BaseCommand { nopt(types, shorthands, partialWords.slice(0, -1), 0) // check if there's a command already. const cmd = parsed.argv.remain[1] - if (!cmd) + if (!cmd) { return this.wrap(opts, cmdCompl(opts)) + } Object.keys(parsed).forEach(k => this.npm.config.set(k, parsed[k])) @@ -173,17 +180,20 @@ class Completion extends BaseCommand { // Ie, returning ['a', 'b c', ['d', 'e']] would allow it to expand // to: 'a', 'b c', or 'd' 'e' wrap (opts, compls) { - if (!Array.isArray(compls)) + if (!Array.isArray(compls)) { compls = compls ? [compls] : [] + } compls = compls.map(c => Array.isArray(c) ? c.map(escape).join(' ') : escape(c)) - if (opts.partialWord) + if (opts.partialWord) { compls = compls.filter(c => c.startsWith(opts.partialWord)) + } - if (compls.length > 0) + if (compls.length > 0) { this.npm.output(compls.join('\n')) + } } } @@ -197,8 +207,9 @@ const dumpScript = async () => { await new Promise((res, rej) => { let done = false process.stdout.on('error', er => { - if (done) + if (done) { return + } done = true @@ -214,15 +225,17 @@ const dumpScript = async () => { // can never ever work on OS X. // TODO Ignoring coverage, see 'non EPIPE errors cause failures' test. /* istanbul ignore next */ - if (er.errno === 'EPIPE') + if (er.errno === 'EPIPE') { res() - else + } else { rej(er) + } }) process.stdout.write(d, () => { - if (done) + if (done) { return + } done = true res() @@ -258,7 +271,7 @@ const isFlag = word => { const split = word.match(/^(-*)((?:no-)+)?(.*)$/) const no = split[2] const conf = split[3] - const {type} = definitions[conf] + const { type } = definitions[conf] return no || type === Boolean || (Array.isArray(type) && type.includes(Boolean)) || @@ -269,12 +282,14 @@ const isFlag = word => { // if they all resolve to the same thing, just return the thing it already is const cmdCompl = opts => { const matches = fullList.filter(c => c.startsWith(opts.partialWord)) - if (!matches.length) + if (!matches.length) { return matches + } const derefs = new Set([...matches.map(c => deref(c))]) - if (derefs.size === 1) + if (derefs.size === 1) { return [...derefs] + } return fullList } diff --git a/lib/commands/config.js b/lib/commands/config.js index fc482edb6..0e92f6f3e 100644 --- a/lib/commands/config.js +++ b/lib/commands/config.js @@ -64,13 +64,15 @@ class Config extends BaseCommand { async completion (opts) { const argv = opts.conf.argv.remain - if (argv[1] !== 'config') + if (argv[1] !== 'config') { argv.unshift('config') + } if (argv.length === 2) { const cmds = ['get', 'set', 'delete', 'ls', 'rm', 'edit'] - if (opts.partialWord !== 'l') + if (opts.partialWord !== 'l') { cmds.push('list') + } return cmds } @@ -79,8 +81,9 @@ class Config extends BaseCommand { switch (action) { case 'set': // todo: complete with valid values, if possible. - if (argv.length > 3) + if (argv.length > 3) { return [] + } // fallthrough /* eslint no-fallthrough:0 */ @@ -132,28 +135,32 @@ class Config extends BaseCommand { } async set (args) { - if (!args.length) + if (!args.length) { throw this.usageError() + } const where = this.npm.flatOptions.location for (const [key, val] of Object.entries(keyValues(args))) { this.npm.log.info('config', 'set %j %j', key, val) this.npm.config.set(key, val || '', where) - if (!this.npm.config.validate(where)) + if (!this.npm.config.validate(where)) { this.npm.log.warn('config', 'omitting invalid config values') + } } await this.npm.config.save(where) } async get (keys) { - if (!keys.length) + if (!keys.length) { return this.list() + } const out = [] for (const key of keys) { - if (!publicVar(key)) + if (!publicVar(key)) { throw `The ${key} option is protected, and cannot be retrieved in this way` + } const pref = keys.length > 1 ? `${key}=` : '' out.push(pref + this.npm.config.get(key)) @@ -162,12 +169,14 @@ class Config extends BaseCommand { } async del (keys) { - if (!keys.length) + if (!keys.length) { throw this.usageError() + } const where = this.npm.flatOptions.location - for (const key of keys) + for (const key of keys) { this.npm.config.delete(key, where) + } await this.npm.config.save(where) } @@ -220,8 +229,9 @@ ${defData} const [bin, ...args] = e.split(/\s+/) const editor = spawn(bin, [...args, file], { stdio: 'inherit' }) editor.on('exit', (code) => { - if (code) + if (code) { return reject(new Error(`editor process exited with code: ${code}`)) + } return resolve() }) }) @@ -232,12 +242,14 @@ ${defData} // long does not have a flattener const long = this.npm.config.get('long') for (const [where, { data, source }] of this.npm.config.data.entries()) { - if (where === 'default' && !long) + if (where === 'default' && !long) { continue + } const keys = Object.keys(data).sort(localeCompare) - if (!keys.length) + if (!keys.length) { continue + } msg.push(`; "${where}" config from ${source}`, '') for (const k of keys) { @@ -265,8 +277,9 @@ ${defData} async listJson () { const publicConf = {} for (const key in this.npm.config.list[0]) { - if (!publicVar(key)) + if (!publicVar(key)) { continue + } publicConf[key] = this.npm.config.get(key) } diff --git a/lib/commands/deprecate.js b/lib/commands/deprecate.js index 37b9d2dc2..1e33b98bf 100644 --- a/lib/commands/deprecate.js +++ b/lib/commands/deprecate.js @@ -30,8 +30,9 @@ class Deprecate extends BaseCommand { } async completion (opts) { - if (opts.conf.argv.remain.length > 1) + if (opts.conf.argv.remain.length > 1) { return [] + } const username = await getIdentity(this.npm, this.npm.flatOptions) const packages = await libaccess.lsPackages(username, this.npm.flatOptions) @@ -44,8 +45,9 @@ class Deprecate extends BaseCommand { async exec ([pkg, msg]) { // msg == null because '' is a valid value, it indicates undeprecate - if (!pkg || msg == null) + if (!pkg || msg == null) { throw this.usageError() + } // fetch the data and make sure it exists. const p = npa(pkg) @@ -53,8 +55,9 @@ class Deprecate extends BaseCommand { // "*" is the appropriate default. const spec = p.rawSpec === '' ? '*' : p.fetchSpec - if (semver.validRange(spec, true) === null) + if (semver.validRange(spec, true) === null) { throw new Error(`invalid version range: ${spec}`) + } const uri = '/' + p.escapedName const packument = await fetch.json(uri, { diff --git a/lib/commands/diff.js b/lib/commands/diff.js index 67d0d1505..f6e2cce8b 100644 --- a/lib/commands/diff.js +++ b/lib/commands/diff.js @@ -49,22 +49,25 @@ class Diff extends BaseCommand { async exec (args) { const specs = this.npm.config.get('diff').filter(d => d) - if (specs.length > 2) + if (specs.length > 2) { throw this.usageError(`Can't use more than two --diff arguments.`) + } // execWorkspaces may have set this already - if (!this.prefix) + if (!this.prefix) { this.prefix = this.npm.prefix + } // this is the "top" directory, one up from node_modules // in global mode we have to walk one up from globalDir because our // node_modules is sometimes under ./lib, and in global mode we're only ever // walking through node_modules (because we will have been given a package // name already) - if (this.npm.config.get('global')) + if (this.npm.config.get('global')) { this.top = resolve(this.npm.globalDir, '..') - else + } else { this.top = this.prefix + } const [a, b] = await this.retrieveSpecs(specs) npmlog.info('diff', { src: a, dst: b }) @@ -96,8 +99,9 @@ class Diff extends BaseCommand { npmlog.verbose('diff', 'could not read project dir package.json') } - if (!name) + if (!name) { throw this.usageError('Needs multiple arguments to compare or run from a project dir.') + } return name } @@ -129,14 +133,16 @@ class Diff extends BaseCommand { noPackageJson = true } - const missingPackageJson = this.usageError('Needs multiple arguments to compare or run from a project dir.') + const missingPackageJson = + this.usageError('Needs multiple arguments to compare or run from a project dir.') // using a valid semver range, that means it should just diff // the cwd against a published version to the registry using the // same project name and the provided semver range if (semver.validRange(a)) { - if (!pkgName) + if (!pkgName) { throw missingPackageJson + } return [ `${pkgName}@${a}`, `file:${this.prefix}`, @@ -165,8 +171,9 @@ class Diff extends BaseCommand { } if (!node || !node.name || !node.package || !node.package.version) { - if (noPackageJson) + if (noPackageJson) { throw missingPackageJson + } return [ `${spec.name}@${spec.fetchSpec}`, `file:${this.prefix}`, @@ -177,8 +184,9 @@ class Diff extends BaseCommand { (actualTree && actualTree.edgesOut.get(spec.name) || {}).spec const tryAnySpec = () => { - for (const edge of node.edgesIn) + for (const edge of node.edgesIn) { return edge.spec + } } const aSpec = `file:${node.realpath}` @@ -188,9 +196,9 @@ class Diff extends BaseCommand { // work from the top of the arborist tree to find the original semver // range declared in the package that depends on the package. let bSpec - if (spec.rawSpec) + if (spec.rawSpec) { bSpec = spec.rawSpec - else { + } else { const bTargetVersion = tryRootNodeSpec() || tryAnySpec() @@ -217,8 +225,9 @@ class Diff extends BaseCommand { `file:${spec.fetchSpec}`, `file:${this.prefix}`, ] - } else + } else { throw this.usageError(`Spec type ${spec.type} not supported.`) + } } async convertVersionsToSpecs ([a, b]) { @@ -234,19 +243,22 @@ class Diff extends BaseCommand { npmlog.verbose('diff', 'could not read project dir package.json') } - if (!pkgName) + if (!pkgName) { throw this.usageError('Needs to be run from a project dir in order to diff two versions.') + } return [`${pkgName}@${a}`, `${pkgName}@${b}`] } // otherwise uses the name from the other arg to // figure out the spec.name of what to compare - if (!semverA && semverB) + if (!semverA && semverB) { return [a, `${npa(a).name}@${b}`] + } - if (semverA && !semverB) + if (semverA && !semverB) { return [`${npa(b).name}@${a}`, b] + } // no valid semver ranges used return [a, b] @@ -267,8 +279,9 @@ class Diff extends BaseCommand { return specs.map(i => { const spec = npa(i) - if (spec.rawSpec) + if (spec.rawSpec) { return i + } const node = actualTree && actualTree.inventory.query('name', spec.name) diff --git a/lib/commands/dist-tag.js b/lib/commands/dist-tag.js index b7baa3d46..9c938851a 100644 --- a/lib/commands/dist-tag.js +++ b/lib/commands/dist-tag.js @@ -33,8 +33,9 @@ class DistTag extends BaseCommand { async completion (opts) { const argv = opts.conf.argv.remain - if (argv.length === 2) + if (argv.length === 2) { return ['add', 'rm', 'ls'] + } switch (argv[2]) { default: @@ -45,21 +46,25 @@ class DistTag extends BaseCommand { async exec ([cmdName, pkg, tag]) { const opts = this.npm.flatOptions - if (['add', 'a', 'set', 's'].includes(cmdName)) + if (['add', 'a', 'set', 's'].includes(cmdName)) { return this.add(pkg, tag, opts) + } - if (['rm', 'r', 'del', 'd', 'remove'].includes(cmdName)) + if (['rm', 'r', 'del', 'd', 'remove'].includes(cmdName)) { return this.remove(pkg, tag, opts) + } - if (['ls', 'l', 'sl', 'list'].includes(cmdName)) + if (['ls', 'l', 'sl', 'list'].includes(cmdName)) { return this.list(pkg, opts) + } if (!pkg) { // when only using the pkg name the default behavior // should be listing the existing tags return this.list(cmdName, opts) - } else + } else { throw this.usageError() + } } async execWorkspaces ([cmdName, pkg, tag], filters) { @@ -68,16 +73,18 @@ class DistTag extends BaseCommand { // - unset // - . // - .@version - if (['ls', 'l', 'sl', 'list'].includes(cmdName) && (!pkg || pkg === '.' || /^\.@/.test(pkg))) + if (['ls', 'l', 'sl', 'list'].includes(cmdName) && (!pkg || pkg === '.' || /^\.@/.test(pkg))) { return this.listWorkspaces(filters) + } // pkg is unset // cmdName is one of: // - unset // - . // - .@version - if (!pkg && (!cmdName || cmdName === '.' || /^\.@/.test(cmdName))) + if (!pkg && (!cmdName || cmdName === '.' || /^\.@/.test(cmdName))) { return this.listWorkspaces(filters) + } // anything else is just a regular dist-tag command // so we fallback to the non-workspaces implementation @@ -92,13 +99,15 @@ class DistTag extends BaseCommand { log.verbose('dist-tag add', defaultTag, 'to', spec.name + '@' + version) - if (!spec.name || !version || !defaultTag) + if (!spec.name || !version || !defaultTag) { throw this.usageError() + } const t = defaultTag.trim() - if (semver.validRange(t)) + if (semver.validRange(t)) { throw new Error('Tag name must not be a valid SemVer range: ' + t) + } const tags = await this.fetchTags(spec, opts) if (tags[t] === version) { @@ -125,8 +134,9 @@ class DistTag extends BaseCommand { spec = npa(spec || '') log.verbose('dist-tag del', tag, 'from', spec.name) - if (!spec.name) + if (!spec.name) { throw this.usageError() + } const tags = await this.fetchTags(spec, opts) if (!tags[tag]) { @@ -148,11 +158,13 @@ class DistTag extends BaseCommand { async list (spec, opts) { if (!spec) { - if (this.npm.config.get('global')) + if (this.npm.config.get('global')) { throw this.usageError() + } const pkg = await readPackageName(this.npm.prefix) - if (!pkg) + if (!pkg) { throw this.usageError() + } return this.list(pkg, opts) } @@ -190,10 +202,12 @@ class DistTag extends BaseCommand { `/-/package/${spec.escapedName}/dist-tags`, { ...opts, 'prefer-online': true, spec } ) - if (data && typeof data === 'object') + if (data && typeof data === 'object') { delete data._etag - if (!data || !Object.keys(data).length) + } + if (!data || !Object.keys(data).length) { throw new Error('No dist-tags found for ' + spec.name) + } return data } diff --git a/lib/commands/docs.js b/lib/commands/docs.js index 4482678ea..e73528d18 100644 --- a/lib/commands/docs.js +++ b/lib/commands/docs.js @@ -32,8 +32,9 @@ class Docs extends BaseCommand { } async exec (args) { - if (!args || !args.length) + if (!args || !args.length) { args = ['.'] + } await Promise.all(args.map(pkg => this.getDocs(pkg))) } @@ -52,12 +53,14 @@ class Docs extends BaseCommand { } getDocsUrl (mani) { - if (mani.homepage) + if (mani.homepage) { return mani.homepage + } const info = hostedFromMani(mani) - if (info) + if (info) { return info.docs() + } return 'https://www.npmjs.com/package/' + mani.name } diff --git a/lib/commands/doctor.js b/lib/commands/doctor.js index b6363467c..8cb774ee3 100644 --- a/lib/commands/doctor.js +++ b/lib/commands/doctor.js @@ -11,21 +11,26 @@ const { promisify } = require('util') const ansiTrim = require('../utils/ansi-trim.js') const isWindows = require('../utils/is-windows.js') const ping = require('../utils/ping.js') -const { registry: { default: defaultRegistry } } = require('../utils/config/definitions.js') +const { + registry: { default: defaultRegistry }, +} = require('../utils/config/definitions.js') const lstat = promisify(fs.lstat) const readdir = promisify(fs.readdir) const access = promisify(fs.access) const { R_OK, W_OK, X_OK } = fs.constants const maskLabel = mask => { const label = [] - if (mask & R_OK) + if (mask & R_OK) { label.push('readable') + } - if (mask & W_OK) + if (mask & W_OK) { label.push('writable') + } - if (mask & X_OK) + if (mask & X_OK) { label.push('executable') + } return label.join(', ') } @@ -59,13 +64,31 @@ class Doctor extends BaseCommand { ['node -v', 'getLatestNodejsVersion', []], ['npm config get registry', 'checkNpmRegistry', []], ['which git', 'getGitPath', []], - ...(isWindows ? [] : [ - ['Perms check on cached files', 'checkFilesPermission', [this.npm.cache, true, R_OK]], - ['Perms check on local node_modules', 'checkFilesPermission', [this.npm.localDir, true]], - ['Perms check on global node_modules', 'checkFilesPermission', [this.npm.globalDir, false]], - ['Perms check on local bin folder', 'checkFilesPermission', [this.npm.localBin, false, R_OK | W_OK | X_OK]], - ['Perms check on global bin folder', 'checkFilesPermission', [this.npm.globalBin, false, X_OK]], - ]), + ...(isWindows + ? [] + : [ + ['Perms check on cached files', 'checkFilesPermission', [this.npm.cache, true, R_OK]], + [ + 'Perms check on local node_modules', + 'checkFilesPermission', + [this.npm.localDir, true], + ], + [ + 'Perms check on global node_modules', + 'checkFilesPermission', + [this.npm.globalDir, false], + ], + [ + 'Perms check on local bin folder', + 'checkFilesPermission', + [this.npm.localBin, false, R_OK | W_OK | X_OK], + ], + [ + 'Perms check on global bin folder', + 'checkFilesPermission', + [this.npm.globalBin, false, X_OK], + ], + ]), ['Verify cache contents', 'verifyCachedFiles', [this.npm.flatOptions.cache]], // TODO: // - ensure arborist.loadActual() runs without errors and no invalid edges @@ -85,39 +108,43 @@ class Doctor extends BaseCommand { messages.push(line) } - const outHead = ['Check', 'Value', 'Recommendation/Notes'] - .map(!this.npm.color ? h => h : h => chalk.underline(h)) + const outHead = ['Check', 'Value', 'Recommendation/Notes'].map( + !this.npm.color ? h => h : h => chalk.underline(h) + ) let allOk = true - const outBody = messages.map(!this.npm.color - ? item => { - allOk = allOk && item[1] - item[1] = item[1] ? 'ok' : 'not ok' - item[2] = String(item[2]) - return item - } - : item => { - allOk = allOk && item[1] - if (!item[1]) { - item[0] = chalk.red(item[0]) - item[2] = chalk.magenta(String(item[2])) + const outBody = messages.map( + !this.npm.color + ? item => { + allOk = allOk && item[1] + item[1] = item[1] ? 'ok' : 'not ok' + item[2] = String(item[2]) + return item } - item[1] = item[1] ? chalk.green('ok') : chalk.red('not ok') - return item - }) + : item => { + allOk = allOk && item[1] + if (!item[1]) { + item[0] = chalk.red(item[0]) + item[2] = chalk.magenta(String(item[2])) + } + item[1] = item[1] ? chalk.green('ok') : chalk.red('not ok') + return item + } + ) const outTable = [outHead, ...outBody] const tableOpts = { stringLength: s => ansiTrim(s).length, } - const silent = this.npm.log.levels[this.npm.log.level] > - this.npm.log.levels.error + const silent = this.npm.log.levels[this.npm.log.level] > this.npm.log.levels.error if (!silent) { this.npm.output(table(outTable, tableOpts)) - if (!allOk) + if (!allOk) { console.error('') + } } - if (!allOk) + if (!allOk) { throw new Error('Some problems found. See above for recommendations.') + } } async checkPing () { @@ -127,10 +154,11 @@ class Doctor extends BaseCommand { await ping(this.npm.flatOptions) return '' } catch (er) { - if (/^E\d{3}$/.test(er.code || '')) + if (/^E\d{3}$/.test(er.code || '')) { throw er.code.substr(1) + ' ' + er.message - else + } else { throw er.message + } } finally { tracker.finish() } @@ -141,10 +169,11 @@ class Doctor extends BaseCommand { 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)) + if (semver.gte(this.npm.version, latest)) { return `current: v${this.npm.version}, latest: v${latest}` - else + } else { throw `Use npm v${latest}` + } } finally { tracker.finish() } @@ -163,26 +192,29 @@ class Doctor extends BaseCommand { let maxCurrent = '0.0.0' let maxLTS = '0.0.0' for (const { lts, version } of data) { - if (lts && semver.gt(version, maxLTS)) + if (lts && semver.gt(version, maxLTS)) { maxLTS = version + } - if (semver.satisfies(version, currentRange) && - semver.gt(version, maxCurrent)) + if (semver.satisfies(version, currentRange) && semver.gt(version, maxCurrent)) { maxCurrent = version + } } const recommended = semver.gt(maxCurrent, maxLTS) ? maxCurrent : maxLTS - if (semver.gte(process.version, recommended)) + if (semver.gte(process.version, recommended)) { return `current: ${current}, recommended: ${recommended}` - else + } else { throw `Use node ${recommended} (current: ${current})` + } } finally { tracker.finish() } } async checkFilesPermission (root, shouldOwn, mask = null) { - if (mask === null) + if (mask === null) { mask = shouldOwn ? R_OK | W_OK : R_OK + } let ok = true @@ -194,24 +226,25 @@ class Doctor extends BaseCommand { const files = new Set([root]) for (const f of files) { tracker.silly('checkFilesPermission', f.substr(root.length + 1)) - const st = await lstat(f) - .catch(er => { - ok = false - tracker.warn('checkFilesPermission', 'error getting info for ' + f) - }) + const st = await lstat(f).catch(er => { + ok = false + tracker.warn('checkFilesPermission', 'error getting info for ' + f) + }) tracker.completeWork(1) - if (!st) + if (!st) { continue + } if (shouldOwn && (uid !== st.uid || gid !== st.gid)) { tracker.warn('checkFilesPermission', 'should be owner of ' + f) ok = false } - if (!st.isDirectory() && !st.isFile()) + if (!st.isDirectory() && !st.isFile()) { continue + } try { await access(f, mask) @@ -223,23 +256,26 @@ class Doctor extends BaseCommand { } if (st.isDirectory()) { - const entries = await readdir(f) - .catch(er => { - ok = false - tracker.warn('checkFilesPermission', 'error reading directory ' + f) - return [] - }) - for (const entry of entries) + const entries = await readdir(f).catch(er => { + ok = false + tracker.warn('checkFilesPermission', 'error reading directory ' + f) + return [] + }) + for (const entry of entries) { files.add(resolve(f, entry)) + } } } } finally { tracker.finish() if (!ok) { - throw `Check the permissions of files in ${root}` + + throw ( + `Check the permissions of files in ${root}` + (shouldOwn ? ' (should be owned by current user)' : '') - } else + ) + } else { return '' + } } } @@ -261,27 +297,29 @@ class Doctor extends BaseCommand { tracker.info('verifyCachedFiles', 'Verifying the npm cache') try { const stats = await cacache.verify(this.npm.flatOptions.cache) - const { - badContentCount, - reclaimedCount, - missingContent, - reclaimedSize, - } = stats + const { badContentCount, reclaimedCount, missingContent, reclaimedSize } = stats if (badContentCount || reclaimedCount || missingContent) { - if (badContentCount) + if (badContentCount) { tracker.warn('verifyCachedFiles', `Corrupted content removed: ${badContentCount}`) + } - if (reclaimedCount) - tracker.warn('verifyCachedFiles', `Content garbage-collected: ${reclaimedCount} (${reclaimedSize} bytes)`) + if (reclaimedCount) { + tracker.warn( + 'verifyCachedFiles', + `Content garbage-collected: ${reclaimedCount} (${reclaimedSize} bytes)` + ) + } - if (missingContent) + if (missingContent) { tracker.warn('verifyCachedFiles', `Missing content: ${missingContent}`) + } tracker.warn('verifyCachedFiles', 'Cache issues have been fixed') } - tracker.info('verifyCachedFiles', `Verification complete. Stats: ${ - JSON.stringify(stats, null, 2) - }`) + tracker.info( + 'verifyCachedFiles', + `Verification complete. Stats: ${JSON.stringify(stats, null, 2)}` + ) return `verified ${stats.verifiedContent} tarballs` } finally { tracker.finish() @@ -289,10 +327,11 @@ class Doctor extends BaseCommand { } async checkNpmRegistry () { - if (this.npm.flatOptions.registry !== defaultRegistry) + if (this.npm.flatOptions.registry !== defaultRegistry) { throw `Try \`npm config set registry=${defaultRegistry}\`` - else + } else { return `using default registry (${defaultRegistry})` + } } } diff --git a/lib/commands/edit.js b/lib/commands/edit.js index 4f0af6e83..3a9a10b40 100644 --- a/lib/commands/edit.js +++ b/lib/commands/edit.js @@ -34,8 +34,9 @@ class Edit extends BaseCommand { } async exec (args) { - if (args.length !== 1) + if (args.length !== 1) { throw this.usageError() + } const path = splitPackageNames(args[0]) const dir = resolve(this.npm.dir, path) @@ -43,13 +44,15 @@ class Edit extends BaseCommand { // graceful-fs does not promisify await new Promise((resolve, reject) => { fs.lstat(dir, (err) => { - if (err) + if (err) { return reject(err) + } const [bin, ...args] = this.npm.config.get('editor').split(/\s+/) const editor = spawn(bin, [...args, dir], { stdio: 'inherit' }) editor.on('exit', (code) => { - if (code) + if (code) { return reject(new Error(`editor process exited with code: ${code}`)) + } this.npm.exec('rebuild', [dir]).catch(reject).then(resolve) }) }) diff --git a/lib/commands/exec.js b/lib/commands/exec.js index ffe72ccb4..86a806eb5 100644 --- a/lib/commands/exec.js +++ b/lib/commands/exec.js @@ -60,11 +60,13 @@ class Exec extends BaseCommand { } async exec (_args, { locationMsg, path, runPath } = {}) { - if (!path) + if (!path) { path = this.npm.localPrefix + } - if (!runPath) + if (!runPath) { runPath = process.cwd() + } const args = [..._args] const call = this.npm.config.get('call') @@ -79,8 +81,9 @@ class Exec extends BaseCommand { const packages = this.npm.config.get('package') const yes = this.npm.config.get('yes') - if (call && _args.length) + if (call && _args.length) { throw this.usageError() + } return libexec({ ...flatOptions, diff --git a/lib/commands/explain.js b/lib/commands/explain.js index 0ef41559f..03930c2f7 100644 --- a/lib/commands/explain.js +++ b/lib/commands/explain.js @@ -36,8 +36,9 @@ class Explain extends ArboristWorkspaceCmd { } async exec (args) { - if (!args.length) + if (!args.length) { throw this.usageError() + } const arb = new Arborist({ path: this.npm.prefix, ...this.npm.flatOptions }) const tree = await arb.loadActual() @@ -45,9 +46,9 @@ class Explain extends ArboristWorkspaceCmd { if (this.npm.flatOptions.workspacesEnabled && this.workspaceNames && this.workspaceNames.length - ) + ) { this.filterSet = arb.workspaceDependencySet(tree, this.workspaceNames) - else if (!this.npm.flatOptions.workspacesEnabled) { + } else if (!this.npm.flatOptions.workspacesEnabled) { this.filterSet = arb.excludeWorkspacesDependencySet(tree) } @@ -58,20 +59,22 @@ class Explain extends ArboristWorkspaceCmd { const filteredOut = this.filterSet && this.filterSet.size > 0 && !this.filterSet.has(node) - if (!filteredOut) + if (!filteredOut) { nodes.add(node) + } } } - if (nodes.size === 0) + if (nodes.size === 0) { throw new Error(`No dependencies found matching ${args.join(', ')}`) + } const expls = [] for (const node of nodes) { const { extraneous, dev, optional, devOptional, peer, inBundle } = node const expl = node.explain() - if (extraneous) + if (extraneous) { expl.extraneous = true - else { + } else { expl.dev = dev expl.optional = optional expl.devOptional = devOptional @@ -81,9 +84,9 @@ class Explain extends ArboristWorkspaceCmd { expls.push(expl) } - if (this.npm.flatOptions.json) + if (this.npm.flatOptions.json) { this.npm.output(JSON.stringify(expls, null, 2)) - else { + } else { this.npm.output(expls.map(expl => { return explainNode(expl, Infinity, this.npm.color) }).join('\n\n')) @@ -93,21 +96,24 @@ class Explain extends ArboristWorkspaceCmd { getNodes (tree, arg) { // if it's just a name, return packages by that name const { validForOldPackages: valid } = validName(arg) - if (valid) + if (valid) { return tree.inventory.query('packageName', arg) + } // if it's a location, get that node const maybeLoc = arg.replace(/\\/g, '/').replace(/\/+$/, '') const nodeByLoc = tree.inventory.get(maybeLoc) - if (nodeByLoc) + if (nodeByLoc) { return [nodeByLoc] + } // maybe a path to a node_modules folder const maybePath = relative(this.npm.prefix, resolve(maybeLoc)) .replace(/\\/g, '/').replace(/\/+$/, '') const nodeByPath = tree.inventory.get(maybePath) - if (nodeByPath) + if (nodeByPath) { return [nodeByPath] + } // otherwise, try to select all matching nodes try { @@ -119,8 +125,9 @@ class Explain extends ArboristWorkspaceCmd { getNodesByVersion (tree, arg) { const spec = npa(arg, this.npm.prefix) - if (spec.type !== 'version' && spec.type !== 'range') + if (spec.type !== 'version' && spec.type !== 'range') { return [] + } return tree.inventory.filter(node => { return node.package.name === spec.name && diff --git a/lib/commands/explore.js b/lib/commands/explore.js index 81a71f86a..d7397262c 100644 --- a/lib/commands/explore.js +++ b/lib/commands/explore.js @@ -33,15 +33,17 @@ class Explore extends BaseCommand { } async exec (args) { - if (args.length < 1 || !args[0]) + if (args.length < 1 || !args[0]) { throw this.usageError() + } const pkgname = args.shift() // detect and prevent any .. shenanigans const path = join(this.npm.dir, join('/', pkgname)) - if (relative(path, this.npm.dir) === '') + if (relative(path, this.npm.dir) === '') { throw this.usageError() + } // run as if running a script named '_explore', which we set to either // the set of arguments, or the shell config, and let @npmcli/run-script @@ -58,8 +60,9 @@ class Explore extends BaseCommand { _explore: args.join(' ').trim() || shell, } - if (!args.length) + if (!args.length) { this.npm.output(`\nExploring ${path}\nType 'exit' or ^D when finished\n`) + } this.npm.log.disableProgress() try { return await runScript({ @@ -76,8 +79,9 @@ class Explore extends BaseCommand { // if it's not an exit error, or non-interactive, throw it const isProcExit = er.message === 'command failed' && (typeof er.code === 'number' || /^SIG/.test(er.signal || '')) - if (args.length || !isProcExit) + if (args.length || !isProcExit) { throw er + } }) } finally { this.npm.log.enableProgress() diff --git a/lib/commands/fund.js b/lib/commands/fund.js index fbf78051d..e2a158bd4 100644 --- a/lib/commands/fund.js +++ b/lib/commands/fund.js @@ -5,11 +5,7 @@ const pacote = require('pacote') const semver = require('semver') const npa = require('npm-package-arg') const { depth } = require('treeverse') -const { - readTree: getFundingInfo, - normalizeFunding, - isValidFunding, -} = require('libnpmfund') +const { readTree: getFundingInfo, normalizeFunding, isValidFunding } = require('libnpmfund') const completion = require('../utils/completion/installed-deep.js') const openUrl = require('../utils/open-url.js') @@ -33,13 +29,7 @@ class Fund extends ArboristWorkspaceCmd { /* istanbul ignore next - see test/lib/load-all-commands.js */ static get params () { - return [ - 'json', - 'browser', - 'unicode', - 'workspace', - 'which', - ] + return ['json', 'browser', 'unicode', 'workspace', 'which'] } /* istanbul ignore next - see test/lib/load-all-commands.js */ @@ -59,11 +49,12 @@ class Fund extends ArboristWorkspaceCmd { const fundingSourceNumber = numberArg && parseInt(numberArg, 10) const badFundingSourceNumber = - numberArg !== null && - (String(fundingSourceNumber) !== numberArg || fundingSourceNumber < 1) + numberArg !== null && (String(fundingSourceNumber) !== numberArg || fundingSourceNumber < 1) if (badFundingSourceNumber) { - const err = new Error('`npm fund [<@scope>/]<pkg> [--which=fundingSourceNumber]` must be given a positive integer') + const err = new Error( + '`npm fund [<@scope>/]<pkg> [--which=fundingSourceNumber]` must be given a positive integer' + ) err.code = 'EFUNDNUMBER' throw err } @@ -95,10 +86,11 @@ class Fund extends ArboristWorkspaceCmd { workspaces: this.workspaceNames, }) - if (this.npm.config.get('json')) + if (this.npm.config.get('json')) { this.npm.output(this.printJSON(fundingInfo)) - else + } else { this.npm.output(this.printHuman(fundingInfo)) + } } printJSON (fundingInfo) { @@ -110,8 +102,7 @@ class Fund extends ArboristWorkspaceCmd { const unicode = this.npm.config.get('unicode') const seenUrls = new Map() - const tree = obj => - archy(obj, '', { unicode }) + const tree = obj => archy(obj, '', { unicode }) const result = depth({ tree: fundingInfo, @@ -119,9 +110,7 @@ class Fund extends ArboristWorkspaceCmd { // composes human readable package name // and creates a new archy item for readable output visit: ({ name, version, funding }) => { - const [fundingSource] = [] - .concat(normalizeFunding(funding)) - .filter(isValidFunding) + const [fundingSource] = [].concat(normalizeFunding(funding)).filter(isValidFunding) const { url } = fundingSource || {} const pkgRef = getPrintableName({ name, version }) let item = { @@ -139,8 +128,9 @@ class Fund extends ArboristWorkspaceCmd { item = seenUrls.get(url) item.label += `, ${pkgRef}` return null - } else + } else { seenUrls.set(url, item) + } } return item @@ -149,20 +139,20 @@ class Fund extends ArboristWorkspaceCmd { // puts child nodes back into returned archy // output while also filtering out missing items leave: (item, children) => { - if (item) + if (item) { item.nodes = children.filter(Boolean) + } return item }, // turns tree-like object return by libnpmfund // into children to be properly read by treeverse - getChildren: (node) => - Object.keys(node.dependencies || {}) - .map(key => ({ - name: key, - ...node.dependencies[key], - })), + getChildren: node => + Object.keys(node.dependencies || {}).map(key => ({ + name: key, + ...node.dependencies[key], + })), }) const res = tree(result) @@ -179,8 +169,9 @@ class Fund extends ArboristWorkspaceCmd { } else { // matches any file path within current arborist inventory for (const item of tree.inventory.values()) { - if (item.path === arg.fetchSpec) + if (item.path === arg.fetchSpec) { return item.package + } } } } else { @@ -190,17 +181,17 @@ class Fund extends ArboristWorkspaceCmd { .filter(i => semver.valid(i.package.version)) .sort((a, b) => semver.rcompare(a.package.version, b.package.version)) - if (item) + if (item) { return item.package + } } } - const { funding } = retrievePackageMetadata() || - await pacote.manifest(arg, this.npm.flatOptions).catch(() => ({})) + const { funding } = + retrievePackageMetadata() || + (await pacote.manifest(arg, this.npm.flatOptions).catch(() => ({}))) - const validSources = [] - .concat(normalizeFunding(funding)) - .filter(isValidFunding) + const validSources = [].concat(normalizeFunding(funding)).filter(isValidFunding) const matchesValidSource = validSources.length === 1 || @@ -218,7 +209,10 @@ class Fund extends ArboristWorkspaceCmd { const msg = `${typePrefix} available at the following URL` this.npm.output(`${i + 1}: ${msg}: ${url}`) }) - this.npm.output('Run `npm fund [<@scope>/]<pkg> --which=1`, for example, to open the first funding URL listed in that package') + this.npm.output( + /* eslint-disable-next-line max-len */ + 'Run `npm fund [<@scope>/]<pkg> --which=1`, for example, to open the first funding URL listed in that package' + ) } else { const noFundingError = new Error(`No valid funding method available for: ${spec}`) noFundingError.code = 'ENOFUND' diff --git a/lib/commands/help-search.js b/lib/commands/help-search.js index a179939ab..a2586f309 100644 --- a/lib/commands/help-search.js +++ b/lib/commands/help-search.js @@ -27,18 +27,20 @@ class HelpSearch extends BaseCommand { } async exec (args) { - if (!args.length) + if (!args.length) { throw this.usageError() + } const docPath = path.resolve(__dirname, '..', '..', 'docs/content') const files = await glob(`${docPath}/*/*.md`) const data = await this.readFiles(files) const results = await this.searchFiles(args, data, files) const formatted = this.formatResults(args, results) - if (!formatted.trim()) + if (!formatted.trim()) { this.npm.output(`No matches in help for: ${args.join(' ')}\n`) - else + } else { this.npm.output(formatted) + } } async readFiles (files) { @@ -55,8 +57,9 @@ class HelpSearch extends BaseCommand { for (const [file, content] of Object.entries(data)) { const lowerCase = content.toLowerCase() // skip if no matches at all - if (!args.some(a => lowerCase.includes(a.toLowerCase()))) + if (!args.some(a => lowerCase.includes(a.toLowerCase()))) { continue + } const lines = content.split(/\n+/) @@ -90,17 +93,20 @@ class HelpSearch extends BaseCommand { // now squish any string of nulls into a single null const pruned = lines.reduce((l, r) => { - if (!(r === null && l[l.length - 1] === null)) + if (!(r === null && l[l.length - 1] === null)) { l.push(r) + } return l }, []) - if (pruned[pruned.length - 1] === null) + if (pruned[pruned.length - 1] === null) { pruned.pop() + } - if (pruned[0] === null) + if (pruned[0] === null) { pruned.shift() + } // now count how many args were found const found = {} @@ -157,15 +163,17 @@ class HelpSearch extends BaseCommand { out.push(' '.repeat((Math.max(1, cols - out.join(' ').length - r.length - 1)))) out.push(r) - if (!this.npm.config.get('long')) + if (!this.npm.config.get('long')) { return out.join('') + } out.unshift('\n\n') out.push('\n') out.push('-'.repeat(cols - 1) + '\n') res.lines.forEach((line, i) => { - if (line === null || i > 3) + if (line === null || i > 3) { return + } if (!this.npm.color) { out.push(line + '\n') diff --git a/lib/commands/help.js b/lib/commands/help.js index bfc7f8b60..0de047615 100644 --- a/lib/commands/help.js +++ b/lib/commands/help.js @@ -34,8 +34,9 @@ class Help extends BaseCommand { } async completion (opts) { - if (opts.conf.argv.remain.length > 2) + if (opts.conf.argv.remain.length > 2) { return [] + } const g = path.resolve(__dirname, '../../man/man[0-9]/*.[0-9]') const files = await glob(g) @@ -51,15 +52,18 @@ class Help extends BaseCommand { // By default we search all of our man subdirectories, but if the user has // asked for a specific one we limit the search to just there let manSearch = 'man*' - if (/^\d+$/.test(args[0])) + if (/^\d+$/.test(args[0])) { manSearch = `man${args.shift()}` + } - if (!args.length) + if (!args.length) { return this.npm.output(await this.npm.usage) + } // npm help foo bar baz: search topics - if (args.length > 1) + if (args.length > 1) { return this.helpSearch(args) + } let section = this.npm.deref(args[0]) || args[0] @@ -76,17 +80,19 @@ class Help extends BaseCommand { const bManNumber = b.match(manNumberRegex)[1] // man number sort first so that 1 aka commands are preferred - if (aManNumber !== bManNumber) + if (aManNumber !== bManNumber) { return aManNumber - bManNumber + } return localeCompare(a, b) }) const man = mans[0] - if (man) + if (man) { await this.viewMan(man) - else + } else { return this.helpSearch(args) + } } helpSearch (args) { @@ -125,8 +131,9 @@ class Help extends BaseCommand { const proc = spawn(bin, args, opts) return new Promise((resolve, reject) => { proc.on('exit', (code) => { - if (code) + if (code) { return reject(new Error(`help process exited with code: ${code}`)) + } return resolve() }) diff --git a/lib/commands/hook.js b/lib/commands/hook.js index 7b2deff22..3ae2e07b4 100644 --- a/lib/commands/hook.js +++ b/lib/commands/hook.js @@ -50,9 +50,9 @@ class Hook extends BaseCommand { async add (pkg, uri, secret, opts) { const hook = await hookApi.add(pkg, uri, secret, opts) - if (opts.json) + if (opts.json) { this.npm.output(JSON.stringify(hook, null, 2)) - else if (opts.parseable) { + } else if (opts.parseable) { this.npm.output(Object.keys(hook).join('\t')) this.npm.output(Object.keys(hook).map(k => hook[k]).join('\t')) } else if (!opts.silent && opts.loglevel !== 'silent') { @@ -64,20 +64,21 @@ class Hook extends BaseCommand { async ls (pkg, opts) { const hooks = await hookApi.ls({ ...opts, package: pkg }) - if (opts.json) + if (opts.json) { this.npm.output(JSON.stringify(hooks, null, 2)) - else if (opts.parseable) { + } else if (opts.parseable) { this.npm.output(Object.keys(hooks[0]).join('\t')) hooks.forEach(hook => { this.npm.output(Object.keys(hook).map(k => hook[k]).join('\t')) }) - } else if (!hooks.length) + } else if (!hooks.length) { this.npm.output("You don't have any hooks configured yet.") - else if (!opts.silent && opts.loglevel !== 'silent') { - if (hooks.length === 1) + } else if (!opts.silent && opts.loglevel !== 'silent') { + if (hooks.length === 1) { this.npm.output('You have one hook configured.') - else + } else { this.npm.output(`You have ${hooks.length} hooks configured.`) + } const table = new Table({ head: ['id', 'target', 'endpoint'] }) hooks.forEach((hook) => { @@ -94,8 +95,9 @@ class Hook extends BaseCommand { }, hook.response_code, ]) - } else + } else { table.push([{ colSpan: 2, content: 'never triggered' }]) + } }) this.npm.output(table.toString()) } @@ -103,9 +105,9 @@ class Hook extends BaseCommand { async rm (id, opts) { const hook = await hookApi.rm(id, opts) - if (opts.json) + if (opts.json) { this.npm.output(JSON.stringify(hook, null, 2)) - else if (opts.parseable) { + } else if (opts.parseable) { this.npm.output(Object.keys(hook).join('\t')) this.npm.output(Object.keys(hook).map(k => hook[k]).join('\t')) } else if (!opts.silent && opts.loglevel !== 'silent') { @@ -117,9 +119,9 @@ class Hook extends BaseCommand { async update (id, uri, secret, opts) { const hook = await hookApi.update(id, uri, secret, opts) - if (opts.json) + if (opts.json) { this.npm.output(JSON.stringify(hook, null, 2)) - else if (opts.parseable) { + } else if (opts.parseable) { this.npm.output(Object.keys(hook).join('\t')) this.npm.output(Object.keys(hook).map(k => hook[k]).join('\t')) } else if (!opts.silent && opts.loglevel !== 'silent') { @@ -131,10 +133,12 @@ class Hook extends BaseCommand { hookName (hook) { let target = hook.name - if (hook.type === 'scope') + if (hook.type === 'scope') { target = '@' + target - if (hook.type === 'owner') + } + if (hook.type === 'owner') { target = '~' + target + } return target } } diff --git a/lib/commands/init.js b/lib/commands/init.js index b88b38436..1eb6fbf24 100644 --- a/lib/commands/init.js +++ b/lib/commands/init.js @@ -38,8 +38,9 @@ class Init extends BaseCommand { async exec (args) { // npm exec style - if (args.length) + if (args.length) { return (await this.execCreate({ args, path: process.cwd() })) + } // no args, uses classic init-package-json boilerplate await this.template() @@ -47,8 +48,9 @@ class Init extends BaseCommand { async execWorkspaces (args, filters) { // if the root package is uninitiated, take care of it first - if (this.npm.flatOptions.includeWorkspaceRoot) + if (this.npm.flatOptions.includeWorkspaceRoot) { await this.exec(args) + } // reads package.json for the top-level folder first, by doing this we // ensure the command throw if no package.json is found before trying @@ -80,9 +82,9 @@ class Init extends BaseCommand { const [initerName, ...otherArgs] = args let packageName = initerName - if (/^@[^/]+$/.test(initerName)) + if (/^@[^/]+$/.test(initerName)) { packageName = initerName + '/create' - else { + } else { const req = npa(initerName) if (req.type === 'git' && req.hosted) { const { user, project } = req.hosted @@ -90,8 +92,9 @@ class Init extends BaseCommand { .replace(user + '/' + project, user + '/create-' + project) } else if (req.registry) { packageName = req.name.replace(/^(@[^/]+\/)?/, '$1create-') - if (req.rawSpec) + if (req.rawSpec) { packageName += '@' + req.rawSpec + } } else { throw Object.assign(new Error( 'Unrecognized initializer: ' + initerName + @@ -166,9 +169,9 @@ class Init extends BaseCommand { this.npm.log.warn('init', 'canceled') return res() } - if (er) + if (er) { rej(er) - else { + } else { this.npm.log.info('init', 'written successfully') res(data) } @@ -181,8 +184,9 @@ class Init extends BaseCommand { // skip setting workspace if current package.json glob already satisfies it for (const wPath of workspaces.values()) { - if (wPath === workspacePath) + if (wPath === workspacePath) { return + } } // if a create-pkg didn't generate a package.json at the workspace diff --git a/lib/commands/install.js b/lib/commands/install.js index ea3bbcee3..95b5a5bac 100644 --- a/lib/commands/install.js +++ b/lib/commands/install.js @@ -1,5 +1,4 @@ /* eslint-disable camelcase */ -/* eslint-disable standard/no-callback-literal */ const fs = require('fs') const util = require('util') const readdir = util.promisify(fs.readdir) @@ -78,10 +77,11 @@ class Install extends ArboristWorkspaceCmd { const partialName = partialWord.slice(lastSlashIdx + 1) const partialPath = partialWord.slice(0, lastSlashIdx) || '/' - const annotatePackageDirMatch = async (sibling) => { + const annotatePackageDirMatch = async sibling => { const fullPath = join(partialPath, sibling) - if (sibling.slice(0, partialName.length) !== partialName) - return null // not name match + if (sibling.slice(0, partialName.length) !== partialName) { + return null + } // not name match try { const contents = await readdir(fullPath) @@ -136,10 +136,15 @@ class Install extends ArboristWorkspaceCmd { try { checks.checkEngine(npmManifest, npmManifest.version, process.version) } catch (e) { - if (forced) - this.npm.log.warn('install', `Forcing global npm install with incompatible version ${npmManifest.version} into node ${process.version}`) - else + if (forced) { + this.npm.log.warn( + 'install', + /* eslint-disable-next-line max-len */ + `Forcing global npm install with incompatible version ${npmManifest.version} into node ${process.version}` + ) + } else { throw e + } } } @@ -147,12 +152,17 @@ class Install extends ArboristWorkspaceCmd { args = args.filter(a => resolve(a) !== this.npm.prefix) // `npm i -g` => "install this package globally" - if (where === globalTop && !args.length) + if (where === globalTop && !args.length) { args = ['.'] + } // TODO: Add warnings for other deprecated flags? or remove this one? - if (isDev) - log.warn('install', 'Usage of the `--dev` option is deprecated. Use `--include=dev` instead.') + if (isDev) { + log.warn( + 'install', + 'Usage of the `--dev` option is deprecated. Use `--include=dev` instead.' + ) + } const opts = { ...this.npm.flatOptions, diff --git a/lib/commands/link.js b/lib/commands/link.js index 4a800d7c6..b4f4a1289 100644 --- a/lib/commands/link.js +++ b/lib/commands/link.js @@ -169,8 +169,9 @@ class Link extends ArboristWorkspaceCmd { // Returns a list of items that can't be fulfilled by // things found in the current arborist inventory missingArgsFromTree (tree, args) { - if (tree.isLink) + if (tree.isLink) { return this.missingArgsFromTree(tree.target, args) + } const foundNodes = [] const missing = args.filter(a => { @@ -193,8 +194,9 @@ class Link extends ArboristWorkspaceCmd { // remote nodes from the loaded tree in order // to avoid dropping them later when reifying - for (const node of foundNodes) + for (const node of foundNodes) { node.parent = null + } return missing } diff --git a/lib/commands/logout.js b/lib/commands/logout.js index 3c0bdc756..43a04bb57 100644 --- a/lib/commands/logout.js +++ b/lib/commands/logout.js @@ -37,15 +37,16 @@ class Logout extends BaseCommand { method: 'DELETE', ignoreBody: true, }) - } else if (auth.isBasicAuth) + } else if (auth.isBasicAuth) { log.verbose('logout', `clearing user credentials for ${reg}`) - else { + } else { const msg = `not logged in to ${reg}, so can't log out!` throw Object.assign(new Error(msg), { code: 'ENEEDAUTH' }) } - if (scope) + if (scope) { this.npm.config.delete(regRef, 'user') + } this.npm.config.clearCredentialsByURI(reg) diff --git a/lib/commands/ls.js b/lib/commands/ls.js index af7d44ab4..b8c1f0ef9 100644 --- a/lib/commands/ls.js +++ b/lib/commands/ls.js @@ -88,23 +88,26 @@ class LS extends ArboristWorkspaceCmd { legacyPeerDeps: false, path, }) - const tree = await this.initTree({arb, args, packageLockOnly }) + const tree = await this.initTree({ arb, args, packageLockOnly }) // filters by workspaces nodes when using -w <workspace-name> // We only have to filter the first layer of edges, so we don't // explore anything that isn't part of the selected workspace set. let wsNodes - if (this.workspaceNames && this.workspaceNames.length) + if (this.workspaceNames && this.workspaceNames.length) { wsNodes = arb.workspaceNodes(tree, this.workspaceNames) + } const filterBySelectedWorkspaces = edge => { if (!workspacesEnabled && edge.from.isProjectRoot && edge.to.isWorkspace - ) + ) { return false + } - if (!wsNodes || !wsNodes.length) + if (!wsNodes || !wsNodes.length) { return true + } if (edge.from.isProjectRoot) { return edge.to && @@ -176,8 +179,9 @@ class LS extends ArboristWorkspaceCmd { // loop through list of node problems to add them to global list if (node[_include]) { - for (const problem of node[_problems]) + for (const problem of node[_problems]) { problems.add(problem) + } } seenItems.add(item) @@ -200,8 +204,9 @@ class LS extends ArboristWorkspaceCmd { ) // if filtering items, should exit with error code on no results - if (result && !result[_include] && args.length) + if (result && !result[_include] && args.length) { process.exitCode = 1 + } if (rootError) { throw Object.assign( @@ -237,8 +242,9 @@ class LS extends ArboristWorkspaceCmd { module.exports = LS const isGitNode = (node) => { - if (!node.resolved) + if (!node.resolved) { return + } try { const { type } = npa(node.resolved) @@ -257,14 +263,17 @@ const isExtraneous = (node, { global }) => const getProblems = (node, { global }) => { const problems = new Set() - if (node[_missing] && !isOptional(node)) + if (node[_missing] && !isOptional(node)) { problems.add(`missing: ${node.pkgid}, required by ${node[_missing]}`) + } - if (node[_invalid]) + if (node[_invalid]) { problems.add(`invalid: ${node.pkgid} ${node.path}`) + } - if (isExtraneous(node, { global })) + if (isExtraneous(node, { global })) { problems.add(`extraneous: ${node.pkgid} ${node.path}`) + } return problems } @@ -297,10 +306,11 @@ const getHumanOutputItem = (node, { args, color, global, long }) => { // special formatting for top-level package name if (node.isRoot) { const hasNoPackageJson = !Object.keys(node.package).length - if (hasNoPackageJson || global) + if (hasNoPackageJson || global) { printable = path - else + } else { printable += `${long ? EOL : ' '}${path}` + } } const highlightDepName = @@ -347,19 +357,22 @@ const getHumanOutputItem = (node, { args, color, global, long }) => { const getJsonOutputItem = (node, { global, long }) => { const item = {} - if (node.version) + if (node.version) { item.version = node.version + } - if (node.resolved) + if (node.resolved) { item.resolved = node.resolved + } item[_name] = node.name // special formatting for top-level package name const hasPackageJson = node && node.package && Object.keys(node.package).length - if (node.isRoot && hasPackageJson) + if (node.isRoot && hasPackageJson) { item.name = node.package.name || node.name + } if (long && !node[_missing]) { item.name = item[_name] @@ -376,18 +389,21 @@ const getJsonOutputItem = (node, { global, long }) => { } // augment json output items with extra metadata - if (isExtraneous(node, { global })) + if (isExtraneous(node, { global })) { item.extraneous = true + } - if (node[_invalid]) + if (node[_invalid]) { item.invalid = node[_invalid] + } if (node[_missing] && !isOptional(node)) { item.required = node[_required] item.missing = true } - if (node[_include] && node[_problems] && node[_problems].size) + if (node[_include] && node[_problems] && node[_problems].size) { item.problems = [...node[_problems]] + } return augmentItemWithIncludeMetadata(node, item) } @@ -436,8 +452,9 @@ const mapEdgesToNodes = ({ seenPaths }) => (edge) => { // item would appear twice given that it's a children of an extraneous item, // so it's marked extraneous but it will ALSO show up in edgesOuts of // its parent so it ends up as two diff nodes if we don't track it - if (node.path) + if (node.path) { seenPaths.add(node.path) + } node[_required] = edge.spec || '*' node[_type] = edge.type @@ -515,20 +532,23 @@ const humanOutput = ({ color, result, seenItems, unicode }) => { // so that all its ancestors should be displayed) // here is where we put items in their expected place for archy output for (const item of seenItems) { - if (item[_include] && item[_parent]) + if (item[_include] && item[_parent]) { item[_parent].nodes.push(item) + } } - if (!result.nodes.length) + if (!result.nodes.length) { result.nodes = ['(empty)'] + } const archyOutput = archy(result, '', { unicode }) return color ? chalk.reset(archyOutput) : archyOutput } const jsonOutput = ({ path, problems, result, rootError, seenItems }) => { - if (problems.size) + if (problems.size) { result.problems = [...problems] + } if (rootError) { result.problems = [ @@ -546,8 +566,9 @@ const jsonOutput = ({ path, problems, result, rootError, seenItems }) => { // append current item to its parent item.dependencies obj in order // to provide a json object structure that represents the installed tree if (item[_include] && item[_parent]) { - if (!item[_parent].dependencies) + if (!item[_parent].dependencies) { item[_parent].dependencies = {} + } item[_parent].dependencies[item[_name]] = item } diff --git a/lib/commands/org.js b/lib/commands/org.js index 6d0b8cd50..18f73cb59 100644 --- a/lib/commands/org.js +++ b/lib/commands/org.js @@ -24,18 +24,14 @@ class Org extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ static get params () { - return [ - 'registry', - 'otp', - 'json', - 'parseable', - ] + return ['registry', 'otp', 'json', 'parseable'] } async completion (opts) { const argv = opts.conf.argv.remain - if (argv.length === 2) + if (argv.length === 2) { return ['set', 'rm', 'ls'] + } switch (argv[2]) { case 'ls': @@ -66,85 +62,109 @@ class Org extends BaseCommand { set (org, user, role, opts) { role = role || 'developer' - if (!org) + if (!org) { throw new Error('First argument `orgname` is required.') + } - if (!user) + if (!user) { throw new Error('Second argument `username` is required.') + } - if (!['owner', 'admin', 'developer'].find(x => x === role)) - throw new Error('Third argument `role` must be one of `owner`, `admin`, or `developer`, with `developer` being the default value if omitted.') + if (!['owner', 'admin', 'developer'].find(x => x === role)) { + throw new Error( + /* eslint-disable-next-line max-len */ + 'Third argument `role` must be one of `owner`, `admin`, or `developer`, with `developer` being the default value if omitted.' + ) + } return liborg.set(org, user, role, opts).then(memDeets => { - if (opts.json) + if (opts.json) { this.npm.output(JSON.stringify(memDeets, null, 2)) - else if (opts.parseable) { + } else if (opts.parseable) { this.npm.output(['org', 'orgsize', 'user', 'role'].join('\t')) - this.npm.output([ - memDeets.org.name, - memDeets.org.size, - memDeets.user, - memDeets.role, - ].join('\t')) - } else if (!opts.silent && opts.loglevel !== 'silent') - this.npm.output(`Added ${memDeets.user} as ${memDeets.role} to ${memDeets.org.name}. You now have ${memDeets.org.size} member${memDeets.org.size === 1 ? '' : 's'} in this org.`) + this.npm.output( + [memDeets.org.name, memDeets.org.size, memDeets.user, memDeets.role].join('\t') + ) + } else if (!opts.silent && opts.loglevel !== 'silent') { + this.npm.output( + `Added ${memDeets.user} as ${memDeets.role} to ${memDeets.org.name}. You now have ${ + memDeets.org.size + } member${memDeets.org.size === 1 ? '' : 's'} in this org.` + ) + } return memDeets }) } rm (org, user, opts) { - if (!org) + if (!org) { throw new Error('First argument `orgname` is required.') + } - if (!user) + if (!user) { throw new Error('Second argument `username` is required.') + } - return liborg.rm(org, user, opts).then(() => { - return liborg.ls(org, opts) - }).then(roster => { - user = user.replace(/^[~@]?/, '') - org = org.replace(/^[~@]?/, '') - const userCount = Object.keys(roster).length - if (opts.json) { - this.npm.output(JSON.stringify({ - user, - org, - userCount, - deleted: true, - })) - } else if (opts.parseable) { - this.npm.output(['user', 'org', 'userCount', 'deleted'].join('\t')) - this.npm.output([user, org, userCount, true].join('\t')) - } else if (!opts.silent && opts.loglevel !== 'silent') - this.npm.output(`Successfully removed ${user} from ${org}. You now have ${userCount} member${userCount === 1 ? '' : 's'} in this org.`) - }) + return liborg + .rm(org, user, opts) + .then(() => { + return liborg.ls(org, opts) + }) + .then(roster => { + user = user.replace(/^[~@]?/, '') + org = org.replace(/^[~@]?/, '') + const userCount = Object.keys(roster).length + if (opts.json) { + this.npm.output( + JSON.stringify({ + user, + org, + userCount, + deleted: true, + }) + ) + } else if (opts.parseable) { + this.npm.output(['user', 'org', 'userCount', 'deleted'].join('\t')) + this.npm.output([user, org, userCount, true].join('\t')) + } else if (!opts.silent && opts.loglevel !== 'silent') { + this.npm.output( + `Successfully removed ${user} from ${org}. You now have ${userCount} member${ + userCount === 1 ? '' : 's' + } in this org.` + ) + } + }) } ls (org, user, opts) { - if (!org) + if (!org) { throw new Error('First argument `orgname` is required.') + } return liborg.ls(org, opts).then(roster => { if (user) { const newRoster = {} - if (roster[user]) + if (roster[user]) { newRoster[user] = roster[user] + } roster = newRoster } - if (opts.json) + if (opts.json) { this.npm.output(JSON.stringify(roster, null, 2)) - else if (opts.parseable) { + } else if (opts.parseable) { this.npm.output(['user', 'role'].join('\t')) Object.keys(roster).forEach(user => { this.npm.output([user, roster[user]].join('\t')) }) } else if (!opts.silent && opts.loglevel !== 'silent') { const table = new Table({ head: ['user', 'role'] }) - Object.keys(roster).sort().forEach(user => { - table.push([user, roster[user]]) - }) + Object.keys(roster) + .sort() + .forEach(user => { + table.push([user, roster[user]]) + }) this.npm.output(table.toString()) } }) diff --git a/lib/commands/outdated.js b/lib/commands/outdated.js index 119316d3b..01047b4d3 100644 --- a/lib/commands/outdated.js +++ b/lib/commands/outdated.js @@ -91,19 +91,21 @@ class Outdated extends ArboristWorkspaceCmd { // sorts list alphabetically const outdated = this.list.sort((a, b) => localeCompare(a.name, b.name)) - if (outdated.length > 0) + if (outdated.length > 0) { process.exitCode = 1 + } // return if no outdated packages - if (outdated.length === 0 && !this.npm.config.get('json')) + if (outdated.length === 0 && !this.npm.config.get('json')) { return + } // display results - if (this.npm.config.get('json')) + if (this.npm.config.get('json')) { this.npm.output(this.makeJSON(outdated)) - else if (this.npm.config.get('parseable')) + } else if (this.npm.config.get('parseable')) { this.npm.output(this.makeParseable(outdated)) - else { + } else { const outList = outdated.map(x => this.makePretty(x)) const outHead = ['Package', 'Current', @@ -113,12 +115,14 @@ class Outdated extends ArboristWorkspaceCmd { 'Depended by', ] - if (this.npm.config.get('long')) + if (this.npm.config.get('long')) { outHead.push('Package Type', 'Homepage') + } const outTable = [outHead].concat(outList) - if (this.npm.color) + if (this.npm.color) { outTable[0] = outTable[0].map(heading => styles.underline(heading)) + } const tableOpts = { align: ['l', 'r', 'r', 'r', 'l'], @@ -145,18 +149,21 @@ class Outdated extends ArboristWorkspaceCmd { } getEdgesIn (node) { - for (const edge of node.edgesIn) + for (const edge of node.edgesIn) { this.trackEdge(edge) + } } getEdgesOut (node) { // TODO: normalize usage of edges and avoid looping through nodes here if (this.npm.config.get('global')) { - for (const child of node.children.values()) + for (const child of node.children.values()) { this.trackEdge(child) + } } else { - for (const edge of node.edgesOut.values()) + for (const edge of node.edgesOut.values()) { this.trackEdge(edge) + } } } @@ -167,15 +174,17 @@ class Outdated extends ArboristWorkspaceCmd { && this.filterSet.size > 0 && !this.filterSet.has(edge.from.target) - if (filteredOut) + if (filteredOut) { return + } this.edges.add(edge) } getWorkspacesEdges (node) { - if (this.npm.config.get('global')) + if (this.npm.config.get('global')) { return + } for (const edge of this.tree.edgesOut.values()) { const workspace = edge @@ -183,8 +192,9 @@ class Outdated extends ArboristWorkspaceCmd { && edge.to.target && edge.to.target.isWorkspace - if (workspace) + if (workspace) { this.getEdgesOut(edge.to.target) + } } } @@ -209,22 +219,25 @@ class Outdated extends ArboristWorkspaceCmd { : 'dependencies' for (const omitType of this.npm.config.get('omit')) { - if (node[omitType]) + if (node[omitType]) { return + } } // deps different from prod not currently // on disk are not included in the output - if (edge.error === 'MISSING' && type !== 'dependencies') + if (edge.error === 'MISSING' && type !== 'dependencies') { return + } try { const packument = await this.getPackument(spec) const expected = edge.spec // if it's not a range, version, or tag, skip it try { - if (!npa(`${edge.name}@${edge.spec}`).registry) + if (!npa(`${edge.name}@${edge.spec}`).registry) { return null + } } catch (err) { return null } @@ -259,14 +272,16 @@ class Outdated extends ArboristWorkspaceCmd { err.code === 'ETARGET' || err.code === 'E403' || err.code === 'E404') - ) + ) { throw err + } } } maybeWorkspaceName (node) { - if (!node.isWorkspace) + if (!node.isWorkspace) { return node.name + } const humanOutput = !this.npm.config.get('json') && !this.npm.config.get('parseable') @@ -331,8 +346,9 @@ class Outdated extends ArboristWorkspaceCmd { name + '@' + latest, dependent, ] - if (this.npm.config.get('long')) + if (this.npm.config.get('long')) { out.push(type, homepage) + } return out.join(':') }).join(os.EOL) diff --git a/lib/commands/owner.js b/lib/commands/owner.js index 5d28e2b75..4d1fe9b9f 100644 --- a/lib/commands/owner.js +++ b/lib/commands/owner.js @@ -36,30 +36,36 @@ class Owner extends BaseCommand { async completion (opts) { const argv = opts.conf.argv.remain - if (argv.length > 3) + if (argv.length > 3) { return [] + } - if (argv[1] !== 'owner') + if (argv[1] !== 'owner') { argv.unshift('owner') + } - if (argv.length === 2) + if (argv.length === 2) { return ['add', 'rm', 'ls'] + } // reaches registry in order to autocomplete rm if (argv[2] === 'rm') { - if (this.npm.config.get('global')) + if (this.npm.config.get('global')) { return [] + } const pkgName = await readLocalPkgName(this.npm.prefix) - if (!pkgName) + if (!pkgName) { return [] + } const spec = npa(pkgName) const data = await pacote.packument(spec, { ...this.npm.flatOptions, fullMetadata: true, }) - if (data && data.maintainers && data.maintainers.length) + if (data && data.maintainers && data.maintainers.length) { return data.maintainers.map(m => m.name) + } } return [] } @@ -82,12 +88,14 @@ class Owner extends BaseCommand { async ls (pkg, opts) { if (!pkg) { - if (this.npm.config.get('global')) + if (this.npm.config.get('global')) { throw this.usageError() + } const pkgName = await readLocalPkgName(this.npm.prefix) - if (!pkgName) + if (!pkgName) { throw this.usageError() + } pkg = pkgName } @@ -97,10 +105,11 @@ class Owner extends BaseCommand { try { const packumentOpts = { ...opts, fullMetadata: true } const { maintainers } = await pacote.packument(spec, packumentOpts) - if (!maintainers || !maintainers.length) + if (!maintainers || !maintainers.length) { this.npm.output('no admin found') - else + } else { this.npm.output(maintainers.map(o => `${o.name} <${o.email}>`).join('\n')) + } return maintainers } catch (err) { @@ -110,15 +119,18 @@ class Owner extends BaseCommand { } async add (user, pkg, opts) { - if (!user) + if (!user) { throw this.usageError() + } if (!pkg) { - if (this.npm.config.get('global')) + if (this.npm.config.get('global')) { throw this.usageError() + } const pkgName = await readLocalPkgName(this.npm.prefix) - if (!pkgName) + if (!pkgName) { throw this.usageError() + } pkg = pkgName } @@ -130,15 +142,18 @@ class Owner extends BaseCommand { } async rm (user, pkg, opts) { - if (!user) + if (!user) { throw this.usageError() + } if (!pkg) { - if (this.npm.config.get('global')) + if (this.npm.config.get('global')) { throw this.usageError() + } const pkgName = await readLocalPkgName(this.npm.prefix) - if (!pkgName) + if (!pkgName) { throw this.usageError() + } pkg = pkgName } @@ -178,8 +193,9 @@ class Owner extends BaseCommand { const before = data.maintainers ? data.maintainers.length : 0 const m = validation(u, data.maintainers) - if (!m) - return // invalid owners + if (!m) { + return + } // invalid owners const body = { _id: data._id, @@ -197,10 +213,11 @@ class Owner extends BaseCommand { }) if (!res.error) { - if (m.length < before) + if (m.length < before) { this.npm.output(`- ${user} (${spec.name})`) - else + } else { this.npm.output(`+ ${user} (${spec.name})`) + } } else { throw Object.assign( new Error('Failed to update package: ' + JSON.stringify(res)), diff --git a/lib/commands/pack.js b/lib/commands/pack.js index 013e88b44..27682878c 100644 --- a/lib/commands/pack.js +++ b/lib/commands/pack.js @@ -40,8 +40,9 @@ class Pack extends BaseCommand { } async exec (args) { - if (args.length === 0) + if (args.length === 0) { args = ['.'] + } const unicode = this.npm.config.get('unicode') const dryRun = this.npm.config.get('dry-run') @@ -53,8 +54,9 @@ class Pack extends BaseCommand { for (const arg of args) { const spec = npa(arg) const manifest = await pacote.manifest(spec, this.npm.flatOptions) - if (!manifest._id) + if (!manifest._id) { throw new Error('Invalid package, must have name and version') + } const filename = `${manifest.name}-${manifest.version}.tgz` .replace(/^@/, '').replace(/\//, '-') @@ -69,8 +71,9 @@ class Pack extends BaseCommand { const pkgContents = await getContents(manifest, tarballData) const tarballFilename = path.resolve(this.npm.config.get('pack-destination'), filename) - if (!dryRun) + if (!dryRun) { await writeFile(tarballFilename, tarballData) + } tarballs.push(pkgContents) } diff --git a/lib/commands/ping.js b/lib/commands/ping.js index d8ad1dc2a..0025573d6 100644 --- a/lib/commands/ping.js +++ b/lib/commands/ping.js @@ -30,8 +30,9 @@ class Ping extends BaseCommand { time, details, }, null, 2)) - } else if (Object.keys(details).length) + } else if (Object.keys(details).length) { log.notice('PONG', `${JSON.stringify(details, null, 2)}`) + } } } module.exports = Ping diff --git a/lib/commands/pkg.js b/lib/commands/pkg.js index 1fa2c3bc5..53e6431ee 100644 --- a/lib/commands/pkg.js +++ b/lib/commands/pkg.js @@ -32,10 +32,11 @@ class Pkg extends BaseCommand { } async exec (args, { prefix } = {}) { - if (!prefix) + if (!prefix) { this.prefix = this.npm.localPrefix - else + } else { this.prefix = prefix + } if (this.npm.config.get('global')) { throw Object.assign( @@ -81,15 +82,17 @@ class Pkg extends BaseCommand { // in case there's only a single result from the query // just prints that one element to stdout - if (Object.keys(result).length === 1) + if (Object.keys(result).length === 1) { result = result[args] + } } // only outputs if not running with workspaces config, // in case you're retrieving info for workspaces the pkgWorkspaces // will handle the output to make sure it get keyed by ws name - if (!this.workspaces) + if (!this.workspaces) { this.npm.output(JSON.stringify(result, null, 2)) + } return result } @@ -98,8 +101,9 @@ class Pkg extends BaseCommand { const setError = () => this.usageError('npm pkg set expects a key=value pair of args.') - if (!args.length) + if (!args.length) { throw setError() + } const force = this.npm.config.get('force') const json = this.npm.config.get('json') @@ -108,8 +112,9 @@ class Pkg extends BaseCommand { for (const arg of args) { const [key, ...rest] = arg.split('=') const value = rest.join('=') - if (!key || !value) + if (!key || !value) { throw setError() + } q.set(key, json ? JSON.parse(value) : value, { force }) } @@ -122,14 +127,16 @@ class Pkg extends BaseCommand { const setError = () => this.usageError('npm pkg delete expects key args.') - if (!args.length) + if (!args.length) { throw setError() + } const pkgJson = await PackageJson.load(this.prefix) const q = new Queryable(pkgJson.content) for (const key of args) { - if (!key) + if (!key) { throw setError() + } q.delete(key) } diff --git a/lib/commands/profile.js b/lib/commands/profile.js index abfe5edd7..72e4bb849 100644 --- a/lib/commands/profile.js +++ b/lib/commands/profile.js @@ -70,8 +70,9 @@ class Profile extends BaseCommand { async completion (opts) { var argv = opts.conf.argv.remain - if (!argv[2]) + if (!argv[2]) { return ['enable-2fa', 'disable-2fa', 'get', 'set'] + } switch (argv[2]) { case 'enable-2fa': @@ -89,8 +90,9 @@ class Profile extends BaseCommand { } async exec (args) { - if (args.length === 0) + if (args.length === 0) { throw this.usageError() + } log.gauge.show('profile') @@ -122,8 +124,9 @@ class Profile extends BaseCommand { npmProfile.get(this.npm.flatOptions) ) - if (!info.cidr_whitelist) + if (!info.cidr_whitelist) { delete info.cidr_whitelist + } if (this.npm.config.get('json')) { this.npm.output(JSON.stringify(info, null, 2)) @@ -132,21 +135,24 @@ class Profile extends BaseCommand { // clean up and format key/values for output const cleaned = {} - for (const key of knownProfileKeys) + for (const key of knownProfileKeys) { cleaned[key] = info[key] || '' + } const unknownProfileKeys = Object.keys(info).filter((k) => !(k in cleaned)) - for (const key of unknownProfileKeys) + for (const key of unknownProfileKeys) { cleaned[key] = info[key] || '' + } delete cleaned.tfa delete cleaned.email_verified cleaned.email += info.email_verified ? ' (verified)' : '(unverified)' - if (info.tfa && !info.tfa.pending) + if (info.tfa && !info.tfa.pending) { cleaned[tfa] = info.tfa.mode - else + } else { cleaned[tfa] = 'disabled' + } if (args.length) { const values = args // comma or space separated @@ -159,15 +165,17 @@ class Profile extends BaseCommand { } else { if (this.npm.config.get('parseable')) { for (const key of Object.keys(info)) { - if (key === 'tfa') + if (key === 'tfa') { this.npm.output(`${key}\t${cleaned[tfa]}`) - else + } else { this.npm.output(`${key}\t${info[key]}`) + } } } else { const table = new Table() - for (const key of Object.keys(cleaned)) + for (const key of Object.keys(cleaned)) { table.push({ [ansistyles.bright(key)]: cleaned[key] }) + } this.npm.output(table.toString()) } @@ -192,8 +200,9 @@ class Profile extends BaseCommand { return newpassword } - if (prop !== 'password' && value === null) + if (prop !== 'password' && value === null) { throw new Error('npm profile set <prop> <value>') + } if (prop === 'password' && value !== null) { throw new Error( @@ -217,26 +226,29 @@ class Profile extends BaseCommand { const user = await pulseTillDone.withPromise(npmProfile.get(conf)) const newUser = {} - for (const key of writableProfileKeys) + for (const key of writableProfileKeys) { newUser[key] = user[key] + } newUser[prop] = value const result = await otplease(conf, conf => npmProfile.set(newUser, conf)) - if (this.npm.config.get('json')) + if (this.npm.config.get('json')) { this.npm.output(JSON.stringify({ [prop]: result[prop] }, null, 2)) - else if (this.npm.config.get('parseable')) + } else if (this.npm.config.get('parseable')) { this.npm.output(prop + '\t' + result[prop]) - else if (result[prop] != null) + } else if (result[prop] != null) { this.npm.output('Set', prop, 'to', result[prop]) - else + } else { this.npm.output('Set', prop) + } } async enable2fa (args) { - if (args.length > 1) + if (args.length > 1) { throw new Error('npm profile enable-2fa [auth-and-writes|auth-only]') + } const mode = args[0] || 'auth-and-writes' if (mode !== 'auth-only' && mode !== 'auth-and-writes') { @@ -267,11 +279,11 @@ class Profile extends BaseCommand { const creds = this.npm.config.getCredentialsByURI(this.npm.config.get('registry')) const auth = {} - if (creds.token) + if (creds.token) { auth.token = creds.token - else if (creds.username) + } else if (creds.username) { auth.basic = { username: creds.username, password: creds.password } - else if (creds.auth) { + } else if (creds.auth) { const basic = Buffer.from(creds.auth, 'base64').toString().split(':', 2) auth.basic = { username: basic[0], password: basic[1] } } @@ -370,8 +382,9 @@ class Profile extends BaseCommand { 'if you lose your authentication device.' ) - for (const tfaCode of result.tfa) + for (const tfaCode of result.tfa) { this.npm.output('\t' + tfaCode) + } } async disable2fa (args) { @@ -396,12 +409,13 @@ class Profile extends BaseCommand { tfa: { password: password, mode: 'disable' }, }, conf)) - if (this.npm.config.get('json')) + if (this.npm.config.get('json')) { this.npm.output(JSON.stringify({ tfa: false }, null, 2)) - else if (this.npm.config.get('parseable')) + } else if (this.npm.config.get('parseable')) { this.npm.output('tfa\tfalse') - else + } else { this.npm.output('Two factor authentication disabled.') + } } } module.exports = Profile diff --git a/lib/commands/publish.js b/lib/commands/publish.js index 3bc309c12..efa148565 100644 --- a/lib/commands/publish.js +++ b/lib/commands/publish.js @@ -56,10 +56,12 @@ class Publish extends BaseCommand { } async exec (args) { - if (args.length === 0) + if (args.length === 0) { args = ['.'] - if (args.length !== 1) + } + if (args.length !== 1) { throw this.usageError() + } log.verbose('publish', replaceInfo(args)) @@ -70,8 +72,9 @@ class Publish extends BaseCommand { const ignoreScripts = this.npm.config.get('ignore-scripts') const silent = log.level === 'silent' - if (semver.validRange(defaultTag)) + if (semver.validRange(defaultTag)) { throw new Error('Tag name must not be a valid SemVer range: ' + defaultTag.trim()) + } const opts = { ...this.npm.flatOptions } @@ -80,8 +83,9 @@ class Publish extends BaseCommand { const spec = npa(args[0]) let manifest = await this.getManifest(spec, opts) - if (manifest.publishConfig) + if (manifest.publishConfig) { flatten(manifest.publishConfig, opts) + } // only run scripts for directory type publishes if (spec.type === 'directory' && !ignoreScripts) { @@ -101,13 +105,15 @@ class Publish extends BaseCommand { // so that we send the latest and greatest thing to the registry // note that publishConfig might have changed as well! manifest = await this.getManifest(spec, opts) - if (manifest.publishConfig) + if (manifest.publishConfig) { flatten(manifest.publishConfig, opts) + } // note that logTar calls npmlog.notice(), so if we ARE in silent mode, // this will do nothing, but we still want it in the debuglog if it fails. - if (!json) + if (!json) { logTar(pkgContents, { log, unicode }) + } if (!dryRun) { const resolved = npa.resolve(manifest.name, manifest.version) @@ -140,10 +146,11 @@ class Publish extends BaseCommand { } if (!this.suppressOutput) { - if (!silent && json) + if (!silent && json) { this.npm.output(JSON.stringify(pkgContents, null, 2)) - else if (!silent) + } else if (!silent) { this.npm.output(`+ ${pkgContents.id}`) + } } return pkgContents @@ -180,21 +187,24 @@ class Publish extends BaseCommand { } // This needs to be in-line w/ the rest of the output that non-JSON // publish generates - if (!silent && !json) + if (!silent && !json) { this.npm.output(`+ ${pkgContents.id}`) - else + } else { results[name] = pkgContents + } } - if (!silent && json) + if (!silent && json) { this.npm.output(JSON.stringify(results, null, 2)) + } } // if it's a directory, read it from the file system // otherwise, get the full metadata from whatever it is getManifest (spec, opts) { - if (spec.type === 'directory') + if (spec.type === 'directory') { return readJson(`${spec.fetchSpec}/package.json`) + } return pacote.manifest(spec, { ...opts, fullMetadata: true }) } } diff --git a/lib/commands/rebuild.js b/lib/commands/rebuild.js index 3b9211e2e..d95a865b4 100644 --- a/lib/commands/rebuild.js +++ b/lib/commands/rebuild.js @@ -51,33 +51,39 @@ class Rebuild extends ArboristWorkspaceCmd { const tree = await arb.loadActual() const specs = args.map(arg => { const spec = npa(arg) - if (spec.type === 'tag' && spec.rawSpec === '') + if (spec.type === 'tag' && spec.rawSpec === '') { return spec + } - if (spec.type !== 'range' && spec.type !== 'version' && spec.type !== 'directory') + if (spec.type !== 'range' && spec.type !== 'version' && spec.type !== 'directory') { throw new Error('`npm rebuild` only supports SemVer version/range specifiers') + } return spec }) const nodes = tree.inventory.filter(node => this.isNode(specs, node)) await arb.rebuild({ nodes }) - } else + } else { await arb.rebuild() + } this.npm.output('rebuilt dependencies successfully') } isNode (specs, node) { return specs.some(spec => { - if (spec.type === 'directory') + if (spec.type === 'directory') { return node.path === spec.fetchSpec + } - if (spec.name !== node.name) + if (spec.name !== node.name) { return false + } - if (spec.rawSpec === '' || spec.rawSpec === '*') + if (spec.rawSpec === '' || spec.rawSpec === '*') { return true + } const { version } = node.package // TODO: add tests for a package with missing version diff --git a/lib/commands/repo.js b/lib/commands/repo.js index 372940512..f87309896 100644 --- a/lib/commands/repo.js +++ b/lib/commands/repo.js @@ -28,8 +28,9 @@ class Repo extends BaseCommand { } async exec (args) { - if (!args || !args.length) + if (!args || !args.length) { args = ['.'] + } await Promise.all(args.map(pkg => this.get(pkg))) } @@ -86,8 +87,9 @@ const unknownHostedUrl = url => { } = new URL(url) /* istanbul ignore next - URL ctor should prevent this */ - if (!protocol || !hostname) + if (!protocol || !hostname) { return null + } const proto = /(git\+)http:$/.test(protocol) ? 'http:' : 'https:' const path = pathname.replace(/\.git$/, '') diff --git a/lib/commands/run-script.js b/lib/commands/run-script.js index 34e96257c..832e166a6 100644 --- a/lib/commands/run-script.js +++ b/lib/commands/run-script.js @@ -66,17 +66,19 @@ class RunScript extends BaseCommand { } async exec (args) { - if (args.length) + if (args.length) { return this.run(args) - else + } else { return this.list(args) + } } async execWorkspaces (args, filters) { - if (args.length) + if (args.length) { return this.runWorkspaces(args, filters) - else + } else { return this.listWorkspaces(args, filters) + } } async run ([event, ...args], { path = this.npm.localPrefix, pkg } = {}) { @@ -87,32 +89,38 @@ class RunScript extends BaseCommand { pkg = pkg || (await rpj(`${path}/package.json`)) const { scripts = {} } = pkg - if (event === 'restart' && !scripts.restart) + if (event === 'restart' && !scripts.restart) { scripts.restart = 'npm stop --if-present && npm start' - else if (event === 'env' && !scripts.env) + } else if (event === 'env' && !scripts.env) { scripts.env = isWindowsShell ? 'SET' : 'env' + } pkg.scripts = scripts if ( !Object.prototype.hasOwnProperty.call(scripts, event) && - !(event === 'start' && await isServerPackage(path)) + !(event === 'start' && (await isServerPackage(path))) ) { - if (this.npm.config.get('if-present')) + if (this.npm.config.get('if-present')) { return + } const suggestions = await didYouMean(this.npm, path, event) - throw new Error(`Missing script: "${event}"${suggestions}\n\nTo see a list of scripts, run:\n npm run`) + throw new Error( + `Missing script: "${event}"${suggestions}\n\nTo see a list of scripts, run:\n npm run` + ) } // positional args only added to the main event, not pre/post const events = [[event, args]] if (!this.npm.config.get('ignore-scripts')) { - if (scripts[`pre${event}`]) + if (scripts[`pre${event}`]) { events.unshift([`pre${event}`, []]) + } - if (scripts[`post${event}`]) + if (scripts[`post${event}`]) { events.push([`post${event}`, []]) + } } const opts = { @@ -140,12 +148,14 @@ class RunScript extends BaseCommand { const pkgid = _id || name const color = this.npm.color - if (!scripts) + if (!scripts) { return [] + } const allScripts = Object.keys(scripts) - if (log.level === 'silent') + if (log.level === 'silent') { return allScripts + } if (this.npm.config.get('json')) { this.npm.output(JSON.stringify(scripts, null, 2)) @@ -153,8 +163,9 @@ class RunScript extends BaseCommand { } if (this.npm.config.get('parseable')) { - for (const [script, cmd] of Object.entries(scripts)) + for (const [script, cmd] of Object.entries(scripts)) { this.npm.output(`${script}:${cmd}`) + } return allScripts } @@ -170,24 +181,30 @@ class RunScript extends BaseCommand { const colorize = color ? chalk : nocolor if (cmds.length) { - this.npm.output(`${ - colorize.reset(colorize.bold('Lifecycle scripts'))} included in ${ - colorize.green(pkgid)}:`) + this.npm.output( + `${colorize.reset(colorize.bold('Lifecycle scripts'))} included in ${colorize.green( + pkgid + )}:` + ) } - for (const script of cmds) + for (const script of cmds) { this.npm.output(prefix + script + indent + colorize.dim(scripts[script])) + } if (!cmds.length && runScripts.length) { - this.npm.output(`${ - colorize.bold('Scripts') - } available in ${colorize.green(pkgid)} via \`${ - colorize.blue('npm run-script')}\`:`) - } else if (runScripts.length) + this.npm.output( + `${colorize.bold('Scripts')} available in ${colorize.green(pkgid)} via \`${colorize.blue( + 'npm run-script' + )}\`:` + ) + } else if (runScripts.length) { this.npm.output(`\navailable via \`${colorize.blue('npm run-script')}\`:`) + } - for (const script of runScripts) + for (const script of runScripts) { this.npm.output(prefix + script + indent + colorize.dim(scripts[script])) + } this.npm.output('') return allScripts @@ -212,8 +229,9 @@ class RunScript extends BaseCommand { // avoids exiting with error code in case there's scripts missing // in some workspaces since other scripts might have succeeded - if (!scriptMissing) + if (!scriptMissing) { process.exitCode = 1 + } return scriptMissing }) @@ -221,15 +239,17 @@ class RunScript extends BaseCommand { } // in case **all** tests are missing, then it should exit with error code - if (res.every(Boolean)) + if (res.every(Boolean)) { throw new Error(`Missing script: ${args[0]}`) + } } async listWorkspaces (args, filters) { await this.setWorkspaces(filters) - if (log.level === 'silent') + if (log.level === 'silent') { return + } if (this.npm.config.get('json')) { const res = {} @@ -244,14 +264,16 @@ class RunScript extends BaseCommand { if (this.npm.config.get('parseable')) { for (const workspacePath of this.workspacePaths) { const { scripts, name } = await rpj(`${workspacePath}/package.json`) - for (const [script, cmd] of Object.entries(scripts || {})) + for (const [script, cmd] of Object.entries(scripts || {})) { this.npm.output(`${name}:${script}:${cmd}`) + } } return } - for (const workspacePath of this.workspacePaths) + for (const workspacePath of this.workspacePaths) { await this.list(args, workspacePath) + } } } diff --git a/lib/commands/search.js b/lib/commands/search.js index e60f41afb..6c5c995c3 100644 --- a/lib/commands/search.js +++ b/lib/commands/search.js @@ -14,10 +14,11 @@ function prepareIncludes (args) { function prepareExcludes (searchexclude) { var exclude - if (typeof searchexclude === 'string') + if (typeof searchexclude === 'string') { exclude = searchexclude.split(/\s+/) - else + } else { exclude = [] + } return exclude .map(s => s.toLowerCase()) @@ -66,16 +67,18 @@ class Search extends BaseCommand { exclude: prepareExcludes(this.npm.flatOptions.search.exclude), } - if (opts.include.length === 0) + if (opts.include.length === 0) { throw new Error('search must be called with arguments') + } // Used later to figure out whether we had any packages go out let anyOutput = false class FilterStream extends Minipass { write (pkg) { - if (packageFilter(pkg, opts.include, opts.exclude)) + if (packageFilter(pkg, opts.include, opts.exclude)) { super.write(pkg) + } } } @@ -96,14 +99,16 @@ class Search extends BaseCommand { ) p.on('data', chunk => { - if (!anyOutput) + if (!anyOutput) { anyOutput = true + } this.npm.output(chunk.toString('utf8')) }) await p.promise() - if (!anyOutput && !this.npm.config.get('json') && !this.npm.config.get('parseable')) + if (!anyOutput && !this.npm.config.get('json') && !this.npm.config.get('parseable')) { this.npm.output('No matches found for ' + (args.map(JSON.stringify).join(' '))) + } log.silly('search', 'search completed') log.clearProgress() diff --git a/lib/commands/set-script.js b/lib/commands/set-script.js index 00f9b5d5b..d99487e67 100644 --- a/lib/commands/set-script.js +++ b/lib/commands/set-script.js @@ -36,19 +36,22 @@ class SetScript extends BaseCommand { } validate (args) { - if (process.env.npm_lifecycle_event === 'postinstall') + if (process.env.npm_lifecycle_event === 'postinstall') { throw new Error('Scripts can’t set from the postinstall script') + } // Parse arguments - if (args.length !== 2) + if (args.length !== 2) { throw new Error(`Expected 2 arguments: got ${args.length}`) + } } async exec (args) { this.validate(args) const warn = await this.doSetScript(this.npm.localPrefix, args[0], args[1]) - if (warn) + if (warn) { log.warn('set-script', `Script "${args[0]}" was overwritten`) + } } async execWorkspaces (args, filters) { @@ -86,8 +89,9 @@ class SetScript extends BaseCommand { && scripts[name] && scripts[name] !== value - if (overwriting) + if (overwriting) { warn = true + } pkgJson.update({ scripts: { diff --git a/lib/commands/set.js b/lib/commands/set.js index cdaabc04a..b38623c60 100644 --- a/lib/commands/set.js +++ b/lib/commands/set.js @@ -21,8 +21,9 @@ class Set extends BaseCommand { } async exec (args) { - if (!args.length) + if (!args.length) { throw this.usageError() + } return this.npm.exec('config', ['set'].concat(args)) } } diff --git a/lib/commands/shrinkwrap.js b/lib/commands/shrinkwrap.js index 42489a27f..2d57e7b91 100644 --- a/lib/commands/shrinkwrap.js +++ b/lib/commands/shrinkwrap.js @@ -57,19 +57,22 @@ class Shrinkwrap extends BaseCommand { if (newFile) { let message = 'created a lockfile as npm-shrinkwrap.json' - if (updatedVersion) + if (updatedVersion) { message += ` with version ${updatedVersion}` + } log.notice('', message) } else if (notSW) { await unlink(oldFilename) let message = 'package-lock.json has been renamed to npm-shrinkwrap.json' - if (updatedVersion) + if (updatedVersion) { message += ` and updated to version ${updatedVersion}` + } log.notice('', message) - } else if (updatedVersion) + } else if (updatedVersion) { log.notice('', `npm-shrinkwrap.json updated to version ${updatedVersion}`) - else + } else { log.notice('', 'npm-shrinkwrap.json up to date') + } } } module.exports = Shrinkwrap diff --git a/lib/commands/star.js b/lib/commands/star.js index 36003a020..ce1564ff1 100644 --- a/lib/commands/star.js +++ b/lib/commands/star.js @@ -29,8 +29,9 @@ class Star extends BaseCommand { } async exec (args) { - if (!args.length) + if (!args.length) { throw this.usageError() + } // if we're unstarring, then show an empty star image // otherwise, show the full star image @@ -52,8 +53,9 @@ class Star extends BaseCommand { }), ]) - if (!username) + if (!username) { throw new Error('You need to be logged in!') + } const body = { _id: fullData._id, diff --git a/lib/commands/stars.js b/lib/commands/stars.js index d430be2ce..61fd45f84 100644 --- a/lib/commands/stars.js +++ b/lib/commands/stars.js @@ -29,21 +29,25 @@ class Stars extends BaseCommand { async exec ([user]) { try { - if (!user) + if (!user) { user = await getIdentity(this.npm, this.npm.flatOptions) + } const { rows } = await fetch.json('/-/_view/starredByUser', { ...this.npm.flatOptions, query: { key: `"${user}"` }, }) - if (rows.length === 0) + if (rows.length === 0) { log.warn('stars', 'user has not starred any packages') + } - for (const row of rows) + for (const row of rows) { this.npm.output(row.value) + } } catch (err) { - if (err.code === 'ENEEDAUTH') + if (err.code === 'ENEEDAUTH') { log.warn('stars', 'auth is required to look up your username') + } throw err } } diff --git a/lib/commands/team.js b/lib/commands/team.js index b337a7536..04b1b708f 100644 --- a/lib/commands/team.js +++ b/lib/commands/team.js @@ -39,11 +39,13 @@ class Team extends BaseCommand { const { conf: { argv: { remain: argv } } } = opts const subcommands = ['create', 'destroy', 'add', 'rm', 'ls'] - if (argv.length === 2) + if (argv.length === 2) { return subcommands + } - if (subcommands.includes(argv[2])) + if (subcommands.includes(argv[2])) { return [] + } throw new Error(argv[2] + ' not recognized') } @@ -62,10 +64,11 @@ class Team extends BaseCommand { case 'rm': return this.rm(entity, user, opts) case 'ls': { const match = entity.match(/[^:]+:.+/) - if (match) + if (match) { return this.listUsers(entity, opts) - else + } else { return this.listTeams(entity, opts) + } } default: throw this.usageError() @@ -80,10 +83,11 @@ class Team extends BaseCommand { created: true, team: entity, })) - } else if (opts.parseable) + } else if (opts.parseable) { this.npm.output(`${entity}\tcreated`) - else if (!opts.silent && opts.loglevel !== 'silent') + } else if (!opts.silent && opts.loglevel !== 'silent') { this.npm.output(`+@${entity}`) + } } async destroy (entity, opts) { @@ -93,10 +97,11 @@ class Team extends BaseCommand { deleted: true, team: entity, })) - } else if (opts.parseable) + } else if (opts.parseable) { this.npm.output(`${entity}\tdeleted`) - else if (!opts.silent && opts.loglevel !== 'silent') + } else if (!opts.silent && opts.loglevel !== 'silent') { this.npm.output(`-@${entity}`) + } } async add (entity, user, opts) { @@ -107,10 +112,11 @@ class Team extends BaseCommand { team: entity, user, })) - } else if (opts.parseable) + } else if (opts.parseable) { this.npm.output(`${user}\t${entity}\tadded`) - else if (!opts.silent && opts.loglevel !== 'silent') + } else if (!opts.silent && opts.loglevel !== 'silent') { this.npm.output(`${user} added to @${entity}`) + } } async rm (entity, user, opts) { @@ -121,19 +127,20 @@ class Team extends BaseCommand { team: entity, user, })) - } else if (opts.parseable) + } else if (opts.parseable) { this.npm.output(`${user}\t${entity}\tremoved`) - else if (!opts.silent && opts.loglevel !== 'silent') + } else if (!opts.silent && opts.loglevel !== 'silent') { this.npm.output(`${user} removed from @${entity}`) + } } async listUsers (entity, opts) { const users = (await libteam.lsUsers(entity, opts)).sort() - if (opts.json) + if (opts.json) { this.npm.output(JSON.stringify(users, null, 2)) - else if (opts.parseable) + } else if (opts.parseable) { this.npm.output(users.join('\n')) - else if (!opts.silent && opts.loglevel !== 'silent') { + } else if (!opts.silent && opts.loglevel !== 'silent') { const plural = users.length === 1 ? '' : 's' const more = users.length === 0 ? '' : ':\n' this.npm.output(`\n@${entity} has ${users.length} user${plural}${more}`) @@ -143,11 +150,11 @@ class Team extends BaseCommand { async listTeams (entity, opts) { const teams = (await libteam.lsTeams(entity, opts)).sort() - if (opts.json) + if (opts.json) { this.npm.output(JSON.stringify(teams, null, 2)) - else if (opts.parseable) + } else if (opts.parseable) { this.npm.output(teams.join('\n')) - else if (!opts.silent && opts.loglevel !== 'silent') { + } else if (!opts.silent && opts.loglevel !== 'silent') { const plural = teams.length === 1 ? '' : 's' const more = teams.length === 0 ? '' : ':\n' this.npm.output(`\n@${entity} has ${teams.length} team${plural}${more}`) diff --git a/lib/commands/token.js b/lib/commands/token.js index f7b92ea1d..499ea3d02 100644 --- a/lib/commands/token.js +++ b/lib/commands/token.js @@ -21,39 +21,33 @@ class Token extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ static get usage () { - return [ - 'list', - 'revoke <id|token>', - 'create [--read-only] [--cidr=list]', - ] + return ['list', 'revoke <id|token>', 'create [--read-only] [--cidr=list]'] } /* istanbul ignore next - see test/lib/load-all-commands.js */ static get params () { - return [ - 'read-only', - 'cidr', - 'registry', - 'otp', - ] + return ['read-only', 'cidr', 'registry', 'otp'] } async completion (opts) { const argv = opts.conf.argv.remain const subcommands = ['list', 'revoke', 'create'] - if (argv.length === 2) + if (argv.length === 2) { return subcommands + } - if (subcommands.includes(argv[2])) + if (subcommands.includes(argv[2])) { return [] + } throw new Error(argv[2] + ' not recognized') } async exec (args, cb) { log.gauge.show('token') - if (args.length === 0) + if (args.length === 0) { return this.list() + } switch (args[0]) { case 'list': case 'ls': @@ -79,25 +73,26 @@ class Token extends BaseCommand { return } else if (conf.parseable) { this.npm.output(['key', 'token', 'created', 'readonly', 'CIDR whitelist'].join('\t')) - tokens.forEach((token) => { - this.npm.output([ - token.key, - token.token, - token.created, - token.readonly ? 'true' : 'false', - token.cidr_whitelist ? token.cidr_whitelist.join(',') : '', - ].join('\t')) + tokens.forEach(token => { + this.npm.output( + [ + token.key, + token.token, + token.created, + token.readonly ? 'true' : 'false', + token.cidr_whitelist ? token.cidr_whitelist.join(',') : '', + ].join('\t') + ) }) return } this.generateTokenIds(tokens, 6) - const idWidth = tokens.reduce((acc, token) => - Math.max(acc, token.id.length), 0) + const idWidth = tokens.reduce((acc, token) => Math.max(acc, token.id.length), 0) const table = new Table({ head: ['id', 'token', 'created', 'readonly', 'CIDR whitelist'], colWidths: [Math.max(idWidth, 2) + 2, 9, 12, 10], }) - tokens.forEach((token) => { + tokens.forEach(token => { table.push([ token.id, token.token + '…', @@ -110,39 +105,47 @@ class Token extends BaseCommand { } async rm (args) { - if (args.length === 0) + if (args.length === 0) { throw this.usageError('`<tokenKey>` argument is required.') + } 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)) - args.forEach((id) => { - const matches = tokens.filter((token) => token.key.indexOf(id) === 0) - if (matches.length === 1) + args.forEach(id => { + const matches = tokens.filter(token => token.key.indexOf(id) === 0) + if (matches.length === 1) { toRemove.push(matches[0].key) - else if (matches.length > 1) - throw new Error(`Token ID "${id}" was ambiguous, a new token may have been created since you last ran \`npm token list\`.`) - else { + } else if (matches.length > 1) { + throw new Error( + /* eslint-disable-next-line max-len */ + `Token ID "${id}" was ambiguous, a new token may have been created since you last ran \`npm token list\`.` + ) + } else { const tokenMatches = tokens.some(t => id.indexOf(t.token) === 0) - if (!tokenMatches) + if (!tokenMatches) { throw new Error(`Unknown token id or value "${id}".`) + } toRemove.push(id) } }) - await Promise.all(toRemove.map(key => { - return otplease(conf, conf => { - return profile.removeToken(key, conf) + await Promise.all( + toRemove.map(key => { + return otplease(conf, conf => { + return profile.removeToken(key, conf) + }) }) - })) - if (conf.json) + ) + if (conf.json) { this.npm.output(JSON.stringify(toRemove)) - else if (conf.parseable) + } else if (conf.parseable) { this.npm.output(toRemove.join('\t')) - else + } else { this.npm.output('Removed ' + toRemove.length + ' token' + (toRemove.length !== 1 ? 's' : '')) + } } async create (args) { @@ -150,34 +153,40 @@ class Token extends BaseCommand { const cidr = conf.cidr const readonly = conf.readOnly - return readUserInfo.password().then((password) => { - const validCIDR = this.validateCIDRList(cidr) - log.info('token', 'creating') - return pulseTillDone.withPromise(otplease(conf, conf => { - return profile.createToken(password, readonly, validCIDR, conf) - })) - }).then((result) => { - delete result.key - delete result.updated - if (conf.json) - this.npm.output(JSON.stringify(result)) - else if (conf.parseable) - Object.keys(result).forEach((k) => this.npm.output(k + '\t' + result[k])) - else { - const table = new Table() - for (const k of Object.keys(result)) - table.push({ [ansistyles.bright(k)]: String(result[k]) }) - this.npm.output(table.toString()) - } - }) + return readUserInfo + .password() + .then(password => { + const validCIDR = this.validateCIDRList(cidr) + log.info('token', 'creating') + return pulseTillDone.withPromise( + otplease(conf, conf => { + return profile.createToken(password, readonly, validCIDR, conf) + }) + ) + }) + .then(result => { + delete result.key + delete result.updated + if (conf.json) { + this.npm.output(JSON.stringify(result)) + } else if (conf.parseable) { + Object.keys(result).forEach(k => this.npm.output(k + '\t' + result[k])) + } else { + const table = new Table() + for (const k of Object.keys(result)) { + table.push({ [ansistyles.bright(k)]: String(result[k]) }) + } + this.npm.output(table.toString()) + } + }) } config () { const conf = { ...this.npm.flatOptions } const creds = this.npm.config.getCredentialsByURI(conf.registry) - if (creds.token) + if (creds.token) { conf.auth = { token: creds.token } - else if (creds.username) { + } else if (creds.username) { conf.auth = { basic: { username: creds.username, @@ -192,11 +201,13 @@ class Token extends BaseCommand { password: auth[1], }, } - } else + } else { conf.auth = {} + } - if (conf.otp) + if (conf.otp) { conf.auth.otp = conf.otp + } return conf } @@ -209,9 +220,9 @@ class Token extends BaseCommand { for (const token of tokens) { token.id = token.key for (let ii = minLength; ii < token.key.length; ++ii) { - const match = tokens.some(ot => - ot !== token && - ot.key.slice(0, ii) === token.key.slice(0, ii)) + const match = tokens.some( + ot => ot !== token && ot.key.slice(0, ii) === token.key.slice(0, ii) + ) if (!match) { token.id = token.key.slice(0, ii) break @@ -226,11 +237,15 @@ class Token extends BaseCommand { const maybeList = cidrs ? (Array.isArray(cidrs) ? cidrs : [cidrs]) : [] const list = maybeList.length === 1 ? maybeList[0].split(/,\s*/) : maybeList for (const cidr of list) { - if (isCidrV6(cidr)) - throw this.invalidCIDRError('CIDR whitelist can only contain IPv4 addresses, ' + cidr + ' is IPv6') + if (isCidrV6(cidr)) { + throw this.invalidCIDRError( + 'CIDR whitelist can only contain IPv4 addresses, ' + cidr + ' is IPv6' + ) + } - if (!isCidrV4(cidr)) + if (!isCidrV4(cidr)) { throw this.invalidCIDRError('CIDR whitelist contains invalid CIDR entry: ' + cidr) + } } return list } diff --git a/lib/commands/uninstall.js b/lib/commands/uninstall.js index 09b6e47a7..aaebd1a90 100644 --- a/lib/commands/uninstall.js +++ b/lib/commands/uninstall.js @@ -39,18 +39,19 @@ class Uninstall extends ArboristWorkspaceCmd { : this.npm.localPrefix if (!args.length) { - if (!global) + if (!global) { throw new Error('Must provide a package name to remove') - else { + } else { let pkg try { pkg = await rpj(resolve(this.npm.localPrefix, 'package.json')) } catch (er) { - if (er.code !== 'ENOENT' && er.code !== 'ENOTDIR') + if (er.code !== 'ENOENT' && er.code !== 'ENOTDIR') { throw er - else + } else { throw this.usageError() + } } args.push(pkg.name) diff --git a/lib/commands/unpublish.js b/lib/commands/unpublish.js index 60ab4a5f9..6ef3f282a 100644 --- a/lib/commands/unpublish.js +++ b/lib/commands/unpublish.js @@ -33,38 +33,44 @@ class Unpublish extends BaseCommand { async completion (args) { const { partialWord, conf } = args - if (conf.argv.remain.length >= 3) + if (conf.argv.remain.length >= 3) { return [] + } const opts = this.npm.flatOptions const username = await getIdentity(this.npm, { ...opts }).catch(() => null) - if (!username) + if (!username) { return [] + } const access = await libaccess.lsPackages(username, opts) // do a bit of filtering at this point, so that we don't need // to fetch versions for more than one thing, but also don't // accidentally unpublish a whole project let pkgs = Object.keys(access || {}) - if (!partialWord || !pkgs.length) + if (!partialWord || !pkgs.length) { return pkgs + } const pp = npa(partialWord).name pkgs = pkgs.filter(p => !p.indexOf(pp)) - if (pkgs.length > 1) + if (pkgs.length > 1) { return pkgs + } const json = await npmFetch.json(npa(pkgs[0]).escapedName, opts) const versions = Object.keys(json.versions) - if (!versions.length) + if (!versions.length) { return pkgs - else + } else { return versions.map(v => `${pkgs[0]}@${v}`) + } } async exec (args) { - if (args.length > 1) + if (args.length > 1) { throw this.usageError() + } const spec = args.length && npa(args[0]) const force = this.npm.config.get('force') @@ -93,10 +99,11 @@ class Unpublish extends BaseCommand { try { manifest = await readJson(pkgJson) } catch (err) { - if (err && err.code !== 'ENOENT' && err.code !== 'ENOTDIR') + if (err && err.code !== 'ENOENT' && err.code !== 'ENOTDIR') { throw err - else + } else { throw this.usageError() + } } this.npm.log.verbose('unpublish', manifest) @@ -104,19 +111,22 @@ class Unpublish extends BaseCommand { const { name, version, publishConfig } = manifest const pkgJsonSpec = npa.resolve(name, version) const optsWithPub = { ...opts, publishConfig } - if (!dryRun) + if (!dryRun) { await otplease(opts, opts => libunpub(pkgJsonSpec, optsWithPub)) + } pkgName = name pkgVersion = version ? `@${version}` : '' } else { - if (!dryRun) + if (!dryRun) { await otplease(opts, opts => libunpub(spec, opts)) + } pkgName = spec.name pkgVersion = spec.type === 'version' ? `@${spec.rawSpec}` : '' } - if (!silent) + if (!silent) { this.npm.output(`- ${pkgName}${pkgVersion}`) + } } async execWorkspaces (args, filters) { @@ -130,8 +140,9 @@ class Unpublish extends BaseCommand { ) } - for (const name of this.workspaceNames) + for (const name of this.workspaceNames) { await this.exec([name]) + } } } module.exports = Unpublish diff --git a/lib/commands/version.js b/lib/commands/version.js index 60e1e36f5..1572a3845 100644 --- a/lib/commands/version.js +++ b/lib/commands/version.js @@ -32,13 +32,21 @@ class Version extends BaseCommand { /* istanbul ignore next - see test/lib/load-all-commands.js */ static get usage () { - return ['[<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease | from-git]'] + return [ + /* eslint-disable-next-line max-len */ + '[<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease | from-git]', + ] } async completion (opts) { - const { conf: { argv: { remain } } } = opts - if (remain.length > 2) + const { + conf: { + argv: { remain }, + }, + } = opts + if (remain.length > 2) { return [] + } return [ 'major', @@ -104,17 +112,20 @@ class Version extends BaseCommand { .then(data => JSON.parse(data)) .catch(() => ({})) - if (pkg.name && pkg.version) + if (pkg.name && pkg.version) { results[pkg.name] = pkg.version + } results.npm = this.npm.version - for (const [key, version] of Object.entries(process.versions)) + for (const [key, version] of Object.entries(process.versions)) { results[key] = version + } - if (this.npm.config.get('json')) + if (this.npm.config.get('json')) { this.npm.output(JSON.stringify(results, null, 2)) - else + } else { this.npm.output(results) + } } async listWorkspaces (filters) { @@ -123,11 +134,11 @@ class Version extends BaseCommand { for (const path of this.workspacePaths) { const pj = resolve(path, 'package.json') // setWorkspaces has already parsed package.json so we know it won't error - const pkg = await readFile(pj, 'utf8') - .then(data => JSON.parse(data)) + const pkg = await readFile(pj, 'utf8').then(data => JSON.parse(data)) - if (pkg.name && pkg.version) + if (pkg.name && pkg.version) { results[pkg.name] = pkg.version + } } return this.list(results) } diff --git a/lib/commands/view.js b/lib/commands/view.js index 24d13cfcf..08bed57e0 100644 --- a/lib/commands/view.js +++ b/lib/commands/view.js @@ -67,44 +67,51 @@ class View extends BaseCommand { function getFields (d, f, pref) { f = f || [] - if (!d) + if (!d) { return f + } pref = pref || [] Object.keys(d).forEach((k) => { - if (k.charAt(0) === '_' || k.indexOf('.') !== -1) + if (k.charAt(0) === '_' || k.indexOf('.') !== -1) { return + } const p = pref.concat(k).join('.') f.push(p) if (Array.isArray(d[k])) { d[k].forEach((val, i) => { const pi = p + '[' + i + ']' - if (val && typeof val === 'object') + if (val && typeof val === 'object') { getFields(val, f, [p]) - else + } else { f.push(pi) + } }) return } - if (typeof d[k] === 'object') + if (typeof d[k] === 'object') { getFields(d[k], f, [p]) + } }) return f } } async exec (args) { - if (!args.length) + if (!args.length) { args = ['.'] + } let pkg = args.shift() const local = /^\.@/.test(pkg) || pkg === '.' if (local) { - if (this.npm.config.get('global')) + if (this.npm.config.get('global')) { throw new Error('Cannot use view command in global mode.') + } const dir = this.npm.prefix const manifest = await readJson(resolve(dir, 'package.json')) - if (!manifest.name) + if (!manifest.name) { throw new Error('Invalid package.json, no "name" field') + } // put the version back if it existed pkg = `${manifest.name}${pkg.slice(1)}` } @@ -131,14 +138,16 @@ class View extends BaseCommand { log.disableProgress() const msg = await this.jsonData(reducedData, pckmnt._id) - if (msg !== '') + if (msg !== '') { console.log(msg) + } } } async execWorkspaces (args, filters) { - if (!args.length) + if (!args.length) { args = ['.'] + } const pkg = args.shift() @@ -166,22 +175,25 @@ class View extends BaseCommand { } if (!this.npm.config.get('json')) { - if (wholePackument) + if (wholePackument) { data.map((v) => this.prettyView(pckmnt, v[Object.keys(v)[0]][''])) - else { + } else { console.log(`${name}:`) const msg = await this.jsonData(reducedData, pckmnt._id) - if (msg !== '') + if (msg !== '') { console.log(msg) + } } } else { const msg = await this.jsonData(reducedData, pckmnt._id) - if (msg !== '') + if (msg !== '') { results[name] = JSON.parse(msg) + } } } - if (Object.keys(results).length > 0) + if (Object.keys(results).length > 0) { console.log(JSON.stringify(results, null, 2)) + } } async getData (pkg, args) { @@ -196,13 +208,15 @@ class View extends BaseCommand { // get the data about this package let version = this.npm.config.get('tag') // rawSpec is the git url if this is from git - if (spec.type !== 'git' && spec.rawSpec) + if (spec.type !== 'git' && spec.rawSpec) { version = spec.rawSpec + } const pckmnt = await packument(spec, opts) - if (pckmnt['dist-tags'] && pckmnt['dist-tags'][version]) + if (pckmnt['dist-tags'] && pckmnt['dist-tags'][version]) { version = pckmnt['dist-tags'][version] + } if (pckmnt.time && pckmnt.time.unpublished) { const u = pckmnt.time.unpublished @@ -218,15 +232,17 @@ class View extends BaseCommand { pckmnt.versions = Object.keys(versions).sort(semver.compareLoose) // remove readme unless we asked for it - if (args.indexOf('readme') === -1) + if (args.indexOf('readme') === -1) { delete pckmnt.readme + } Object.keys(versions).forEach((v) => { if (semver.satisfies(v, version, true)) { args.forEach(arg => { // remove readme unless we asked for it - if (args.indexOf('readme') !== -1) + if (args.indexOf('readme') !== -1) { delete versions[v].readme + } data.push(showFields(pckmnt, versions[v], arg)) }) @@ -237,8 +253,9 @@ class View extends BaseCommand { !this.npm.config.get('json') && args.length === 1 && args[0] === '' - ) + ) { pckmnt.version = version + } return [pckmnt, data] } @@ -254,17 +271,19 @@ class View extends BaseCommand { versions.forEach((v) => { const fields = Object.keys(data[v]) includeFields = includeFields || (fields.length > 1) - if (json) + if (json) { msgJson.push({}) + } fields.forEach((f) => { let d = cleanup(data[v][f]) - if (fields.length === 1 && json) + if (fields.length === 1 && json) { msgJson[msgJson.length - 1][f] = d + } if (includeVersions || includeFields || typeof d !== 'string') { - if (json) + if (json) { msgJson[msgJson.length - 1][f] = d - else { + } else { d = inspect(d, { showHidden: false, depth: 5, @@ -272,12 +291,14 @@ class View extends BaseCommand { maxArrayLength: null, }) } - } else if (typeof d === 'string' && json) + } else if (typeof d === 'string' && json) { d = JSON.stringify(d) + } if (!json) { - if (f && includeFields) + if (f && includeFields) { f += ' = ' + } msg += (includeVersions ? name + '@' + v + ' ' : '') + (includeFields ? f : '') + d + '\n' } @@ -289,10 +310,11 @@ class View extends BaseCommand { const k = Object.keys(msgJson[0])[0] msgJson = msgJson.map(m => m[k]) } - if (msgJson.length === 1) + if (msgJson.length === 1) { msg = JSON.stringify(msgJson[0], null, 2) + '\n' - else if (msgJson.length > 1) + } else if (msgJson.length > 1) { msg = JSON.stringify(msgJson, null, 2) + '\n' + } } return msg.trim() @@ -351,10 +373,11 @@ class View extends BaseCommand { manifest.dist.fileCount && color.yellow(manifest.dist.fileCount), unpackedSize: unpackedSize && color.yellow(unpackedSize), } - if (info.license.toLowerCase().trim() === 'proprietary') + if (info.license.toLowerCase().trim() === 'proprietary') { info.license = style.bright(color.red(info.license)) - else + } else { info.license = color.green(info.license) + } console.log('') console.log( @@ -364,8 +387,9 @@ class View extends BaseCommand { ' | versions: ' + info.versions ) info.description && console.log(info.description) - if (info.repo || info.site) + if (info.repo || info.site) { info.site && console.log(color.cyan(info.site)) + } const warningSign = unicode ? ' ⚠️ ' : '!!' info.deprecated && console.log( @@ -396,8 +420,9 @@ class View extends BaseCommand { console.log('') console.log('dependencies:') console.log(columns(info.deps.slice(0, maxDeps), { padding: 1 })) - if (info.deps.length > maxDeps) + if (info.deps.length > maxDeps) { console.log(`(...and ${info.deps.length - maxDeps} more.)`) + } } if (info.maintainers && info.maintainers.length) { @@ -412,10 +437,12 @@ class View extends BaseCommand { if (info.publisher || info.modified) { let publishInfo = 'published' - if (info.modified) + if (info.modified) { publishInfo += ` ${info.modified}` - if (info.publisher) + } + if (info.publisher) { publishInfo += ` by ${info.publisher}` + } console.log('') console.log(publishInfo) } @@ -458,24 +485,28 @@ function showFields (data, version, fields) { const s = queryable.query(fields) const res = { [version.version]: s } - if (s) + if (s) { return res + } } function cleanup (data) { - if (Array.isArray(data)) + if (Array.isArray(data)) { return data.map(cleanup) + } - if (!data || typeof data !== 'object') + if (!data || typeof data !== 'object') { return data + } const keys = Object.keys(data) if (keys.length <= 3 && data.name && (keys.length === 1 || (keys.length === 3 && data.email && data.url) || - (keys.length === 2 && (data.email || data.url)))) + (keys.length === 2 && (data.email || data.url)))) { data = unparsePerson(data) + } return data } diff --git a/lib/npm.js b/lib/npm.js index 4b7b3440f..ecc7f0a7d 100644 --- a/lib/npm.js +++ b/lib/npm.js @@ -14,18 +14,19 @@ const timers = new Map() // Finished timers const timings = {} -const processOnTimeHandler = (name) => { +const processOnTimeHandler = name => { timers.set(name, Date.now()) } -const processOnTimeEndHandler = (name) => { +const processOnTimeEndHandler = name => { if (timers.has(name)) { const ms = Date.now() - timers.get(name) log.timing(name, `Completed in ${ms}ms`) timings[name] = ms timers.delete(name) - } else + } else { log.silly('timing', "Tried to end timer that doesn't exist:", name) + } } const { definitions, flatten, shorthands } = require('./utils/config/index.js') @@ -113,17 +114,23 @@ class Npm extends EventEmitter { // Options are prefixed by a hyphen-minus (-, \u2d). // Other dash-type chars look similar but are invalid. if (!warnedNonDashArg) { - args.filter(arg => /^[\u2010-\u2015\u2212\uFE58\uFE63\uFF0D]/.test(arg)) + args + .filter(arg => /^[\u2010-\u2015\u2212\uFE58\uFE63\uFF0D]/.test(arg)) .forEach(arg => { warnedNonDashArg = true - this.log.error('arg', 'Argument starts with non-ascii dash, this is probably invalid:', arg) + this.log.error( + 'arg', + 'Argument starts with non-ascii dash, this is probably invalid:', + arg + ) }) } const workspacesEnabled = this.config.get('workspaces') const workspacesFilters = this.config.get('workspace') - if (workspacesEnabled === false && workspacesFilters.length > 0) + if (workspacesEnabled === false && workspacesFilters.length > 0) { throw new Error('Can not use --no-workspaces and --workspace at the same time') + } const filterByWorkspaces = workspacesEnabled || workspacesFilters.length > 0 // normally this would go in the constructor, but our tests don't @@ -141,8 +148,9 @@ class Npm extends EventEmitter { return } if (filterByWorkspaces) { - if (this.config.get('global')) + if (this.config.get('global')) { throw new Error('Workspaces not supported for global packages') + } return command.execWorkspaces(args, this.config.get('workspace')).finally(() => { process.emit('timeEnd', `command:${cmd}`) @@ -159,16 +167,20 @@ class Npm extends EventEmitter { process.emit('time', 'npm:load') this.log.pause() this.loadPromise = new Promise((resolve, reject) => { - this[_load]().catch(er => er).then((er) => { - this.loadErr = er - if (!er && this.config.get('force')) - this.log.warn('using --force', 'Recommended protections disabled.') - - process.emit('timeEnd', 'npm:load') - if (er) - return reject(er) - resolve() - }) + this[_load]() + .catch(er => er) + .then(er => { + this.loadErr = er + if (!er && this.config.get('force')) { + this.log.warn('using --force', 'Recommended protections disabled.') + } + + process.emit('timeEnd', 'npm:load') + if (er) { + return reject(er) + } + resolve() + }) }) } return this.loadPromise @@ -215,7 +227,8 @@ class Npm extends EventEmitter { // args keeps those from being leaked. process.emit('time', 'npm:load:setTitle') const tokrev = deref(this.argv[0]) === 'token' && this.argv[1] === 'revoke' - this.title = tokrev ? 'npm token revoke' + (this.argv[2] ? ' ***' : '') + this.title = tokrev + ? 'npm token revoke' + (this.argv[2] ? ' ***' : '') : ['npm', ...this.argv].join(' ') process.emit('timeEnd', 'npm:load:setTitle') @@ -232,20 +245,21 @@ class Npm extends EventEmitter { process.emit('time', 'npm:load:configScope') const configScope = this.config.get('scope') - if (configScope && !/^@/.test(configScope)) + if (configScope && !/^@/.test(configScope)) { this.config.set('scope', `@${configScope}`, this.config.find('scope')) + } process.emit('timeEnd', 'npm:load:configScope') process.emit('time', 'npm:load:projectScope') - this.projectScope = this.config.get('scope') || - getProjectScope(this.prefix) + this.projectScope = this.config.get('scope') || getProjectScope(this.prefix) process.emit('timeEnd', 'npm:load:projectScope') } get flatOptions () { const { flat } = this.config - if (this.command) + if (this.command) { flat.npmCommand = this.command + } return flat } @@ -298,7 +312,7 @@ class Npm extends EventEmitter { } get dir () { - return (this.config.get('global')) ? this.globalDir : this.localDir + return this.config.get('global') ? this.globalDir : this.localDir } get globalBin () { diff --git a/lib/search/format-package-stream.js b/lib/search/format-package-stream.js index fb7d81856..7ff44e9e2 100644 --- a/lib/search/format-package-stream.js +++ b/lib/search/format-package-stream.js @@ -31,8 +31,9 @@ class JSONOutputStream extends Minipass { if (!this._didFirst) { super.write('[\n') this._didFirst = true - } else + } else { super.write('\n,\n') + } try { return super.write(JSON.stringify(obj)) @@ -93,8 +94,9 @@ function prettify (data, num, opts) { } ) output = trimToMaxWidth(output) - if (opts.color) + if (opts.color) { output = highlightSearchTerms(output, opts.args) + } return output } diff --git a/lib/search/package-filter.js b/lib/search/package-filter.js index 2e7d8e82a..45a67835b 100644 --- a/lib/search/package-filter.js +++ b/lib/search/package-filter.js @@ -19,13 +19,15 @@ function getWords (data, opts) { function filterWords (data, include, exclude, opts) { var words = getWords(data, opts) for (var i = 0, l = include.length; i < l; i++) { - if (!match(words, include[i])) + if (!match(words, include[i])) { return false + } } for (i = 0, l = exclude.length; i < l; i++) { - if (match(words, exclude[i])) + if (match(words, exclude[i])) { return false + } } return true diff --git a/lib/utils/audit-error.js b/lib/utils/audit-error.js index c58c1d16e..b4ab26fd0 100644 --- a/lib/utils/audit-error.js +++ b/lib/utils/audit-error.js @@ -4,11 +4,13 @@ // returns 'true' if there was an error, false otherwise const auditError = (npm, report) => { - if (!report || !report.error) + if (!report || !report.error) { return false + } - if (npm.command !== 'audit') + if (npm.command !== 'audit') { return true + } const { error } = report @@ -25,8 +27,9 @@ const auditError = (npm, report) => { statusCode: error.statusCode, body, }, null, 2)) - } else + } else { npm.output(body) + } throw 'audit endpoint returned an error' } diff --git a/lib/utils/cleanup-log-files.js b/lib/utils/cleanup-log-files.js index 13d1e50da..8fb0fa155 100644 --- a/lib/utils/cleanup-log-files.js +++ b/lib/utils/cleanup-log-files.js @@ -8,23 +8,26 @@ const { resolve } = require('path') const rimraf = require('rimraf') const glob = require('glob') module.exports = (cache, max, warn) => { - /* eslint-disable promise/param-names */ return new Promise(done => { glob(resolve(cache, '_logs', '*-debug.log'), (er, files) => { - if (er) + if (er) { return done() + } let pending = files.length - max - if (pending <= 0) + if (pending <= 0) { return done() + } for (let i = 0; i < files.length - max; i++) { - rimraf(files[i], (er) => { - if (er) + rimraf(files[i], er => { + if (er) { warn('log', 'failed to remove log file', files[i]) + } - if (--pending === 0) + if (--pending === 0) { done() + } }) } }) diff --git a/lib/utils/completion/installed-deep.js b/lib/utils/completion/installed-deep.js index 62686f9b2..7098d81fe 100644 --- a/lib/utils/completion/installed-deep.js +++ b/lib/utils/completion/installed-deep.js @@ -27,14 +27,16 @@ const installedDeep = async (npm) => { }) const gTree = await gArb.loadActual({ global: true }) - for (const node of getValues(gTree)) + for (const node of getValues(gTree)) { res.add(global ? node.name : [node.name, '-g']) + } if (!global) { const arb = new Arborist({ global: false, path: prefix, workspacesEnabled }) const tree = await arb.loadActual() - for (const node of getValues(tree)) + for (const node of getValues(tree)) { res.add(node.name) + } } return [...res] diff --git a/lib/utils/completion/installed-shallow.js b/lib/utils/completion/installed-shallow.js index 1c9b8ef5a..686c95e63 100644 --- a/lib/utils/completion/installed-shallow.js +++ b/lib/utils/completion/installed-shallow.js @@ -4,8 +4,9 @@ const readdir = promisify(require('readdir-scoped-modules')) const installedShallow = async (npm, opts) => { const names = global => readdir(global ? npm.globalDir : npm.localDir) const { conf: { argv: { remain } } } = opts - if (remain.length > 3) + if (remain.length > 3) { return null + } const { global } = npm.flatOptions const locals = global ? [] : await names(false) diff --git a/lib/utils/config/definition.js b/lib/utils/config/definition.js index 135485132..fc46bc3d6 100644 --- a/lib/utils/config/definition.js +++ b/lib/utils/config/definition.js @@ -6,12 +6,7 @@ // say "these are for registry access", "these are for // version resolution" etc. -const required = [ - 'type', - 'description', - 'default', - 'key', -] +const required = ['type', 'description', 'default', 'key'] const allowed = [ 'default', @@ -44,42 +39,50 @@ class Definition { this.envExport = true Object.assign(this, def) this.validate() - if (!this.defaultDescription) + if (!this.defaultDescription) { this.defaultDescription = describeValue(this.default) - if (!this.typeDescription) + } + if (!this.typeDescription) { this.typeDescription = describeType(this.type) + } // hint is only used for non-boolean values if (!this.hint) { - if (this.type === Number) + if (this.type === Number) { this.hint = '<number>' - else + } else { this.hint = `<${this.key}>` + } } - if (!this.usage) + if (!this.usage) { this.usage = describeUsage(this) + } } validate () { for (const req of required) { - if (!Object.prototype.hasOwnProperty.call(this, req)) + if (!Object.prototype.hasOwnProperty.call(this, req)) { throw new Error(`config lacks ${req}: ${this.key}`) + } } - if (!this.key) + if (!this.key) { throw new Error(`config lacks key: ${this.key}`) + } for (const field of Object.keys(this)) { - if (!allowed.includes(field)) + if (!allowed.includes(field)) { throw new Error(`config defines unknown field ${field}: ${this.key}`) + } } } // a textual description of this config, suitable for help output describe () { const description = unindent(this.description) - const noEnvExport = this.envExport ? '' : ` + const noEnvExport = this.envExport + ? '' + : ` This value is not exported to the environment for child processes. ` - const deprecated = !this.deprecated ? '' - : `* DEPRECATED: ${unindent(this.deprecated)}\n` + const deprecated = !this.deprecated ? '' : `* DEPRECATED: ${unindent(this.deprecated)}\n` return wrapAll(`#### \`${this.key}\` * Default: ${unindent(this.defaultDescription)} @@ -90,28 +93,32 @@ ${noEnvExport}`) } } -const describeUsage = (def) => { +const describeUsage = def => { let key = '' // Single type if (!Array.isArray(def.type)) { - if (def.short) + if (def.short) { key = `-${def.short}|` + } - if (def.type === Boolean && def.default !== false) + if (def.type === Boolean && def.default !== false) { key = `${key}--no-${def.key}` - else + } else { key = `${key}--${def.key}` + } - if (def.type !== Boolean) + if (def.type !== Boolean) { key = `${key} ${def.hint}` + } return key } key = `--${def.key}` - if (def.short) + if (def.short) { key = `-${def.short}|--${def.key}` + } // Multiple types let types = def.type @@ -122,14 +129,15 @@ const describeUsage = (def) => { // all non-optional params have defaults so we render everything as optional types = types.filter(t => t !== null && t !== Array && t !== Boolean) - if (!types.length) + if (!types.length) { return key + } let description - if (!types.some(t => typeof t !== 'string')) + if (!types.some(t => typeof t !== 'string')) { // Specific values, use specifics given description = `<${types.filter(d => d).join('|')}>` - else { + } else { // Generic values, use hint description = def.hint } @@ -142,17 +150,16 @@ const describeUsage = (def) => { } const usage = `${key} ${description}` - if (multiple) + if (multiple) { return `${usage} [${usage} ...]` - else + } else { return usage + } } const describeType = type => { if (Array.isArray(type)) { - const descriptions = type - .filter(t => t !== Array) - .map(t => describeType(t)) + const descriptions = type.filter(t => t !== Array).map(t => describeType(t)) // [a] => "a" // [a, b] => "a or b" @@ -162,8 +169,7 @@ const describeType = type => { const last = descriptions.length > 1 ? [descriptions.pop()] : [] const oxford = descriptions.length > 1 ? ', or ' : ' or ' const words = [descriptions.join(', ')].concat(last).join(oxford) - const multiple = type.includes(Array) ? ' (can be set multiple times)' - : '' + const multiple = type.includes(Array) ? ' (can be set multiple times)' : '' return `${words}${multiple}` } @@ -193,8 +199,7 @@ const describeType = type => { } // if it's a string, quote it. otherwise, just cast to string. -const describeValue = val => - typeof val === 'string' ? JSON.stringify(val) : String(val) +const describeValue = val => (typeof val === 'string' ? JSON.stringify(val) : String(val)) const unindent = s => { // get the first \n followed by a bunch of spaces, and pluck off @@ -203,30 +208,44 @@ const unindent = s => { return !match ? s.trim() : s.split(match[0]).join('\n').trim() } -const wrap = (s) => { +const wrap = s => { const cols = Math.min(Math.max(20, process.stdout.columns) || 80, 80) - 5 - return unindent(s).split(/[ \n]+/).reduce((left, right) => { - const last = left.split('\n').pop() - const join = last.length && last.length + right.length > cols ? '\n' : ' ' - return left + join + right - }) + return unindent(s) + .split(/[ \n]+/) + .reduce((left, right) => { + const last = left.split('\n').pop() + const join = last.length && last.length + right.length > cols ? '\n' : ' ' + return left + join + right + }) } const wrapAll = s => { let inCodeBlock = false - return s.split('\n\n').map(block => { - if (inCodeBlock || block.startsWith('```')) { - inCodeBlock = !block.endsWith('```') - return block - } - - if (block.charAt(0) === '*') { - return '* ' + block.substr(1).trim().split('\n* ').map(li => { - return wrap(li).replace(/\n/g, '\n ') - }).join('\n* ') - } else - return wrap(block) - }).join('\n\n') + return s + .split('\n\n') + .map(block => { + if (inCodeBlock || block.startsWith('```')) { + inCodeBlock = !block.endsWith('```') + return block + } + + if (block.charAt(0) === '*') { + return ( + '* ' + + block + .substr(1) + .trim() + .split('\n* ') + .map(li => { + return wrap(li).replace(/\n/g, '\n ') + }) + .join('\n* ') + ) + } else { + return wrap(block) + } + }) + .join('\n\n') } module.exports = Definition diff --git a/lib/utils/config/definitions.js b/lib/utils/config/definitions.js index a725ee0fa..b47a46de8 100644 --- a/lib/utils/config/definitions.js +++ b/lib/utils/config/definitions.js @@ -16,8 +16,9 @@ const maybeReadFile = file => { try { return fs.readFileSync(file, 'utf8') } catch (er) { - if (er.code !== 'ENOENT') + if (er.code !== 'ENOENT') { throw er + } return null } } @@ -27,27 +28,32 @@ const buildOmitList = obj => { const omit = obj.omit || [] const only = obj.only - if (/^prod(uction)?$/.test(only) || obj.production) + if (/^prod(uction)?$/.test(only) || obj.production) { omit.push('dev') - else if (obj.production === false) + } else if (obj.production === false) { include.push('dev') + } - if (/^dev/.test(obj.also)) + if (/^dev/.test(obj.also)) { include.push('dev') + } - if (obj.dev) + if (obj.dev) { include.push('dev') + } - if (obj.optional === false) + if (obj.optional === false) { omit.push('optional') - else if (obj.optional === true) + } else if (obj.optional === true) { include.push('optional') + } obj.omit = [...new Set(omit)].filter(type => !include.includes(type)) obj.include = [...new Set(include)] - if (obj.omit.includes('dev')) + if (obj.omit.includes('dev')) { process.env.NODE_ENV = 'production' + } return obj.omit } @@ -98,8 +104,9 @@ const { const define = (key, def) => { /* istanbul ignore if - this should never happen, prevents mistakes below */ - if (definitions[key]) + if (definitions[key]) { throw new Error(`defining key more than once: ${key}`) + } definitions[key] = new Definition(key, def) } @@ -342,8 +349,9 @@ define('cache-max', { This option has been deprecated in favor of \`--prefer-online\` `, flatten (key, obj, flatOptions) { - if (obj[key] <= 0) + if (obj[key] <= 0) { flatOptions.preferOnline = true + } }, }) @@ -357,8 +365,9 @@ define('cache-min', { This option has been deprecated in favor of \`--prefer-offline\`. `, flatten (key, obj, flatOptions) { - if (obj[key] >= 9999) + if (obj[key] >= 9999) { flatOptions.preferOffline = true + } }, }) @@ -372,12 +381,14 @@ define('cafile', { `, flatten (key, obj, flatOptions) { // always set to null in defaults - if (!obj.cafile) + if (!obj.cafile) { return + } const raw = maybeReadFile(obj.cafile) - if (!raw) + if (!raw) { return + } const delim = '-----END CERTIFICATE-----' flatOptions.ca = raw.replace(/\r\n/g, '\n').split(delim) @@ -806,8 +817,9 @@ define('global', { `, flatten: (key, obj, flatOptions) => { flatten(key, obj, flatOptions) - if (flatOptions.global) + if (flatOptions.global) { flatOptions.location = 'global' + } }, }) @@ -1150,8 +1162,9 @@ define('location', { `, flatten: (key, obj, flatOptions) => { flatten(key, obj, flatOptions) - if (flatOptions.global) + if (flatOptions.global) { flatOptions.location = 'global' + } }, }) @@ -1281,10 +1294,11 @@ define('noproxy', { Also accepts a comma-delimited string. `, flatten (key, obj, flatOptions) { - if (Array.isArray(obj[key])) + if (Array.isArray(obj[key])) { flatOptions.noProxy = obj[key].join(',') - else + } else { flatOptions.noProxy = obj[key] + } }, }) @@ -1403,8 +1417,9 @@ define('package-lock', { `, flatten: (key, obj, flatOptions) => { flatten(key, obj, flatOptions) - if (flatOptions.packageLockOnly) + if (flatOptions.packageLockOnly) { flatOptions.packageLock = true + } }, }) @@ -1423,8 +1438,9 @@ define('package-lock-only', { `, flatten: (key, obj, flatOptions) => { flatten(key, obj, flatOptions) - if (flatOptions.packageLockOnly) + if (flatOptions.packageLockOnly) { flatOptions.packageLock = true + } }, }) @@ -1607,8 +1623,9 @@ define('save-dev', { `, flatten (key, obj, flatOptions) { if (!obj[key]) { - if (flatOptions.saveType === 'dev') + if (flatOptions.saveType === 'dev') { delete flatOptions.saveType + } return } @@ -1640,20 +1657,23 @@ define('save-optional', { `, flatten (key, obj, flatOptions) { if (!obj[key]) { - if (flatOptions.saveType === 'optional') + if (flatOptions.saveType === 'optional') { delete flatOptions.saveType - else if (flatOptions.saveType === 'peerOptional') + } else if (flatOptions.saveType === 'peerOptional') { flatOptions.saveType = 'peer' + } return } - if (flatOptions.saveType === 'peerOptional') + if (flatOptions.saveType === 'peerOptional') { return + } - if (flatOptions.saveType === 'peer') + if (flatOptions.saveType === 'peer') { flatOptions.saveType = 'peerOptional' - else + } else { flatOptions.saveType = 'optional' + } }, }) @@ -1665,20 +1685,23 @@ define('save-peer', { `, flatten (key, obj, flatOptions) { if (!obj[key]) { - if (flatOptions.saveType === 'peer') + if (flatOptions.saveType === 'peer') { delete flatOptions.saveType - else if (flatOptions.saveType === 'peerOptional') + } else if (flatOptions.saveType === 'peerOptional') { flatOptions.saveType = 'optional' + } return } - if (flatOptions.saveType === 'peerOptional') + if (flatOptions.saveType === 'peerOptional') { return + } - if (flatOptions.saveType === 'optional') + if (flatOptions.saveType === 'optional') { flatOptions.saveType = 'peerOptional' - else + } else { flatOptions.saveType = 'peer' + } }, }) @@ -1715,8 +1738,9 @@ define('save-prod', { `, flatten (key, obj, flatOptions) { if (!obj[key]) { - if (flatOptions.saveType === 'prod') + if (flatOptions.saveType === 'prod') { delete flatOptions.saveType + } return } @@ -2085,8 +2109,9 @@ define('user-agent', { const value = obj[key] const ciName = obj['ci-name'] let inWorkspaces = false - if (obj.workspaces || obj.workspace && obj.workspace.length) + if (obj.workspaces || obj.workspace && obj.workspace.length) { inWorkspaces = true + } flatOptions.userAgent = value.replace(/\{node-version\}/gi, obj['node-version']) .replace(/\{npm-version\}/gi, obj['npm-version']) diff --git a/lib/utils/config/describe-all.js b/lib/utils/config/describe-all.js index 23a10ae97..39f8d5fe4 100644 --- a/lib/utils/config/describe-all.js +++ b/lib/utils/config/describe-all.js @@ -5,7 +5,7 @@ const describeAll = () => { /* istanbul ignore next - typically already sorted in the definitions file, * but this is here so that our help doc will stay consistent if we decide * to move them around. */ - const sort = ([keya, {deprecated: depa}], [keyb, {deprecated: depb}]) => { + const sort = ([keya, { deprecated: depa }], [keyb, { deprecated: depb }]) => { return depa && !depb ? 1 : !depa && depb ? -1 : localeCompare(keya, keyb) diff --git a/lib/utils/config/flatten.js b/lib/utils/config/flatten.js index f6d6124bd..588d05bf0 100644 --- a/lib/utils/config/flatten.js +++ b/lib/utils/config/flatten.js @@ -11,10 +11,11 @@ const definitions = require('./definitions.js') const flatten = (obj, flat = {}) => { for (const [key, val] of Object.entries(obj)) { const def = definitions[key] - if (def && def.flatten) + if (def && def.flatten) { def.flatten(key, obj, flat) - else if (/@.*:registry$/i.test(key) || /^\/\//.test(key)) + } else if (/@.*:registry$/i.test(key) || /^\/\//.test(key)) { flat[key] = val + } } // XXX make this the bin/npm-cli.js file explicitly instead diff --git a/lib/utils/config/index.js b/lib/utils/config/index.js index a24f58652..d8706d50c 100644 --- a/lib/utils/config/index.js +++ b/lib/utils/config/index.js @@ -27,12 +27,14 @@ const shorthands = { reg: ['--registry'], } -for (const [key, {short}] of Object.entries(definitions)) { - if (!short) +for (const [key, { short }] of Object.entries(definitions)) { + if (!short) { continue + } // can be either an array or string - for (const s of [].concat(short)) + for (const s of [].concat(short)) { shorthands[s] = [`--${key}`] + } } module.exports = { diff --git a/lib/utils/deref-command.js b/lib/utils/deref-command.js index f45c2627e..dd89fb5a4 100644 --- a/lib/utils/deref-command.js +++ b/lib/utils/deref-command.js @@ -7,21 +7,25 @@ const abbrev = require('abbrev') const abbrevs = abbrev(fullList) module.exports = c => { - if (!c || typeof c !== 'string') + if (!c || typeof c !== 'string') { return '' + } - if (c.match(/[A-Z]/)) + if (c.match(/[A-Z]/)) { c = c.replace(/([A-Z])/g, m => '-' + m.toLowerCase()) + } - if (plumbing.indexOf(c) !== -1) + if (plumbing.indexOf(c) !== -1) { return c + } // first deref the abbrev, if there is one // then resolve any aliases // so `npm install-cl` will resolve to `install-clean` then to `ci` let a = abbrevs[c] - while (aliases[a]) + while (aliases[a]) { a = aliases[a] + } return a || '' } diff --git a/lib/utils/did-you-mean.js b/lib/utils/did-you-mean.js index 953048309..b859abaaf 100644 --- a/lib/utils/did-you-mean.js +++ b/lib/utils/did-you-mean.js @@ -4,8 +4,7 @@ const { cmdList } = require('./cmd-list.js') const didYouMean = async (npm, path, scmd) => { // const cmd = await npm.cmd(str) - const close = cmdList - .filter(cmd => distance(scmd, cmd) < scmd.length * 0.4 && scmd !== cmd) + const close = cmdList.filter(cmd => distance(scmd, cmd) < scmd.length * 0.4 && scmd !== cmd) let best = [] for (const str of close) { const cmd = await npm.cmd(str) @@ -17,22 +16,25 @@ const didYouMean = async (npm, path, scmd) => { const { bin, scripts } = await readJson(`${path}/package.json`) best = best.concat( Object.keys(scripts || {}) - .filter(cmd => distance(scmd, cmd) < scmd.length * 0.4 && - !runScripts.includes(cmd)) + .filter(cmd => distance(scmd, cmd) < scmd.length * 0.4 && !runScripts.includes(cmd)) .map(str => ` npm run ${str} # run the "${str}" package script`), Object.keys(bin || {}) .filter(cmd => distance(scmd, cmd) < scmd.length * 0.4) + /* eslint-disable-next-line max-len */ .map(str => ` npm exec ${str} # run the "${str}" command from either this or a remote npm package`) ) } catch (_) { // gracefully ignore not being in a folder w/ a package.json } - if (best.length === 0) + if (best.length === 0) { return '' + } - const suggestion = best.length === 1 ? `\n\nDid you mean this?\n${best[0]}` - : `\n\nDid you mean one of these?\n${best.slice(0, 3).join('\n')}` + const suggestion = + best.length === 1 + ? `\n\nDid you mean this?\n${best[0]}` + : `\n\nDid you mean one of these?\n${best.slice(0, 3).join('\n')}` return suggestion } module.exports = didYouMean diff --git a/lib/utils/error-message.js b/lib/utils/error-message.js index 9343d37d5..48ad4676f 100644 --- a/lib/utils/error-message.js +++ b/lib/utils/error-message.js @@ -9,10 +9,12 @@ module.exports = (er, npm) => { const short = [] const detail = [] - if (er.message) + if (er.message) { er.message = replaceInfo(er.message) - if (er.stack) + } + if (er.stack) { er.stack = replaceInfo(er.stack) + } switch (er.code) { case 'ERESOLVE': @@ -46,10 +48,14 @@ module.exports = (er, npm) => { case 'EACCES': case 'EPERM': { - const isCachePath = typeof er.path === 'string' && - npm.config.loaded && er.path.startsWith(npm.config.get('cache')) - const isCacheDest = typeof er.dest === 'string' && - npm.config.loaded && er.dest.startsWith(npm.config.get('cache')) + const isCachePath = + typeof er.path === 'string' && + npm.config.loaded && + er.path.startsWith(npm.config.get('cache')) + const isCacheDest = + typeof er.dest === 'string' && + npm.config.loaded && + er.dest.startsWith(npm.config.get('cache')) const isWindows = require('./is-windows.js') @@ -64,7 +70,9 @@ module.exports = (er, npm) => { 'previous versions of npm which has since been addressed.', '', 'To permanently fix this problem, please run:', - ` sudo chown -R ${process.getuid()}:${process.getgid()} ${JSON.stringify(npm.config.get('cache'))}`, + ` sudo chown -R ${process.getuid()}:${process.getgid()} ${JSON.stringify( + npm.config.get('cache') + )}`, ].join('\n'), ]) } else { @@ -73,14 +81,17 @@ module.exports = (er, npm) => { '', [ '\nThe operation was rejected by your operating system.', - (isWindows - ? 'It\'s possible that the file was already in use (by a text editor or antivirus),\n' + + isWindows + /* eslint-disable-next-line max-len */ + ? "It's possible that the file was already in use (by a text editor or antivirus),\n" + 'or that you lack permissions to access it.' - : 'It is likely you do not have the permissions to access this file as the current user'), + /* eslint-disable-next-line max-len */ + : 'It is likely you do not have the permissions to access this file as the current user', '\nIf you believe this might be a permissions issue, please double-check the', 'permissions of the file and its containing directories, or try running', 'the command again as root/Administrator.', - ].join('\n')]) + ].join('\n'), + ]) } break } @@ -89,11 +100,9 @@ module.exports = (er, npm) => { short.push(['', er.message]) detail.push([ '', - [ - '', - 'Failed using git.', - 'Please check if you have git installed and in your PATH.', - ].join('\n'), + ['', 'Failed using git.', 'Please check if you have git installed and in your PATH.'].join( + '\n' + ), ]) break @@ -101,8 +110,7 @@ module.exports = (er, npm) => { // Check whether we ran into a conflict in our own package.json if (er.path === resolve(npm.prefix, 'package.json')) { const { isDiff } = require('parse-conflict-json') - const txt = require('fs').readFileSync(er.path, 'utf8') - .replace(/\r\n/g, '\n') + const txt = require('fs').readFileSync(er.path, 'utf8').replace(/\r\n/g, '\n') if (isDiff(txt)) { detail.push([ '', @@ -141,17 +149,19 @@ module.exports = (er, npm) => { } else { // npm ERR! code E401 // npm ERR! Unable to authenticate, need: Basic - const auth = !er.headers || !er.headers['www-authenticate'] ? [] - : er.headers['www-authenticate'].map((au) => au.split(/[,\s]+/))[0] + const auth = + !er.headers || !er.headers['www-authenticate'] + ? [] + : er.headers['www-authenticate'].map(au => au.split(/[,\s]+/))[0] if (auth.includes('Bearer')) { - short.push(['', 'Unable to authenticate, your authentication token seems to be invalid.']) + short.push([ + '', + 'Unable to authenticate, your authentication token seems to be invalid.', + ]) detail.push([ '', - [ - 'To correct this please trying logging in again with:', - ' npm login', - ].join('\n'), + ['To correct this please trying logging in again with:', ' npm login'].join('\n'), ]) } else if (auth.includes('Basic')) { short.push(['', 'Incorrect or missing password.']) @@ -169,8 +179,9 @@ module.exports = (er, npm) => { ' npm login', ].join('\n'), ]) - } else + } else { short.push(['', er.message || er]) + } } break @@ -185,19 +196,16 @@ module.exports = (er, npm) => { const valResult = nameValidator(pkg) - if (valResult.validForNewPackages) - detail.push(['404', 'You should bug the author to publish it (or use the name yourself!)']) - else { + if (valResult.validForNewPackages) { + detail.push([ + '404', + 'You should bug the author to publish it (or use the name yourself!)', + ]) + } else { detail.push(['404', 'This package name is not valid, because', '']) - const errorsArray = [ - ...(valResult.errors || []), - ...(valResult.warnings || []), - ] - errorsArray.forEach((item, idx) => detail.push([ - '404', - ' ' + (idx + 1) + '. ' + item, - ])) + const errorsArray = [...(valResult.errors || []), ...(valResult.warnings || [])] + errorsArray.forEach((item, idx) => detail.push(['404', ' ' + (idx + 1) + '. ' + item])) } detail.push(['404', '\nNote that you can also install from a']) @@ -218,26 +226,30 @@ module.exports = (er, npm) => { short.push(['git', ' ' + er.path]) detail.push([ 'git', - [ - 'Refusing to remove it. Update manually,', - 'or move it out of the way first.', - ].join('\n'), + ['Refusing to remove it. Update manually,', 'or move it out of the way first.'].join('\n'), ]) break case 'EBADPLATFORM': { - const validOs = er.required && - er.required.os && - er.required.os.join ? er.required.os.join(',') : er.required.os - const validArch = er.required && - er.required.cpu && - er.required.cpu.join ? er.required.cpu.join(',') : er.required.cpu + const validOs = + er.required && er.required.os && er.required.os.join + ? er.required.os.join(',') + : er.required.os + const validArch = + er.required && er.required.cpu && er.required.cpu.join + ? er.required.cpu.join(',') + : er.required.cpu const expected = { os: validOs, arch: validArch } const actual = { os: process.platform, arch: process.arch } short.push([ 'notsup', [ - format('Unsupported platform for %s: wanted %j (current: %j)', er.pkgid, expected, actual), + format( + 'Unsupported platform for %s: wanted %j (current: %j)', + er.pkgid, + expected, + actual + ), ].join('\n'), ]) detail.push([ @@ -283,19 +295,25 @@ module.exports = (er, npm) => { case 'ETARGET': short.push(['notarget', er.message]) - detail.push(['notarget', [ - 'In most cases you or one of your dependencies are requesting', - "a package version that doesn't exist.", - ].join('\n')]) + detail.push([ + 'notarget', + [ + 'In most cases you or one of your dependencies are requesting', + "a package version that doesn't exist.", + ].join('\n'), + ]) break case 'E403': short.push(['403', er.message]) - detail.push(['403', [ - 'In most cases, you or one of your dependencies are requesting', - 'a package version that is forbidden by your security policy, or', - 'on a server you do not have access to.', - ].join('\n')]) + detail.push([ + '403', + [ + 'In most cases, you or one of your dependencies are requesting', + 'a package version that is forbidden by your security policy, or', + 'on a server you do not have access to.', + ].join('\n'), + ]) break case 'EBADENGINE': @@ -306,10 +324,11 @@ module.exports = (er, npm) => { [ 'Not compatible with your version of node/npm: ' + er.pkgid, 'Required: ' + JSON.stringify(er.required), - 'Actual: ' + JSON.stringify({ - npm: npm.version, - node: npm.config.loaded ? npm.config.get('node-version') : process.version, - }), + 'Actual: ' + + JSON.stringify({ + npm: npm.version, + node: npm.config.loaded ? npm.config.get('node-version') : process.version, + }), ].join('\n'), ]) break @@ -363,17 +382,21 @@ module.exports = (er, npm) => { default: short.push(['', er.message || er]) - if (er.signal) + if (er.signal) { detail.push(['signal', er.signal]) + } - if (er.cmd && Array.isArray(er.args)) + if (er.cmd && Array.isArray(er.args)) { detail.push(['command', ...[er.cmd, ...er.args.map(replaceInfo)]]) + } - if (er.stdout) + if (er.stdout) { detail.push(['', er.stdout.trim()]) + } - if (er.stderr) + if (er.stderr) { detail.push(['', er.stderr.trim()]) + } break } diff --git a/lib/utils/exit-handler.js b/lib/utils/exit-handler.js index 7be138d2c..5b2811468 100644 --- a/lib/utils/exit-handler.js +++ b/lib/utils/exit-handler.js @@ -15,8 +15,13 @@ let wroteLogFile = false const getLogFile = () => { // we call this multiple times, so we need to treat it as a singleton because // the date is part of the name - if (!logFileName) - logFileName = path.resolve(npm.config.get('cache'), '_logs', (new Date()).toISOString().replace(/[.:]/g, '_') + '-debug.log') + if (!logFileName) { + logFileName = path.resolve( + npm.config.get('cache'), + '_logs', + new Date().toISOString().replace(/[.:]/g, '_') + '-debug.log' + ) + } return logFileName } @@ -26,8 +31,9 @@ process.on('exit', code => { // unfinished timer check below process.emit('timeEnd', 'npm') npm.log.disableProgress() - for (const [name, timers] of npm.timers) + for (const [name, timers] of npm.timers) { npm.log.verbose('unfinished npm timer', name, timers) + } if (npm.config.loaded && npm.config.get('timing')) { try { @@ -35,12 +41,15 @@ process.on('exit', code => { const dir = path.dirname(npm.config.get('cache')) mkdirp.sync(dir) - fs.appendFileSync(file, JSON.stringify({ - command: process.argv.slice(2), - logfile: getLogFile(), - version: npm.version, - ...npm.timings, - }) + '\n') + fs.appendFileSync( + file, + JSON.stringify({ + command: process.argv.slice(2), + logfile: getLogFile(), + version: npm.version, + ...npm.timings, + }) + '\n' + ) const st = fs.lstatSync(path.dirname(npm.config.get('cache'))) fs.chownSync(dir, st.uid, st.gid) @@ -50,10 +59,11 @@ process.on('exit', code => { } } - if (!code) + if (!code) { npm.log.info('ok') - else + } else { npm.log.verbose('code', code) + } if (!exitHandlerCalled) { process.exitCode = code || 1 @@ -65,19 +75,18 @@ process.on('exit', code => { writeLogFile() } // In timing mode we always write the log file - if (npm.config.loaded && npm.config.get('timing') && !wroteLogFile) + if (npm.config.loaded && npm.config.get('timing') && !wroteLogFile) { writeLogFile() + } if (wroteLogFile) { // just a line break - if (npm.log.levels[npm.log.level] <= npm.log.levels.error) + if (npm.log.levels[npm.log.level] <= npm.log.levels.error) { console.error('') + } npm.log.error( '', - [ - 'A complete log of this run can be found in:', - ' ' + getLogFile(), - ].join('\n') + ['A complete log of this run can be found in:', ' ' + getLogFile()].join('\n') ) } @@ -86,7 +95,7 @@ process.on('exit', code => { wroteLogFile = false }) -const exitHandler = (err) => { +const exitHandler = err => { npm.log.disableProgress() if (!npm.config.loaded) { err = err || new Error('Exit prior to config file resolving.') @@ -131,8 +140,9 @@ const exitHandler = (err) => { for (const k of ['type', 'stack', 'statusCode', 'pkgid']) { const v = err[k] - if (v) + if (v) { npm.log.verbose(k, replaceInfo(v)) + } } npm.log.verbose('cwd', process.cwd()) @@ -145,13 +155,15 @@ const exitHandler = (err) => { for (const k of ['code', 'syscall', 'file', 'path', 'dest', 'errno']) { const v = err[k] - if (v) + if (v) { npm.log.error(k, v) + } } const msg = errorMessage(err, npm) - for (const errline of [...msg.summary, ...msg.detail]) + for (const errline of [...msg.summary, ...msg.detail]) { npm.log.error(...errline) + } if (npm.config.loaded && npm.config.get('json')) { const error = { @@ -164,21 +176,24 @@ const exitHandler = (err) => { console.error(JSON.stringify(error, null, 2)) } - if (typeof err.errno === 'number') + if (typeof err.errno === 'number') { exitCode = err.errno - else if (typeof err.code === 'number') + } else if (typeof err.code === 'number') { exitCode = err.code + } } } npm.log.verbose('exit', exitCode || 0) - if (npm.log.level === 'silent') + if (npm.log.level === 'silent') { noLog = true + } // noLog is true if there was an error, including if config wasn't loaded, so // this doesn't need a config.loaded guard - if (exitCode && !noLog) + if (exitCode && !noLog) { writeLogFile() + } // explicitly call process.exit now so we don't hang on things like the // update notifier, also flush stdout beforehand because process.exit doesn't @@ -193,11 +208,14 @@ const writeLogFile = () => { let logOutput = '' npm.log.record.forEach(m => { const p = [m.id, m.level] - if (m.prefix) + if (m.prefix) { p.push(m.prefix) + } const pref = p.join(' ') - m.message.trim().split(/\r?\n/) + m.message + .trim() + .split(/\r?\n/) .map(line => (pref + ' ' + line).trim()) .forEach(line => { logOutput += line + os.EOL @@ -216,12 +234,10 @@ const writeLogFile = () => { // truncate once it's been written. npm.log.record.length = 0 wroteLogFile = true - } catch (ex) { - - } + } catch (ex) {} } module.exports = exitHandler -module.exports.setNpm = (n) => { +module.exports.setNpm = n => { npm = n } diff --git a/lib/utils/explain-dep.js b/lib/utils/explain-dep.js index 944b4be62..107f68549 100644 --- a/lib/utils/explain-dep.js +++ b/lib/utils/explain-dep.js @@ -43,20 +43,25 @@ const printNode = (node, color) => { } = node const { bold, dim, green } = color ? chalk : nocolor const extra = [] - if (extraneous) + if (extraneous) { extra.push(' ' + bold(colorType('extraneous', color))) + } - if (dev) + if (dev) { extra.push(' ' + bold(colorType('dev', color))) + } - if (optional) + if (optional) { extra.push(' ' + bold(colorType('optional', color))) + } - if (peer) + if (peer) { extra.push(' ' + bold(colorType('peer', color))) + } - if (bundled) + if (bundled) { extra.push(' ' + bold(colorType('bundled', color))) + } const pkgid = isWorkspace ? green(`${name}@${version}`) @@ -67,8 +72,9 @@ const printNode = (node, color) => { } const explainLinksIn = ({ linksIn }, depth, color) => { - if (!linksIn || !linksIn.length || depth <= 0) + if (!linksIn || !linksIn.length || depth <= 0) { return '' + } const messages = linksIn.map(link => explainNode(link, depth - 1, color)) const str = '\n' + messages.join('\n') @@ -76,8 +82,9 @@ const explainLinksIn = ({ linksIn }, depth, color) => { } const explainDependents = ({ name, dependents }, depth, color) => { - if (!dependents || !dependents.length || depth <= 0) + if (!dependents || !dependents.length || depth <= 0) { return '' + } const max = Math.ceil(depth / 2) const messages = dependents.slice(0, max) @@ -118,8 +125,9 @@ const explainEdge = ({ name, type, bundled, from, spec }, depth, color) => { } const explainFrom = (from, depth, color) => { - if (!from.name && !from.version) + if (!from.name && !from.version) { return 'the root project' + } return printNode(from, color) + explainDependents(from, depth - 1, color) + diff --git a/lib/utils/explain-eresolve.js b/lib/utils/explain-eresolve.js index b25e3e4a9..7f6a10869 100644 --- a/lib/utils/explain-eresolve.js +++ b/lib/utils/explain-eresolve.js @@ -15,20 +15,22 @@ const explain = (expl, color, depth) => { const whileInstalling = dep && dep.whileInstalling || current && current.whileInstalling || edge && edge.from && edge.from.whileInstalling - if (whileInstalling) + if (whileInstalling) { out.push('While resolving: ' + printNode(whileInstalling, color)) + } // it "should" be impossible for an ERESOLVE explanation to lack both // current and currentEdge, but better to have a less helpful error // than a crashing failure. - if (current) + if (current) { out.push('Found: ' + explainNode(current, depth, color)) - else if (peerConflict && peerConflict.current) + } else if (peerConflict && peerConflict.current) { out.push('Found: ' + explainNode(peerConflict.current, depth, color)) - else if (currentEdge) + } else if (currentEdge) { out.push('Found: ' + explainEdge(currentEdge, depth, color)) - else /* istanbul ignore else - should always have one */ if (edge) + } else /* istanbul ignore else - should always have one */ if (edge) { out.push('Found: ' + explainEdge(edge, depth, color)) + } out.push('\nCould not resolve dependency:\n' + explainEdge(edge, depth, color)) diff --git a/lib/utils/format-bytes.js b/lib/utils/format-bytes.js index 87fb561aa..d7cf6d144 100644 --- a/lib/utils/format-bytes.js +++ b/lib/utils/format-bytes.js @@ -4,17 +4,24 @@ const formatBytes = (bytes, space = true) => { let spacer = '' - if (space) + if (space) { spacer = ' ' + } - if (bytes < 1000) // B + if (bytes < 1000) { + // B return `${bytes}${spacer}B` + } - if (bytes < 1000000) // kB + if (bytes < 1000000) { + // kB return `${(bytes / 1000).toFixed(1)}${spacer}kB` + } - if (bytes < 1000000000) // MB + if (bytes < 1000000000) { + // MB return `${(bytes / 1000000).toFixed(1)}${spacer}MB` + } return `${(bytes / 1000000000).toFixed(1)}${spacer}GB` } diff --git a/lib/utils/get-identity.js b/lib/utils/get-identity.js index e92a2c524..e77c2eea4 100644 --- a/lib/utils/get-identity.js +++ b/lib/utils/get-identity.js @@ -5,8 +5,9 @@ const needsAuthError = (msg) => module.exports = async (npm, opts = {}) => { const { registry } = opts - if (!registry) + if (!registry) { throw Object.assign(new Error('No registry specified.'), { code: 'ENOREGISTRY' }) + } // First, check if we have a user/pass-based auth const creds = npm.config.getCredentialsByURI(registry) @@ -22,9 +23,9 @@ module.exports = async (npm, opts = {}) => { }) const { username: usernameFromRegistry } = registryData // Retrieved username from registry; return it - if (usernameFromRegistry) + if (usernameFromRegistry) { return usernameFromRegistry - else { + } else { // Didn't get username from registry; bad token throw needsAuthError( 'Your auth token is no longer valid. Please login again.' diff --git a/lib/utils/get-project-scope.js b/lib/utils/get-project-scope.js index 3ce84d5bb..dc1b4deba 100644 --- a/lib/utils/get-project-scope.js +++ b/lib/utils/get-project-scope.js @@ -2,12 +2,14 @@ const { resolve } = require('path') module.exports = prefix => { try { const { name } = require(resolve(prefix, 'package.json')) - if (!name || typeof name !== 'string') + if (!name || typeof name !== 'string') { return '' + } const split = name.split('/') - if (split.length < 2) + if (split.length < 2) { return '' + } const scope = split[0] return /^@/.test(scope) ? scope : '' diff --git a/lib/utils/npm-usage.js b/lib/utils/npm-usage.js index d54c8ac54..b0c98b2ae 100644 --- a/lib/utils/npm-usage.js +++ b/lib/utils/npm-usage.js @@ -32,8 +32,9 @@ npm@${npm.version} ${dirname(dirname(__dirname))}` } const allCommands = async (npm) => { - if (npm.config.get('long')) + if (npm.config.get('long')) { return usages(npm) + } return ('\n ' + wrap(cmdList)) } @@ -45,9 +46,9 @@ const wrap = (arr) => { let l = 0 for (const c of arr.sort((a, b) => a < b ? -1 : 1)) { - if (out[l].length + c.length + 2 < line) + if (out[l].length + c.length + 2 < line) { out[l] += ', ' + c - else { + } else { out[l++] += ',' out[l] = c } diff --git a/lib/utils/open-url.js b/lib/utils/open-url.js index 331ca96fa..21368efe7 100644 --- a/lib/utils/open-url.js +++ b/lib/utils/open-url.js @@ -25,8 +25,9 @@ const open = async (npm, url, errMsg) => { } try { - if (!/^(https?|file):$/.test(new URL(url).protocol)) + if (!/^(https?|file):$/.test(new URL(url).protocol)) { throw new Error() + } } catch (_) { throw new Error('Invalid URL: ' + url) } @@ -35,10 +36,11 @@ const open = async (npm, url, errMsg) => { await new Promise((resolve, reject) => { opener(url, { command }, (err) => { if (err) { - if (err.code === 'ENOENT') + if (err.code === 'ENOENT') { printAlternateMsg() - else + } else { return reject(err) + } } return resolve() }) diff --git a/lib/utils/otplease.js b/lib/utils/otplease.js index ca271526c..0e32493f9 100644 --- a/lib/utils/otplease.js +++ b/lib/utils/otplease.js @@ -8,11 +8,11 @@ module.exports = otplease function otplease (opts, fn) { opts = { prompt, ...opts } return Promise.resolve().then(() => fn(opts)).catch(err => { - if (!isOtpError(err)) + if (!isOtpError(err)) { throw err - else if (!process.stdin.isTTY || !process.stdout.isTTY) + } else if (!process.stdin.isTTY || !process.stdout.isTTY) { throw err - else { + } else { return readUserInfo.otp(opts.prompt) .then(otp => fn({ ...opts, otp })) } diff --git a/lib/utils/queryable.js b/lib/utils/queryable.js index e10eba3b5..ceb06bdcc 100644 --- a/lib/utils/queryable.js +++ b/lib/utils/queryable.js @@ -19,10 +19,10 @@ const replaceAppendSymbols = str => { return [str] } -const parseKeys = (key) => { +const parseKeys = key => { const sqBracketItems = new Set() sqBracketItems.add(_append) - const parseSqBrackets = (str) => { + const parseSqBrackets = str => { const index = sqBracketsMatcher(str) // once we find square brackets, we recursively parse all these @@ -48,11 +48,7 @@ const parseKeys = (key) => { return [ ...parseSqBrackets(preSqBracketPortion), foundKey, - ...( - postSqBracketPortion - ? parseSqBrackets(postSqBracketPortion) - : [] - ), + ...(postSqBracketPortion ? parseSqBrackets(postSqBracketPortion) : []), ] } @@ -72,13 +68,14 @@ const parseKeys = (key) => { for (const k of sqBracketKeys) { // keys parsed from square brackets should just be added to list of // resulting keys as they might have dots as part of the key - if (sqBracketItems.has(k)) + if (sqBracketItems.has(k)) { res.push(k) - else { + } else { // splits the dot-sep property names and add them to the list of keys - for (const splitKey of k.split('.')) - /* eslint-disable-next-line no-new-wrappers */ - res.push(new String(splitKey)) + /* eslint-disable-next-line no-new-wrappers */ + for (const splitKey of k.split('.')) { + res.push(String(splitKey)) + } } } @@ -98,10 +95,9 @@ const getter = ({ data, key }) => { for (const k of keys) { // empty-bracket-shortcut-syntax is not supported on getter if (k === _append) { - throw Object.assign( - new Error('Empty brackets are not valid syntax for retrieving values.'), - { code: 'EINVALIDSYNTAX' } - ) + throw Object.assign(new Error('Empty brackets are not valid syntax for retrieving values.'), { + code: 'EINVALIDSYNTAX', + }) } // extra logic to take into account printing array, along with its @@ -118,8 +114,9 @@ const getter = ({ data, key }) => { } else { // if can't find any more values, it means it's just over // and there's nothing to return - if (!_data[k]) + if (!_data[k]) { return undefined + } // otherwise sets the next value _data = _data[k] @@ -130,8 +127,9 @@ const getter = ({ data, key }) => { // these are some legacy expectations from // the old API consumed by lib/view.js - if (Array.isArray(_data) && _data.length <= 1) + if (Array.isArray(_data) && _data.length <= 1) { _data = _data[0] + } return { [key]: _data, @@ -151,30 +149,32 @@ const setter = ({ data, key, value, force }) => { try { maybeIndex = Number(_key) } catch (err) {} - if (!Number.isNaN(maybeIndex)) + if (!Number.isNaN(maybeIndex)) { _key = maybeIndex + } // creates new array in case key is an index // and the array obj is not yet defined const keyIsAnArrayIndex = _key === maybeIndex || _key === _append const dataHasNoItems = !Object.keys(_data).length - if (keyIsAnArrayIndex && dataHasNoItems && !Array.isArray(_data)) + if (keyIsAnArrayIndex && dataHasNoItems && !Array.isArray(_data)) { _data = [] + } // converting from array to an object is also possible, in case the // user is using force mode, we should also convert existing arrays // to an empty object if the current _data is an array - if (force && Array.isArray(_data) && !keyIsAnArrayIndex) + if (force && Array.isArray(_data) && !keyIsAnArrayIndex) { _data = { ..._data } + } // the _append key is a special key that is used to represent // the empty-bracket notation, e.g: arr[] -> arr[arr.length] if (_key === _append) { if (!Array.isArray(_data)) { - throw Object.assign( - new Error(`Can't use append syntax in non-Array element`), - { code: 'ENOAPPEND' } - ) + throw Object.assign(new Error(`Can't use append syntax in non-Array element`), { + code: 'ENOAPPEND', + }) } _key = _data.length } @@ -182,23 +182,15 @@ const setter = ({ data, key, value, force }) => { // retrieves the next data object to recursively iterate on, // throws if trying to override a literal value or add props to an array const next = () => { - const haveContents = - !force && - _data[_key] != null && - value !== _delete - const shouldNotOverrideLiteralValue = - !(typeof _data[_key] === 'object') + const haveContents = !force && _data[_key] != null && value !== _delete + const shouldNotOverrideLiteralValue = !(typeof _data[_key] === 'object') // if the next obj to recurse is an array and the next key to be // appended to the resulting obj is not an array index, then it // should throw since we can't append arbitrary props to arrays const shouldNotAddPropsToArrays = - typeof keys[0] !== 'symbol' && - Array.isArray(_data[_key]) && - Number.isNaN(Number(keys[0])) + typeof keys[0] !== 'symbol' && Array.isArray(_data[_key]) && Number.isNaN(Number(keys[0])) - const overrideError = - haveContents && - shouldNotOverrideLiteralValue + const overrideError = haveContents && shouldNotOverrideLiteralValue if (overrideError) { throw Object.assign( new Error(`Property ${_key} already exists and is not an Array or Object.`), @@ -206,14 +198,11 @@ const setter = ({ data, key, value, force }) => { ) } - const addPropsToArrayError = - haveContents && - shouldNotAddPropsToArrays + const addPropsToArrayError = haveContents && shouldNotAddPropsToArrays if (addPropsToArrayError) { - throw Object.assign( - new Error(`Can't add property ${key} to an Array.`), - { code: 'ENOADDPROP' } - ) + throw Object.assign(new Error(`Can't add property ${key} to an Array.`), { + code: 'ENOADDPROP', + }) } return typeof _data[_key] === 'object' ? _data[_key] || {} : {} @@ -222,18 +211,20 @@ const setter = ({ data, key, value, force }) => { // sets items from the parsed array of keys as objects, recurses to // setKeys in case there are still items to be handled, otherwise it // just sets the original value set by the user - if (keys.length) + if (keys.length) { _data[_key] = setKeys(next(), keys.shift()) - else { + } else { // handles special deletion cases for obj props / array items if (value === _delete) { - if (Array.isArray(_data)) + if (Array.isArray(_data)) { _data.splice(_key, 1) - else + } else { delete _data[_key] - } else + } + } else { // finally, sets the value in its right place _data[_key] = value + } } return _data @@ -245,10 +236,9 @@ const setter = ({ data, key, value, force }) => { class Queryable { constructor (obj) { if (!obj || typeof obj !== 'object') { - throw Object.assign( - new Error('Queryable needs an object to query properties from.'), - { code: 'ENOQUERYABLEOBJ' } - ) + throw Object.assign(new Error('Queryable needs an object to query properties from.'), { + code: 'ENOQUERYABLEOBJ', + }) } this[_data] = obj @@ -258,28 +248,33 @@ class Queryable { // this ugly interface here is meant to be a compatibility layer // with the legacy API lib/view.js is consuming, if at some point // we refactor that command then we can revisit making this nicer - if (queries === '') + if (queries === '') { return { '': this[_data] } + } - const q = query => getter({ - data: this[_data], - key: query, - }) + const q = query => + getter({ + data: this[_data], + key: query, + }) if (Array.isArray(queries)) { let res = {} - for (const query of queries) + for (const query of queries) { res = { ...res, ...q(query) } + } return res - } else + } else { return q(queries) + } } // return the value for a single query if found, otherwise returns undefined get (query) { const obj = this.query(query) - if (obj) + if (obj) { return obj[query] + } } // creates objects along the way for the provided `query` parameter diff --git a/lib/utils/read-user-info.js b/lib/utils/read-user-info.js index e3c4a9fbe..993aa886f 100644 --- a/lib/utils/read-user-info.js +++ b/lib/utils/read-user-info.js @@ -23,16 +23,18 @@ function read (opts) { } function readOTP (msg = otpPrompt, otp, isRetry) { - if (isRetry && otp && /^[\d ]+$|^[A-Fa-f0-9]{64,64}$/.test(otp)) + if (isRetry && otp && /^[\d ]+$|^[A-Fa-f0-9]{64,64}$/.test(otp)) { return otp.replace(/\s+/g, '') + } return read({ prompt: msg, default: otp || '' }) .then((otp) => readOTP(msg, otp, true)) } function readPassword (msg = passwordPrompt, password, isRetry) { - if (isRetry && password) + if (isRetry && password) { return password + } return read({ prompt: msg, silent: true, default: password || '' }) .then((password) => readPassword(msg, password, true)) @@ -41,10 +43,11 @@ function readPassword (msg = passwordPrompt, password, isRetry) { function readUsername (msg = usernamePrompt, username, opts = {}, isRetry) { if (isRetry && username) { const error = userValidate.username(username) - if (error) + if (error) { opts.log && opts.log.warn(error.message) - else + } else { return Promise.resolve(username.trim()) + } } return read({ prompt: msg, default: username || '' }) @@ -54,10 +57,11 @@ function readUsername (msg = usernamePrompt, username, opts = {}, isRetry) { function readEmail (msg = emailPrompt, email, opts = {}, isRetry) { if (isRetry && email) { const error = userValidate.email(email) - if (error) + if (error) { opts.log && opts.log.warn(error.message) - else + } else { return email.trim() + } } return read({ prompt: msg, default: email || '' }) diff --git a/lib/utils/reify-finish.js b/lib/utils/reify-finish.js index a9ac4c61f..9b43abcb7 100644 --- a/lib/utils/reify-finish.js +++ b/lib/utils/reify-finish.js @@ -1,7 +1,7 @@ const reifyOutput = require('./reify-output.js') const ini = require('ini') const { writeFile } = require('fs').promises -const {resolve} = require('path') +const { resolve } = require('path') const reifyFinish = async (npm, arb) => { await saveBuiltinConfig(npm, arb) @@ -10,18 +10,21 @@ const reifyFinish = async (npm, arb) => { const saveBuiltinConfig = async (npm, arb) => { const { options: { global }, actualTree } = arb - if (!global) + if (!global) { return + } // if we are using a builtin config, and just installed npm as // a top-level global package, we have to preserve that config. const npmNode = actualTree.inventory.get('node_modules/npm') - if (!npmNode) + if (!npmNode) { return + } const builtinConf = npm.config.data.get('builtin') - if (builtinConf.loadError) + if (builtinConf.loadError) { return + } const content = ini.stringify(builtinConf.raw).trim() + '\n' await writeFile(resolve(npmNode.path, 'npmrc'), content) diff --git a/lib/utils/reify-output.js b/lib/utils/reify-output.js index bf3fa7fb2..7741b7220 100644 --- a/lib/utils/reify-output.js +++ b/lib/utils/reify-output.js @@ -92,14 +92,16 @@ const reifyOutput = (npm, arb) => { // to get the exitCode set appropriately. const printAuditReport = (npm, report) => { const res = getAuditReport(npm, report) - if (!res || !res.report) + if (!res || !res.report) { return + } npm.output(`\n${res.report}`) } const getAuditReport = (npm, report) => { - if (!report) + if (!report) { return + } // when in silent mode, we print nothing. the JSON output is // going to just JSON.stringify() the report object. @@ -115,8 +117,9 @@ const getAuditReport = (npm, report) => { ...npm.flatOptions, auditLevel, }) - if (npm.command === 'audit') + if (npm.command === 'audit') { process.exitCode = process.exitCode || res.exitCode + } return res } @@ -124,43 +127,52 @@ const packagesChangedMessage = (npm, { added, removed, changed, audited }) => { const msg = ['\n'] if (added === 0 && removed === 0 && changed === 0) { msg.push('up to date') - if (audited) + if (audited) { msg.push(', ') + } } else { - if (added) + if (added) { msg.push(`added ${added} package${added === 1 ? '' : 's'}`) + } if (removed) { - if (added) + if (added) { msg.push(', ') + } - if (added && !audited && !changed) + if (added && !audited && !changed) { msg.push('and ') + } msg.push(`removed ${removed} package${removed === 1 ? '' : 's'}`) } if (changed) { - if (added || removed) + if (added || removed) { msg.push(', ') + } - if (!audited && (added || removed)) + if (!audited && (added || removed)) { msg.push('and ') + } msg.push(`changed ${changed} package${changed === 1 ? '' : 's'}`) } - if (audited) + if (audited) { msg.push(', and ') + } } - if (audited) + if (audited) { msg.push(`audited ${audited} package${audited === 1 ? '' : 's'}`) + } msg.push(` in ${ms(Date.now() - npm.started)}`) npm.output(msg.join('')) } const packagesFundingMessage = (npm, { funding }) => { - if (!funding) + if (!funding) { return + } npm.output('') const pkg = funding === 1 ? 'package' : 'packages' diff --git a/lib/utils/replace-info.js b/lib/utils/replace-info.js index 7c7489bc1..e9d19ef5f 100644 --- a/lib/utils/replace-info.js +++ b/lib/utils/replace-info.js @@ -5,8 +5,9 @@ function replaceInfo (arg) { const isArray = Array.isArray(arg) const isString = str => typeof str === 'string' - if (!isArray && !isString(arg)) + if (!isArray && !isString(arg)) { return arg + } const testUrlAndReplace = str => { try { @@ -19,8 +20,9 @@ function replaceInfo (arg) { const args = isString(arg) ? arg.split(' ') : arg const info = args.map(a => { - if (isString(a) && a.indexOf(' ') > -1) + if (isString(a) && a.indexOf(' ') > -1) { return a.split(' ').map(testUrlAndReplace).join(' ') + } return testUrlAndReplace(a) }) diff --git a/lib/utils/setup-log.js b/lib/utils/setup-log.js index aaf7fa47e..05ca38c82 100644 --- a/lib/utils/setup-log.js +++ b/lib/utils/setup-log.js @@ -35,28 +35,32 @@ module.exports = (config) => { return warn(heading, ...args) } - if (config.get('timing') && config.get('loglevel') === 'notice') + if (config.get('timing') && config.get('loglevel') === 'notice') { log.level = 'timing' - else + } else { log.level = config.get('loglevel') + } log.heading = config.get('heading') || 'npm' - if (enableColorStderr) + if (enableColorStderr) { log.enableColor() - else + } else { log.disableColor() + } - if (config.get('unicode')) + if (config.get('unicode')) { log.enableUnicode() - else + } else { log.disableUnicode() + } // if it's more than error, don't show progress const quiet = log.levels[log.level] > log.levels.error - if (config.get('progress') && stderrNotDumb && !quiet) + if (config.get('progress') && stderrNotDumb && !quiet) { log.enableProgress() - else + } else { log.disableProgress() + } } diff --git a/lib/utils/split-package-names.js b/lib/utils/split-package-names.js index bb6e449ba..395c2517d 100644 --- a/lib/utils/split-package-names.js +++ b/lib/utils/split-package-names.js @@ -4,15 +4,17 @@ const splitPackageNames = (path) => { return path.split('/') // combine scoped parts .reduce((parts, part) => { - if (parts.length === 0) + if (parts.length === 0) { return [part] + } const lastPart = parts[parts.length - 1] // check if previous part is the first part of a scoped package - if (lastPart[0] === '@' && !lastPart.includes('/')) + if (lastPart[0] === '@' && !lastPart.includes('/')) { parts[parts.length - 1] += '/' + part - else + } else { parts.push(part) + } return parts }, []) diff --git a/lib/utils/tar.js b/lib/utils/tar.js index 0ff822370..26e7a98df 100644 --- a/lib/utils/tar.js +++ b/lib/utils/tar.js @@ -14,39 +14,58 @@ const logTar = (tarball, opts = {}) => { log.notice('', `${unicode ? '📦 ' : 'package:'} ${tarball.name}@${tarball.version}`) log.notice('=== Tarball Contents ===') if (tarball.files.length) { - log.notice('', columnify(tarball.files.map((f) => { - const bytes = formatBytes(f.size, false) - return (/^node_modules\//.test(f.path)) ? null - : { path: f.path, size: `${bytes}` } - }).filter(f => f), { - include: ['size', 'path'], - showHeaders: false, - })) + log.notice( + '', + columnify( + tarball.files + .map(f => { + const bytes = formatBytes(f.size, false) + return /^node_modules\//.test(f.path) ? null : { path: f.path, size: `${bytes}` } + }) + .filter(f => f), + { + include: ['size', 'path'], + showHeaders: false, + } + ) + ) } if (tarball.bundled.length) { log.notice('=== Bundled Dependencies ===') - tarball.bundled.forEach((name) => log.notice('', name)) + tarball.bundled.forEach(name => log.notice('', name)) } log.notice('=== Tarball Details ===') - log.notice('', columnify([ - { name: 'name:', value: tarball.name }, - { name: 'version:', value: tarball.version }, - tarball.filename && { name: 'filename:', value: tarball.filename }, - { name: 'package size:', value: formatBytes(tarball.size) }, - { name: 'unpacked size:', value: formatBytes(tarball.unpackedSize) }, - { name: 'shasum:', value: tarball.shasum }, - { - name: 'integrity:', - value: tarball.integrity.toString().substr(0, 20) + '[...]' + tarball.integrity.toString().substr(80), - }, - tarball.bundled.length && { name: 'bundled deps:', value: tarball.bundled.length }, - tarball.bundled.length && { name: 'bundled files:', value: tarball.entryCount - tarball.files.length }, - tarball.bundled.length && { name: 'own files:', value: tarball.files.length }, - { name: 'total files:', value: tarball.entryCount }, - ].filter((x) => x), { - include: ['name', 'value'], - showHeaders: false, - })) + log.notice( + '', + columnify( + [ + { name: 'name:', value: tarball.name }, + { name: 'version:', value: tarball.version }, + tarball.filename && { name: 'filename:', value: tarball.filename }, + { name: 'package size:', value: formatBytes(tarball.size) }, + { name: 'unpacked size:', value: formatBytes(tarball.unpackedSize) }, + { name: 'shasum:', value: tarball.shasum }, + { + name: 'integrity:', + value: + tarball.integrity.toString().substr(0, 20) + + '[...]' + + tarball.integrity.toString().substr(80), + }, + tarball.bundled.length && { name: 'bundled deps:', value: tarball.bundled.length }, + tarball.bundled.length && { + name: 'bundled files:', + value: tarball.entryCount - tarball.files.length, + }, + tarball.bundled.length && { name: 'own files:', value: tarball.files.length }, + { name: 'total files:', value: tarball.entryCount }, + ].filter(x => x), + { + include: ['name', 'value'], + showHeaders: false, + } + ) + ) log.notice('', '') } @@ -81,7 +100,7 @@ const getContents = async (manifest, tarball) => { const comparator = ({ path: a }, { path: b }) => localeCompare(a, b) - const isUpper = (str) => { + const isUpper = str => { const ch = str.charAt(0) return ch === ch.toUpperCase() } diff --git a/lib/utils/update-notifier.js b/lib/utils/update-notifier.js index 14c4fac0d..2b45d54c8 100644 --- a/lib/utils/update-notifier.js +++ b/lib/utils/update-notifier.js @@ -37,8 +37,9 @@ const updateNotifier = async (npm, spec = 'latest') => { // never check for updates in CI, when updating npm already, or opted out if (!npm.config.get('update-notifier') || isGlobalNpmUpdate(npm) || - ciDetect()) + ciDetect()) { return null + } // if we're on a prerelease train, then updates are coming fast // check for a new one daily. otherwise, weekly. @@ -46,15 +47,17 @@ const updateNotifier = async (npm, spec = 'latest') => { const current = semver.parse(version) // if we're on a beta train, always get the next beta - if (current.prerelease.length) + if (current.prerelease.length) { spec = `^${version}` + } // while on a beta train, get updates daily const duration = spec !== 'latest' ? DAILY : WEEKLY // if we've already checked within the specified duration, don't check again - if (!(await checkTimeout(npm, duration))) + if (!(await checkTimeout(npm, duration))) { return null + } // if they're currently using a prerelease, nudge to the next prerelease // otherwise, nudge to latest. @@ -67,8 +70,9 @@ const updateNotifier = async (npm, spec = 'latest') => { }).catch(() => null) // if pacote failed, give up - if (!mani) + if (!mani) { return null + } const latest = mani.version @@ -76,12 +80,14 @@ const updateNotifier = async (npm, spec = 'latest') => { // and should get the updates from that release train. // Note that this isn't another http request over the network, because // the packument will be cached by pacote from previous request. - if (semver.gt(version, latest) && spec === 'latest') + if (semver.gt(version, latest) && spec === 'latest') { return updateNotifier(npm, `^${version}`) + } // if we already have something >= the desired spec, then we're done - if (semver.gte(version, latest)) + if (semver.gte(version, latest)) { return null + } // ok! notify the user about this update they should get. // The message is saved for printing at process exit so it will not get diff --git a/lib/utils/usage.js b/lib/utils/usage.js index 5f4eca73e..e23e50c51 100644 --- a/lib/utils/usage.js +++ b/lib/utils/usage.js @@ -3,13 +3,15 @@ const aliases = require('../utils/cmd-list').aliases module.exports = function usage (cmd, txt, opt) { const post = Object.keys(aliases).reduce(function (p, c) { var val = aliases[c] - if (val !== cmd) + if (val !== cmd) { return p + } return p.concat(c) }, []) - if (opt || post.length > 0) + if (opt || post.length > 0) { txt += '\n\n' + } if (post.length === 1) { txt += 'alias: ' @@ -20,8 +22,9 @@ module.exports = function usage (cmd, txt, opt) { } if (opt) { - if (post.length > 0) + if (post.length > 0) { txt += '\n' + } txt += 'common options: ' + opt } diff --git a/lib/workspaces/get-workspaces.js b/lib/workspaces/get-workspaces.js index 3eb8e4865..a59b5a6c5 100644 --- a/lib/workspaces/get-workspaces.js +++ b/lib/workspaces/get-workspaces.js @@ -10,18 +10,21 @@ const getWorkspaces = async (filters, { path, includeWorkspaceRoot }) => { const pkg = await rpj(resolve(path, 'package.json')) const workspaces = await mapWorkspaces({ cwd: path, pkg }) let res = new Map() - if (includeWorkspaceRoot) + if (includeWorkspaceRoot) { res.set(pkg.name, path) + } - if (!filters.length) + if (!filters.length) { res = new Map([...res, ...workspaces]) + } for (const filterArg of filters) { for (const [workspaceName, workspacePath] of workspaces.entries()) { if (filterArg === workspaceName || resolve(path, filterArg) === workspacePath - || minimatch(workspacePath, `${resolve(path, filterArg)}/*`)) + || minimatch(workspacePath, `${resolve(path, filterArg)}/*`)) { res.set(workspaceName, workspacePath) + } } } |