diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index aa1b42f7bad7f..bb7d8887bb11a 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -288,8 +288,6 @@ graph LR; cidr-regex-->ip-regex; cli-columns-->string-width; cli-columns-->strip-ansi; - cli-table3-->colors-colors["@colors/colors"]; - cli-table3-->string-width; color-convert-->color-name; columnify-->strip-ansi; columnify-->wcwidth; diff --git a/docs/lib/content/commands/npm-doctor.md b/docs/lib/content/commands/npm-doctor.md index d43164eb3a5d3..b5c8126b272c0 100644 --- a/docs/lib/content/commands/npm-doctor.md +++ b/docs/lib/content/commands/npm-doctor.md @@ -34,20 +34,21 @@ there are any recommended changes, it will display them. By default npm runs all of these checks. You can limit what checks are ran by specifying them as extra arguments. -#### `npm ping` +#### `Connecting to the registry` By default, npm installs from the primary npm registry, -`registry.npmjs.org`. `npm doctor` hits a special ping endpoint within the -registry. This can also be checked with `npm ping`. If this check fails, -you may be using a proxy that needs to be configured, or may need to talk -to your IT staff to get access over HTTPS to `registry.npmjs.org`. +`registry.npmjs.org`. `npm doctor` hits a special connection testing +endpoint within the registry. This can also be checked with `npm ping`. +If this check fails, you may be using a proxy that needs to be +configured, or may need to talk to your IT staff to get access over +HTTPS to `registry.npmjs.org`. This check is done against whichever registry you've configured (you can see what that is by running `npm config get registry`), and if you're using a private registry that doesn't support the `/whoami` endpoint supported by the primary registry, this check may fail. -#### `npm -v` +#### `Checking npm version` While Node.js may come bundled with a particular version of npm, it's the policy of the CLI team that we recommend all users run `npm@latest` if they @@ -57,7 +58,7 @@ support releases typically only receive critical security and regression fixes. The team believes that the latest tested version of npm is almost always likely to be the most functional and defect-free version of npm. -#### `node -v` +#### `Checking node version` For most users, in most circumstances, the best version of Node will be the latest long-term support (LTS) release. Those of you who want access to new @@ -66,7 +67,7 @@ be running a newer version, and some may be required to run an older version of Node because of enterprise change control policies. That's OK! But in general, the npm team recommends that most users run Node.js LTS. -#### `npm config get registry` +#### `Checking configured npm registry` You may be installing from private package registries for your project or company. That's great! Others may be following tutorials or StackOverflow @@ -75,7 +76,7 @@ Sometimes, this may entail changing the registry you're pointing at. This part of `npm doctor` just lets you, and maybe whoever's helping you with support, know that you're not using the default registry. -#### `which git` +#### `Checking for git executable in PATH` While it's documented in the README, it may not be obvious that npm needs Git installed to do many of the things that it does. Also, in some cases diff --git a/docs/lib/content/commands/npm-profile.md b/docs/lib/content/commands/npm-profile.md index 0c93cef0d60da..ba6613393d736 100644 --- a/docs/lib/content/commands/npm-profile.md +++ b/docs/lib/content/commands/npm-profile.md @@ -17,28 +17,17 @@ support this interface. * `npm profile get []`: Display all of the properties of your profile, or one or more specific properties. It looks like: -```bash -+-----------------+---------------------------+ -| name | example | -+-----------------+---------------------------+ -| email | me@example.com (verified) | -+-----------------+---------------------------+ -| two factor auth | auth-and-writes | -+-----------------+---------------------------+ -| fullname | Example User | -+-----------------+---------------------------+ -| homepage | | -+-----------------+---------------------------+ -| freenode | | -+-----------------+---------------------------+ -| twitter | | -+-----------------+---------------------------+ -| github | | -+-----------------+---------------------------+ -| created | 2015-02-26T01:38:35.892Z | -+-----------------+---------------------------+ -| updated | 2017-10-02T21:29:45.922Z | -+-----------------+---------------------------+ +``` +name: example +email: e@example.com (verified) +two-factor auth: auth-and-writes +fullname: Example User +homepage: +freenode: +twitter: +github: +created: 2015-02-26T01:38:35.892Z +updated: 2017-10-02T21:29:45.922Z ``` * `npm profile set `: Set the value of a profile diff --git a/docs/lib/content/commands/npm-token.md b/docs/lib/content/commands/npm-token.md index 81624ba6952f8..d4d9d6bd83cce 100644 --- a/docs/lib/content/commands/npm-token.md +++ b/docs/lib/content/commands/npm-token.md @@ -16,24 +16,14 @@ This lets you list, create and revoke authentication tokens. Shows a table of all active authentication tokens. You can request this as JSON with `--json` or tab-separated values with `--parseable`. -```bash -+--------+---------+------------+----------+----------------+ -| id | token | created | read-only | CIDR whitelist | -+--------+---------+------------+----------+----------------+ -| 7f3134 | 1fa9ba… | 2017-10-02 | yes | | -+--------+---------+------------+----------+----------------+ -| c03241 | af7aef… | 2017-10-02 | no | 192.168.0.1/24 | -+--------+---------+------------+----------+----------------+ -| e0cf92 | 3a436a… | 2017-10-02 | no | | -+--------+---------+------------+----------+----------------+ -| 63eb9d | 74ef35… | 2017-09-28 | no | | -+--------+---------+------------+----------+----------------+ -| 2daaa8 | cbad5f… | 2017-09-26 | no | | -+--------+---------+------------+----------+----------------+ -| 68c2fe | 127e51… | 2017-09-23 | no | | -+--------+---------+------------+----------+----------------+ -| 6334e1 | 1dadd1… | 2017-09-23 | no | | -+--------+---------+------------+----------+----------------+ +``` +Read only token npm_1f… with id 7f3134 created 2017-10-21 + +Publish token npm_af… with id c03241 created 2017-10-02 +with IP Whitelist: 192.168.0.1/24 + +Publish token npm_… with id e0cf92 created 2017-10-02 + ``` * `npm token create [--read-only] [--cidr=]`: @@ -49,16 +39,8 @@ This lets you list, create and revoke authentication tokens. website](https://docs.npmjs.com/creating-and-viewing-access-tokens) for more information on generating automation tokens. -```bash -+----------------+--------------------------------------+ -| token | a73c9572-f1b9-8983-983d-ba3ac3cc913d | -+----------------+--------------------------------------+ -| cidr_whitelist | | -+----------------+--------------------------------------+ -| readonly | false | -+----------------+--------------------------------------+ -| created | 2017-10-02T07:52:24.838Z | -+----------------+--------------------------------------+ +``` +Created publish token a73c9572-f1b9-8983-983d-ba3ac3cc913d ``` * `npm token revoke `: diff --git a/lib/commands/doctor.js b/lib/commands/doctor.js index f74fe2ecbcc7e..3048a123d6eb1 100644 --- a/lib/commands/doctor.js +++ b/lib/commands/doctor.js @@ -1,7 +1,6 @@ const cacache = require('cacache') const fs = require('fs') const fetch = require('make-fetch-happen') -const Table = require('cli-table3') const which = require('which') const pacote = require('pacote') const { resolve } = require('path') @@ -34,57 +33,59 @@ const maskLabel = mask => { const subcommands = [ { - groups: ['ping', 'registry'], - title: 'npm ping', + // Ping is left in as a legacy command but is listed as "connection" to + // make more sense to more people + groups: ['connection', 'ping', 'registry'], + title: 'Connecting to the registry', cmd: 'checkPing', }, { groups: ['versions'], - title: 'npm -v', + title: 'Checking npm version', cmd: 'getLatestNpmVersion', }, { groups: ['versions'], - title: 'node -v', + title: 'Checking node version', cmd: 'getLatestNodejsVersion', }, { groups: ['registry'], - title: 'npm config get registry', + title: 'Checking configured npm registry', cmd: 'checkNpmRegistry', }, { groups: ['environment'], - title: 'git executable in PATH', + title: 'Checking for git executable in PATH', cmd: 'getGitPath', }, { groups: ['environment'], - title: 'global bin folder in PATH', + title: 'Checking for global bin folder in PATH', cmd: 'getBinPath', }, { groups: ['permissions', 'cache'], - title: 'Perms check on cached files', + title: 'Checking permissions on cached files (this may take awhile)', cmd: 'checkCachePermission', windows: false, }, { groups: ['permissions'], - title: 'Perms check on local node_modules', + title: 'Checking permissions on local node_modules (this may take awhile)', cmd: 'checkLocalModulesPermission', windows: false, }, { groups: ['permissions'], - title: 'Perms check on global node_modules', + title: 'Checking permissions on global node_modules (this may take awhile)', cmd: 'checkGlobalModulesPermission', windows: false, }, { groups: ['permissions'], - title: 'Perms check on local bin folder', + title: 'Checking permissions on local bin folder', cmd: 'checkLocalBinPermission', windows: false, }, { groups: ['permissions'], - title: 'Perms check on global bin folder', + title: 'Checking permissions on global bin folder', cmd: 'checkGlobalBinPermission', windows: false, }, { groups: ['cache'], - title: 'Verify cache contents', + title: 'Verifying cache contents (this may take awhile)', cmd: 'verifyCachedFiles', windows: false, }, @@ -104,43 +105,28 @@ class Doctor extends BaseCommand { static params = ['registry'] static ignoreImplicitWorkspace = false static usage = [`[${subcommands.flatMap(s => s.groups) - .filter((value, index, self) => self.indexOf(value) === index) + .filter((value, index, self) => self.indexOf(value) === index && value !== 'ping') .join('] [')}]`] static subcommands = subcommands - // minimum width of check column, enough for the word `Check` - #checkWidth = 5 - async exec (args) { log.info('doctor', 'Running checkup') let allOk = true const actions = this.actions(args) - this.#checkWidth = actions.reduce((length, item) => - Math.max(item.title.length, length), this.#checkWidth) - if (!this.npm.silent) { - this.output(['Check', 'Value', 'Recommendation/Notes'].map(h => this.npm.chalk.underline(h))) - } - // Do the actual work + const chalk = this.npm.chalk for (const { title, cmd } of actions) { - const item = [title] + this.output(title) + // TODO when we have an in progress indicator that could go here + let result try { - item.push(true, await this[cmd]()) + result = await this[cmd]() + this.output(`${chalk.green('Ok')}${result ? `\n${result}` : ''}\n`) } catch (err) { - item.push(false, err) - } - if (!item[1]) { allOk = false - item[0] = this.npm.chalk.red(item[0]) - item[1] = this.npm.chalk.red('not ok') - item[2] = this.npm.chalk.cyan(String(item[2])) - } else { - item[1] = this.npm.chalk.green('ok') - } - if (!this.npm.silent) { - this.output(item) + this.output(`${chalk.red('Not ok')}\n${chalk.cyan(err)}\n`) } } @@ -343,38 +329,11 @@ class Doctor extends BaseCommand { } } - output (row) { - const t = new Table({ - chars: { - top: '', - 'top-mid': '', - 'top-left': '', - 'top-right': '', - bottom: '', - 'bottom-mid': '', - 'bottom-left': '', - 'bottom-right': '', - left: '', - 'left-mid': '', - mid: '', - 'mid-mid': '', - right: '', - 'right-mid': '', - middle: ' ', - }, - style: { - 'padding-left': 0, - 'padding-right': 0, - // setting border here is not necessary visually since we've already - // zeroed out all the chars above, but without it cli-table3 will wrap - // some of the separator spaces with ansi codes which show up in - // snapshots. - border: 0, - }, - colWidths: [this.#checkWidth, 6], - }) - t.push(row) - output.standard(t.toString()) + output (...args) { + // TODO display layer should do this + if (!this.npm.silent) { + output.standard(...args) + } } actions (params) { diff --git a/lib/commands/hook.js b/lib/commands/hook.js index 5e6b593cccfd6..7ec95e079d660 100644 --- a/lib/commands/hook.js +++ b/lib/commands/hook.js @@ -1,7 +1,6 @@ const hookApi = require('libnpmhook') const otplease = require('../utils/otplease.js') const relativeDate = require('tiny-relative-date') -const Table = require('cli-table3') const { output } = require('proc-log') const BaseCommand = require('../base-command.js') @@ -52,6 +51,7 @@ class Hook extends BaseCommand { async ls (pkg, opts) { const hooks = await hookApi.ls({ ...opts, package: pkg }) + if (opts.json) { output.standard(JSON.stringify(hooks, null, 2)) } else if (opts.parseable) { @@ -62,32 +62,18 @@ class Hook extends BaseCommand { } else if (!hooks.length) { output.standard("You don't have any hooks configured yet.") } else if (!this.npm.silent) { - if (hooks.length === 1) { - output.standard('You have one hook configured.') - } else { - output.standard(`You have ${hooks.length} hooks configured.`) - } + output.standard(`You have ${hooks.length} hook${hooks.length !== 1 ? 's' : ''} configured.`) - const table = new Table({ head: ['id', 'target', 'endpoint'] }) - hooks.forEach((hook) => { - table.push([ - { rowSpan: 2, content: hook.id }, - this.hookName(hook), - hook.endpoint, - ]) + for (const hook of hooks) { + output.standard(`Hook ${hook.id}: ${this.hookName(hook)}`) + output.standard(`Endpoint: ${hook.endpoint}`) if (hook.last_delivery) { - table.push([ - { - colSpan: 1, - content: `triggered ${relativeDate(hook.last_delivery)}`, - }, - hook.response_code, - ]) + /* eslint-disable-next-line max-len */ + output.standard(`Triggered ${relativeDate(hook.last_delivery)}, response code was "${hook.response_code}"\n`) } else { - table.push([{ colSpan: 2, content: 'never triggered' }]) + output.standard('Never triggered\n') } - }) - output.standard(table.toString()) + } } } @@ -116,11 +102,7 @@ class Hook extends BaseCommand { } hookName (hook) { - let target = hook.name - if (hook.type === 'owner') { - target = '~' + target - } - return target + return `${hook.type === 'owner' ? '~' : ''}${hook.name}` } } module.exports = Hook diff --git a/lib/commands/org.js b/lib/commands/org.js index 8881ded70f638..f1e5b0e09c62c 100644 --- a/lib/commands/org.js +++ b/lib/commands/org.js @@ -1,6 +1,5 @@ const liborg = require('libnpmorg') const otplease = require('../utils/otplease.js') -const Table = require('cli-table3') const BaseCommand = require('../base-command.js') const { output } = require('proc-log') @@ -143,13 +142,10 @@ class Org extends BaseCommand { output.standard([u, roster[u]].join('\t')) }) } else if (!this.npm.silent) { - const table = new Table({ head: ['user', 'role'] }) - Object.keys(roster) - .sort() - .forEach(u => { - table.push([u, roster[u]]) - }) - output.standard(table.toString()) + const chalk = this.npm.chalk + for (const u of Object.keys(roster).sort()) { + output.standard(`${u} - ${chalk.cyan(roster[u])}`) + } } } } diff --git a/lib/commands/profile.js b/lib/commands/profile.js index 98a8dcd050ee9..8bb19e69fd484 100644 --- a/lib/commands/profile.js +++ b/lib/commands/profile.js @@ -3,7 +3,6 @@ const { URL } = require('url') const { log, output } = require('proc-log') const npmProfile = require('npm-profile') const qrcodeTerminal = require('qrcode-terminal') -const Table = require('cli-table3') const otplease = require('../utils/otplease.js') const readUserInfo = require('../utils/read-user-info.js') @@ -153,12 +152,9 @@ class Profile extends BaseCommand { } } } else { - const table = new Table() - for (const key of Object.keys(cleaned)) { - table.push({ [this.npm.chalk.bold(key)]: cleaned[key] }) + for (const [key, value] of Object.entries(cleaned)) { + output.standard(`${key}: ${value}`) } - - output.standard(table.toString()) } } } diff --git a/lib/commands/token.js b/lib/commands/token.js index 991112d1bc1ba..70ff0a332b18a 100644 --- a/lib/commands/token.js +++ b/lib/commands/token.js @@ -1,4 +1,3 @@ -const Table = require('cli-table3') const { log, output } = require('proc-log') const profile = require('npm-profile') @@ -34,10 +33,10 @@ class Token extends BaseCommand { case 'list': case 'ls': return this.list() + case 'rm': case 'delete': case 'revoke': case 'remove': - case 'rm': return this.rm(args.slice(1)) case 'create': return this.create(args.slice(1)) @@ -47,13 +46,15 @@ class Token extends BaseCommand { } async list () { - const conf = this.config() + const json = this.npm.config.get('json') + const parseable = this.npm.config.get('parseable') log.info('token', 'getting list') - const tokens = await profile.listTokens(conf) - if (conf.json) { + const tokens = await profile.listTokens(this.npm.flatOptions) + if (json) { output.standard(JSON.stringify(tokens, null, 2)) return - } else if (conf.parseable) { + } + if (parseable) { output.standard(['key', 'token', 'created', 'readonly', 'CIDR whitelist'].join('\t')) tokens.forEach(token => { output.standard( @@ -69,21 +70,17 @@ class Token extends BaseCommand { return } this.generateTokenIds(tokens, 6) - 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 => { - table.push([ - token.id, - token.token + '…', - String(token.created).slice(0, 10), - token.readonly ? 'yes' : 'no', - token.cidr_whitelist ? token.cidr_whitelist.join(', ') : '', - ]) - }) - output.standard(table.toString()) + const chalk = this.npm.chalk + for (const token of tokens) { + const level = token.readonly ? 'Read only token' : 'Publish token' + const created = String(token.created).slice(0, 10) + /* eslint-disable-next-line max-len */ + output.standard(`${chalk.blue(level)} ${token.token}… with id ${chalk.cyan(token.id)} created ${created}`) + if (token.cidr_whitelist) { + output.standard(`with IP whitelist: ${chalk.green(token.cidr_whitelist.join(','))}`) + } + output.standard() + } } async rm (args) { @@ -91,10 +88,12 @@ class Token extends BaseCommand { throw this.usageError('`` argument is required.') } - const conf = this.config() + const json = this.npm.config.get('json') + const parseable = this.npm.config.get('parseable') const toRemove = [] + const opts = { ...this.npm.flatOptions } log.info('token', `removing ${toRemove.length} tokens`) - const tokens = await profile.listTokens(conf) + const tokens = await profile.listTokens(opts) args.forEach(id => { const matches = tokens.filter(token => token.key.indexOf(id) === 0) if (matches.length === 1) { @@ -115,12 +114,12 @@ class Token extends BaseCommand { }) await Promise.all( toRemove.map(key => { - return otplease(this.npm, conf, c => profile.removeToken(key, c)) + return otplease(this.npm, opts, c => profile.removeToken(key, c)) }) ) - if (conf.json) { + if (json) { output.standard(JSON.stringify(toRemove)) - } else if (conf.parseable) { + } else if (parseable) { output.standard(toRemove.join('\t')) } else { output.standard('Removed ' + toRemove.length + ' token' + (toRemove.length !== 1 ? 's' : '')) @@ -128,61 +127,34 @@ class Token extends BaseCommand { } async create (args) { - const conf = this.config() - const cidr = conf.cidr - const readonly = conf.readOnly + const json = this.npm.config.get('json') + const parseable = this.npm.config.get('parseable') + const cidr = this.npm.config.get('cidr') + const readonly = this.npm.config.get('read-only') - const password = await readUserInfo.password() const validCIDR = await this.validateCIDRList(cidr) + const password = await readUserInfo.password() log.info('token', 'creating') const result = await otplease( this.npm, - conf, + { ...this.npm.flatOptions }, c => profile.createToken(password, readonly, validCIDR, c) ) delete result.key delete result.updated - if (conf.json) { + if (json) { output.standard(JSON.stringify(result)) - } else if (conf.parseable) { + } else if (parseable) { Object.keys(result).forEach(k => output.standard(k + '\t' + result[k])) } else { - const table = new Table() - for (const k of Object.keys(result)) { - table.push({ [this.npm.chalk.bold(k)]: String(result[k]) }) - } - output.standard(table.toString()) - } - } - - config () { - const conf = { ...this.npm.flatOptions } - const creds = this.npm.config.getCredentialsByURI(conf.registry) - if (creds.token) { - conf.auth = { token: creds.token } - } else if (creds.username) { - conf.auth = { - basic: { - username: creds.username, - password: creds.password, - }, + const chalk = this.npm.chalk + // Identical to list + const level = result.readonly ? 'read only' : 'publish' + output.standard(`Created ${chalk.blue(level)} token ${result.token}`) + if (result.cidr_whitelist?.length) { + output.standard(`with IP whitelist: ${chalk.green(result.cidr_whitelist.join(','))}`) } - } else if (creds.auth) { - const auth = Buffer.from(creds.auth, 'base64').toString().split(':', 2) - conf.auth = { - basic: { - username: auth[0], - password: auth[1], - }, - } - } else { - conf.auth = {} - } - - if (conf.otp) { - conf.auth.otp = conf.otp } - return conf } invalidCIDRError (msg) { @@ -190,7 +162,6 @@ class Token extends BaseCommand { } generateTokenIds (tokens, minLength) { - const byId = {} for (const token of tokens) { token.id = token.key for (let ii = minLength; ii < token.key.length; ++ii) { @@ -202,9 +173,7 @@ class Token extends BaseCommand { break } } - byId[token.id] = token } - return byId } async validateCIDRList (cidrs) { @@ -214,12 +183,12 @@ class Token extends BaseCommand { for (const cidr of list) { if (isCidrV6(cidr)) { throw this.invalidCIDRError( - 'CIDR whitelist can only contain IPv4 addresses, ' + cidr + ' is IPv6' + `CIDR whitelist can only contain IPv4 addresses${cidr} is IPv6` ) } if (!isCidrV4(cidr)) { - throw this.invalidCIDRError('CIDR whitelist contains invalid CIDR entry: ' + cidr) + throw this.invalidCIDRError(`CIDR whitelist contains invalid CIDR entry: ${cidr}`) } } return list diff --git a/lib/utils/reify-output.js b/lib/utils/reify-output.js index 40f1722f246e9..a858a546c4010 100644 --- a/lib/utils/reify-output.js +++ b/lib/utils/reify-output.js @@ -15,7 +15,6 @@ const ms = require('ms') const npmAuditReport = require('npm-audit-report') const { readTree: getFundingInfo } = require('libnpmfund') const auditError = require('./audit-error.js') -const Table = require('cli-table3') // TODO: output JSON if flatOptions.json is true const reifyOutput = (npm, arb) => { @@ -42,51 +41,31 @@ const reifyOutput = (npm, arb) => { } if (diff) { - let diffTable - if (npm.config.get('dry-run') || npm.config.get('long')) { - diffTable = new Table({ - chars: { - top: '', - 'top-mid': '', - 'top-left': '', - 'top-right': '', - bottom: '', - 'bottom-mid': '', - 'bottom-left': '', - 'bottom-right': '', - left: '', - 'left-mid': '', - mid: '', - 'mid-mid': '', - right: '', - 'right-mid': '', - middle: ' ', - }, - style: { - 'padding-left': 0, - 'padding-right': 0, - border: 0, - }, - }) - } + const showDiff = npm.config.get('dry-run') || npm.config.get('long') + const chalk = npm.chalk depth({ tree: diff, visit: d => { switch (d.action) { case 'REMOVE': - diffTable?.push(['remove', d.actual.name, d.actual.package.version]) + if (showDiff) { + /* eslint-disable-next-line max-len */ + output.standard(`${chalk.blue('remove')} ${d.actual.name} ${d.actual.package.version}`) + } summary.removed++ break case 'ADD': - diffTable?.push(['add', d.ideal.name, d.ideal.package.version]) + if (showDiff) { + output.standard(`${chalk.green('add')} ${d.ideal.name} ${d.ideal.package.version}`) + } actualTree.inventory.has(d.ideal) && summary.added++ break case 'CHANGE': - diffTable?.push(['change', - d.actual.name, - d.actual.package.version + ' -> ' + d.ideal.package.version, - ]) + if (showDiff) { + /* eslint-disable-next-line max-len */ + output.standard(`${chalk.cyan('change')} ${d.actual.name} ${d.actual.package.version} => ${d.ideal.package.version}`) + } summary.changed++ break default: @@ -97,10 +76,6 @@ const reifyOutput = (npm, arb) => { }, getChildren: d => d.children, }) - - if (diffTable) { - output.standard('\n' + diffTable.toString()) - } } if (npm.flatOptions.fund) { diff --git a/mock-registry/lib/index.js b/mock-registry/lib/index.js index 8664ac56fbefb..d98cb055a1713 100644 --- a/mock-registry/lib/index.js +++ b/mock-registry/lib/index.js @@ -334,6 +334,31 @@ class MockRegistry { this.nock = nock } + getTokens (tokens) { + return this.nock.get('/-/npm/v1/tokens') + .reply(200, { + objects: tokens, + urls: {}, + total: tokens.length, + userHasOldFormatToken: false, + }) + } + + createToken ({ password, readonly = false, cidr = [] }) { + return this.nock.post('/-/npm/v1/tokens', { + password, + readonly, + cidr_whitelist: cidr, + }).reply(200, { + key: 'n3wk3y', + token: 'n3wt0k3n', + created: new Date(), + updated: new Date(), + readonly, + cidr_whitelist: cidr, + }) + } + async package ({ manifest, times = 1, query, tarballs }) { let nock = this.nock const spec = npa(manifest.name) diff --git a/node_modules/.gitignore b/node_modules/.gitignore index beddaa3541d3e..f12013c0f8d76 100644 --- a/node_modules/.gitignore +++ b/node_modules/.gitignore @@ -3,9 +3,6 @@ /* !/.gitignore # Allow all bundled deps -!/@colors/ -/@colors/* -!/@colors/colors !/@isaacs/ /@isaacs/* !/@isaacs/cliui @@ -69,7 +66,6 @@ !/cidr-regex !/clean-stack !/cli-columns -!/cli-table3 !/clone !/cmd-shim !/color-convert diff --git a/node_modules/@colors/colors/LICENSE b/node_modules/@colors/colors/LICENSE deleted file mode 100644 index 6b86056199d2a..0000000000000 --- a/node_modules/@colors/colors/LICENSE +++ /dev/null @@ -1,26 +0,0 @@ -MIT License - -Original Library - - Copyright (c) Marak Squires - -Additional Functionality - - Copyright (c) Sindre Sorhus (sindresorhus.com) - - Copyright (c) DABH (https://github.com/DABH) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/node_modules/@colors/colors/examples/normal-usage.js b/node_modules/@colors/colors/examples/normal-usage.js deleted file mode 100644 index a4bfe7b7be633..0000000000000 --- a/node_modules/@colors/colors/examples/normal-usage.js +++ /dev/null @@ -1,83 +0,0 @@ -var colors = require('../lib/index'); - -console.log('First some yellow text'.yellow); - -console.log('Underline that text'.yellow.underline); - -console.log('Make it bold and red'.red.bold); - -console.log(('Double Raindows All Day Long').rainbow); - -console.log('Drop the bass'.trap); - -console.log('DROP THE RAINBOW BASS'.trap.rainbow); - -// styles not widely supported -console.log('Chains are also cool.'.bold.italic.underline.red); - -// styles not widely supported -console.log('So '.green + 'are'.underline + ' ' + 'inverse'.inverse - + ' styles! '.yellow.bold); -console.log('Zebras are so fun!'.zebra); - -// -// Remark: .strikethrough may not work with Mac OS Terminal App -// -console.log('This is ' + 'not'.strikethrough + ' fun.'); - -console.log('Background color attack!'.black.bgWhite); -console.log('Use random styles on everything!'.random); -console.log('America, Heck Yeah!'.america); - -// eslint-disable-next-line max-len -console.log('Blindingly '.brightCyan + 'bright? '.brightRed + 'Why '.brightYellow + 'not?!'.brightGreen); - -console.log('Setting themes is useful'); - -// -// Custom themes -// -console.log('Generic logging theme as JSON'.green.bold.underline); -// Load theme with JSON literal -colors.setTheme({ - silly: 'rainbow', - input: 'grey', - verbose: 'cyan', - prompt: 'grey', - info: 'green', - data: 'grey', - help: 'cyan', - warn: 'yellow', - debug: 'blue', - error: 'red', -}); - -// outputs red text -console.log('this is an error'.error); - -// outputs yellow text -console.log('this is a warning'.warn); - -// outputs grey text -console.log('this is an input'.input); - -console.log('Generic logging theme as file'.green.bold.underline); - -// Load a theme from file -try { - colors.setTheme(require(__dirname + '/../themes/generic-logging.js')); -} catch (err) { - console.log(err); -} - -// outputs red text -console.log('this is an error'.error); - -// outputs yellow text -console.log('this is a warning'.warn); - -// outputs grey text -console.log('this is an input'.input); - -// console.log("Don't summon".zalgo) - diff --git a/node_modules/@colors/colors/examples/safe-string.js b/node_modules/@colors/colors/examples/safe-string.js deleted file mode 100644 index fc664745705f3..0000000000000 --- a/node_modules/@colors/colors/examples/safe-string.js +++ /dev/null @@ -1,80 +0,0 @@ -var colors = require('../safe'); - -console.log(colors.yellow('First some yellow text')); - -console.log(colors.yellow.underline('Underline that text')); - -console.log(colors.red.bold('Make it bold and red')); - -console.log(colors.rainbow('Double Raindows All Day Long')); - -console.log(colors.trap('Drop the bass')); - -console.log(colors.rainbow(colors.trap('DROP THE RAINBOW BASS'))); - -// styles not widely supported -console.log(colors.bold.italic.underline.red('Chains are also cool.')); - -// styles not widely supported -console.log(colors.green('So ') + colors.underline('are') + ' ' - + colors.inverse('inverse') + colors.yellow.bold(' styles! ')); - -console.log(colors.zebra('Zebras are so fun!')); - -console.log('This is ' + colors.strikethrough('not') + ' fun.'); - - -console.log(colors.black.bgWhite('Background color attack!')); -console.log(colors.random('Use random styles on everything!')); -console.log(colors.america('America, Heck Yeah!')); - -// eslint-disable-next-line max-len -console.log(colors.brightCyan('Blindingly ') + colors.brightRed('bright? ') + colors.brightYellow('Why ') + colors.brightGreen('not?!')); - -console.log('Setting themes is useful'); - -// -// Custom themes -// -// console.log('Generic logging theme as JSON'.green.bold.underline); -// Load theme with JSON literal -colors.setTheme({ - silly: 'rainbow', - input: 'blue', - verbose: 'cyan', - prompt: 'grey', - info: 'green', - data: 'grey', - help: 'cyan', - warn: 'yellow', - debug: 'blue', - error: 'red', -}); - -// outputs red text -console.log(colors.error('this is an error')); - -// outputs yellow text -console.log(colors.warn('this is a warning')); - -// outputs blue text -console.log(colors.input('this is an input')); - - -// console.log('Generic logging theme as file'.green.bold.underline); - -// Load a theme from file -colors.setTheme(require(__dirname + '/../themes/generic-logging.js')); - -// outputs red text -console.log(colors.error('this is an error')); - -// outputs yellow text -console.log(colors.warn('this is a warning')); - -// outputs grey text -console.log(colors.input('this is an input')); - -// console.log(colors.zalgo("Don't summon him")) - - diff --git a/node_modules/@colors/colors/lib/colors.js b/node_modules/@colors/colors/lib/colors.js deleted file mode 100644 index d9fb08762fde5..0000000000000 --- a/node_modules/@colors/colors/lib/colors.js +++ /dev/null @@ -1,211 +0,0 @@ -/* - -The MIT License (MIT) - -Original Library - - Copyright (c) Marak Squires - -Additional functionality - - Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -var colors = {}; -module['exports'] = colors; - -colors.themes = {}; - -var util = require('util'); -var ansiStyles = colors.styles = require('./styles'); -var defineProps = Object.defineProperties; -var newLineRegex = new RegExp(/[\r\n]+/g); - -colors.supportsColor = require('./system/supports-colors').supportsColor; - -if (typeof colors.enabled === 'undefined') { - colors.enabled = colors.supportsColor() !== false; -} - -colors.enable = function() { - colors.enabled = true; -}; - -colors.disable = function() { - colors.enabled = false; -}; - -colors.stripColors = colors.strip = function(str) { - return ('' + str).replace(/\x1B\[\d+m/g, ''); -}; - -// eslint-disable-next-line no-unused-vars -var stylize = colors.stylize = function stylize(str, style) { - if (!colors.enabled) { - return str+''; - } - - var styleMap = ansiStyles[style]; - - // Stylize should work for non-ANSI styles, too - if (!styleMap && style in colors) { - // Style maps like trap operate as functions on strings; - // they don't have properties like open or close. - return colors[style](str); - } - - return styleMap.open + str + styleMap.close; -}; - -var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g; -var escapeStringRegexp = function(str) { - if (typeof str !== 'string') { - throw new TypeError('Expected a string'); - } - return str.replace(matchOperatorsRe, '\\$&'); -}; - -function build(_styles) { - var builder = function builder() { - return applyStyle.apply(builder, arguments); - }; - builder._styles = _styles; - // __proto__ is used because we must return a function, but there is - // no way to create a function with a different prototype. - builder.__proto__ = proto; - return builder; -} - -var styles = (function() { - var ret = {}; - ansiStyles.grey = ansiStyles.gray; - Object.keys(ansiStyles).forEach(function(key) { - ansiStyles[key].closeRe = - new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g'); - ret[key] = { - get: function() { - return build(this._styles.concat(key)); - }, - }; - }); - return ret; -})(); - -var proto = defineProps(function colors() {}, styles); - -function applyStyle() { - var args = Array.prototype.slice.call(arguments); - - var str = args.map(function(arg) { - // Use weak equality check so we can colorize null/undefined in safe mode - if (arg != null && arg.constructor === String) { - return arg; - } else { - return util.inspect(arg); - } - }).join(' '); - - if (!colors.enabled || !str) { - return str; - } - - var newLinesPresent = str.indexOf('\n') != -1; - - var nestedStyles = this._styles; - - var i = nestedStyles.length; - while (i--) { - var code = ansiStyles[nestedStyles[i]]; - str = code.open + str.replace(code.closeRe, code.open) + code.close; - if (newLinesPresent) { - str = str.replace(newLineRegex, function(match) { - return code.close + match + code.open; - }); - } - } - - return str; -} - -colors.setTheme = function(theme) { - if (typeof theme === 'string') { - console.log('colors.setTheme now only accepts an object, not a string. ' + - 'If you are trying to set a theme from a file, it is now your (the ' + - 'caller\'s) responsibility to require the file. The old syntax ' + - 'looked like colors.setTheme(__dirname + ' + - '\'/../themes/generic-logging.js\'); The new syntax looks like '+ - 'colors.setTheme(require(__dirname + ' + - '\'/../themes/generic-logging.js\'));'); - return; - } - for (var style in theme) { - (function(style) { - colors[style] = function(str) { - if (typeof theme[style] === 'object') { - var out = str; - for (var i in theme[style]) { - out = colors[theme[style][i]](out); - } - return out; - } - return colors[theme[style]](str); - }; - })(style); - } -}; - -function init() { - var ret = {}; - Object.keys(styles).forEach(function(name) { - ret[name] = { - get: function() { - return build([name]); - }, - }; - }); - return ret; -} - -var sequencer = function sequencer(map, str) { - var exploded = str.split(''); - exploded = exploded.map(map); - return exploded.join(''); -}; - -// custom formatter methods -colors.trap = require('./custom/trap'); -colors.zalgo = require('./custom/zalgo'); - -// maps -colors.maps = {}; -colors.maps.america = require('./maps/america')(colors); -colors.maps.zebra = require('./maps/zebra')(colors); -colors.maps.rainbow = require('./maps/rainbow')(colors); -colors.maps.random = require('./maps/random')(colors); - -for (var map in colors.maps) { - (function(map) { - colors[map] = function(str) { - return sequencer(colors.maps[map], str); - }; - })(map); -} - -defineProps(colors, init()); diff --git a/node_modules/@colors/colors/lib/custom/trap.js b/node_modules/@colors/colors/lib/custom/trap.js deleted file mode 100644 index fbccf88dede0b..0000000000000 --- a/node_modules/@colors/colors/lib/custom/trap.js +++ /dev/null @@ -1,46 +0,0 @@ -module['exports'] = function runTheTrap(text, options) { - var result = ''; - text = text || 'Run the trap, drop the bass'; - text = text.split(''); - var trap = { - a: ['\u0040', '\u0104', '\u023a', '\u0245', '\u0394', '\u039b', '\u0414'], - b: ['\u00df', '\u0181', '\u0243', '\u026e', '\u03b2', '\u0e3f'], - c: ['\u00a9', '\u023b', '\u03fe'], - d: ['\u00d0', '\u018a', '\u0500', '\u0501', '\u0502', '\u0503'], - e: ['\u00cb', '\u0115', '\u018e', '\u0258', '\u03a3', '\u03be', '\u04bc', - '\u0a6c'], - f: ['\u04fa'], - g: ['\u0262'], - h: ['\u0126', '\u0195', '\u04a2', '\u04ba', '\u04c7', '\u050a'], - i: ['\u0f0f'], - j: ['\u0134'], - k: ['\u0138', '\u04a0', '\u04c3', '\u051e'], - l: ['\u0139'], - m: ['\u028d', '\u04cd', '\u04ce', '\u0520', '\u0521', '\u0d69'], - n: ['\u00d1', '\u014b', '\u019d', '\u0376', '\u03a0', '\u048a'], - o: ['\u00d8', '\u00f5', '\u00f8', '\u01fe', '\u0298', '\u047a', '\u05dd', - '\u06dd', '\u0e4f'], - p: ['\u01f7', '\u048e'], - q: ['\u09cd'], - r: ['\u00ae', '\u01a6', '\u0210', '\u024c', '\u0280', '\u042f'], - s: ['\u00a7', '\u03de', '\u03df', '\u03e8'], - t: ['\u0141', '\u0166', '\u0373'], - u: ['\u01b1', '\u054d'], - v: ['\u05d8'], - w: ['\u0428', '\u0460', '\u047c', '\u0d70'], - x: ['\u04b2', '\u04fe', '\u04fc', '\u04fd'], - y: ['\u00a5', '\u04b0', '\u04cb'], - z: ['\u01b5', '\u0240'], - }; - text.forEach(function(c) { - c = c.toLowerCase(); - var chars = trap[c] || [' ']; - var rand = Math.floor(Math.random() * chars.length); - if (typeof trap[c] !== 'undefined') { - result += trap[c][rand]; - } else { - result += c; - } - }); - return result; -}; diff --git a/node_modules/@colors/colors/lib/custom/zalgo.js b/node_modules/@colors/colors/lib/custom/zalgo.js deleted file mode 100644 index 0ef2b01195635..0000000000000 --- a/node_modules/@colors/colors/lib/custom/zalgo.js +++ /dev/null @@ -1,110 +0,0 @@ -// please no -module['exports'] = function zalgo(text, options) { - text = text || ' he is here '; - var soul = { - 'up': [ - '̍', '̎', '̄', '̅', - '̿', '̑', '̆', '̐', - '͒', '͗', '͑', '̇', - '̈', '̊', '͂', '̓', - '̈', '͊', '͋', '͌', - '̃', '̂', '̌', '͐', - '̀', '́', '̋', '̏', - '̒', '̓', '̔', '̽', - '̉', 'ͣ', 'ͤ', 'ͥ', - 'ͦ', 'ͧ', 'ͨ', 'ͩ', - 'ͪ', 'ͫ', 'ͬ', 'ͭ', - 'ͮ', 'ͯ', '̾', '͛', - '͆', '̚', - ], - 'down': [ - '̖', '̗', '̘', '̙', - '̜', '̝', '̞', '̟', - '̠', '̤', '̥', '̦', - '̩', '̪', '̫', '̬', - '̭', '̮', '̯', '̰', - '̱', '̲', '̳', '̹', - '̺', '̻', '̼', 'ͅ', - '͇', '͈', '͉', '͍', - '͎', '͓', '͔', '͕', - '͖', '͙', '͚', '̣', - ], - 'mid': [ - '̕', '̛', '̀', '́', - '͘', '̡', '̢', '̧', - '̨', '̴', '̵', '̶', - '͜', '͝', '͞', - '͟', '͠', '͢', '̸', - '̷', '͡', ' ҉', - ], - }; - var all = [].concat(soul.up, soul.down, soul.mid); - - function randomNumber(range) { - var r = Math.floor(Math.random() * range); - return r; - } - - function isChar(character) { - var bool = false; - all.filter(function(i) { - bool = (i === character); - }); - return bool; - } - - - function heComes(text, options) { - var result = ''; - var counts; - var l; - options = options || {}; - options['up'] = - typeof options['up'] !== 'undefined' ? options['up'] : true; - options['mid'] = - typeof options['mid'] !== 'undefined' ? options['mid'] : true; - options['down'] = - typeof options['down'] !== 'undefined' ? options['down'] : true; - options['size'] = - typeof options['size'] !== 'undefined' ? options['size'] : 'maxi'; - text = text.split(''); - for (l in text) { - if (isChar(l)) { - continue; - } - result = result + text[l]; - counts = {'up': 0, 'down': 0, 'mid': 0}; - switch (options.size) { - case 'mini': - counts.up = randomNumber(8); - counts.mid = randomNumber(2); - counts.down = randomNumber(8); - break; - case 'maxi': - counts.up = randomNumber(16) + 3; - counts.mid = randomNumber(4) + 1; - counts.down = randomNumber(64) + 3; - break; - default: - counts.up = randomNumber(8) + 1; - counts.mid = randomNumber(6) / 2; - counts.down = randomNumber(8) + 1; - break; - } - - var arr = ['up', 'mid', 'down']; - for (var d in arr) { - var index = arr[d]; - for (var i = 0; i <= counts[index]; i++) { - if (options[index]) { - result = result + soul[index][randomNumber(soul[index].length)]; - } - } - } - } - return result; - } - // don't summon him - return heComes(text, options); -}; - diff --git a/node_modules/@colors/colors/lib/extendStringPrototype.js b/node_modules/@colors/colors/lib/extendStringPrototype.js deleted file mode 100644 index 46fd386a915a6..0000000000000 --- a/node_modules/@colors/colors/lib/extendStringPrototype.js +++ /dev/null @@ -1,110 +0,0 @@ -var colors = require('./colors'); - -module['exports'] = function() { - // - // Extends prototype of native string object to allow for "foo".red syntax - // - var addProperty = function(color, func) { - String.prototype.__defineGetter__(color, func); - }; - - addProperty('strip', function() { - return colors.strip(this); - }); - - addProperty('stripColors', function() { - return colors.strip(this); - }); - - addProperty('trap', function() { - return colors.trap(this); - }); - - addProperty('zalgo', function() { - return colors.zalgo(this); - }); - - addProperty('zebra', function() { - return colors.zebra(this); - }); - - addProperty('rainbow', function() { - return colors.rainbow(this); - }); - - addProperty('random', function() { - return colors.random(this); - }); - - addProperty('america', function() { - return colors.america(this); - }); - - // - // Iterate through all default styles and colors - // - var x = Object.keys(colors.styles); - x.forEach(function(style) { - addProperty(style, function() { - return colors.stylize(this, style); - }); - }); - - function applyTheme(theme) { - // - // Remark: This is a list of methods that exist - // on String that you should not overwrite. - // - var stringPrototypeBlacklist = [ - '__defineGetter__', '__defineSetter__', '__lookupGetter__', - '__lookupSetter__', 'charAt', 'constructor', 'hasOwnProperty', - 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', - 'valueOf', 'charCodeAt', 'indexOf', 'lastIndexOf', 'length', - 'localeCompare', 'match', 'repeat', 'replace', 'search', 'slice', - 'split', 'substring', 'toLocaleLowerCase', 'toLocaleUpperCase', - 'toLowerCase', 'toUpperCase', 'trim', 'trimLeft', 'trimRight', - ]; - - Object.keys(theme).forEach(function(prop) { - if (stringPrototypeBlacklist.indexOf(prop) !== -1) { - console.log('warn: '.red + ('String.prototype' + prop).magenta + - ' is probably something you don\'t want to override. ' + - 'Ignoring style name'); - } else { - if (typeof(theme[prop]) === 'string') { - colors[prop] = colors[theme[prop]]; - addProperty(prop, function() { - return colors[prop](this); - }); - } else { - var themePropApplicator = function(str) { - var ret = str || this; - for (var t = 0; t < theme[prop].length; t++) { - ret = colors[theme[prop][t]](ret); - } - return ret; - }; - addProperty(prop, themePropApplicator); - colors[prop] = function(str) { - return themePropApplicator(str); - }; - } - } - }); - } - - colors.setTheme = function(theme) { - if (typeof theme === 'string') { - console.log('colors.setTheme now only accepts an object, not a string. ' + - 'If you are trying to set a theme from a file, it is now your (the ' + - 'caller\'s) responsibility to require the file. The old syntax ' + - 'looked like colors.setTheme(__dirname + ' + - '\'/../themes/generic-logging.js\'); The new syntax looks like '+ - 'colors.setTheme(require(__dirname + ' + - '\'/../themes/generic-logging.js\'));'); - return; - } else { - applyTheme(theme); - } - }; -}; diff --git a/node_modules/@colors/colors/lib/index.js b/node_modules/@colors/colors/lib/index.js deleted file mode 100644 index 9df5ab7df3077..0000000000000 --- a/node_modules/@colors/colors/lib/index.js +++ /dev/null @@ -1,13 +0,0 @@ -var colors = require('./colors'); -module['exports'] = colors; - -// Remark: By default, colors will add style properties to String.prototype. -// -// If you don't wish to extend String.prototype, you can do this instead and -// native String will not be touched: -// -// var colors = require('colors/safe); -// colors.red("foo") -// -// -require('./extendStringPrototype')(); diff --git a/node_modules/@colors/colors/lib/maps/america.js b/node_modules/@colors/colors/lib/maps/america.js deleted file mode 100644 index dc96903328989..0000000000000 --- a/node_modules/@colors/colors/lib/maps/america.js +++ /dev/null @@ -1,10 +0,0 @@ -module['exports'] = function(colors) { - return function(letter, i, exploded) { - if (letter === ' ') return letter; - switch (i%3) { - case 0: return colors.red(letter); - case 1: return colors.white(letter); - case 2: return colors.blue(letter); - } - }; -}; diff --git a/node_modules/@colors/colors/lib/maps/rainbow.js b/node_modules/@colors/colors/lib/maps/rainbow.js deleted file mode 100644 index 2b00ac0ac998e..0000000000000 --- a/node_modules/@colors/colors/lib/maps/rainbow.js +++ /dev/null @@ -1,12 +0,0 @@ -module['exports'] = function(colors) { - // RoY G BiV - var rainbowColors = ['red', 'yellow', 'green', 'blue', 'magenta']; - return function(letter, i, exploded) { - if (letter === ' ') { - return letter; - } else { - return colors[rainbowColors[i++ % rainbowColors.length]](letter); - } - }; -}; - diff --git a/node_modules/@colors/colors/lib/maps/random.js b/node_modules/@colors/colors/lib/maps/random.js deleted file mode 100644 index 3d82a39ec0fab..0000000000000 --- a/node_modules/@colors/colors/lib/maps/random.js +++ /dev/null @@ -1,11 +0,0 @@ -module['exports'] = function(colors) { - var available = ['underline', 'inverse', 'grey', 'yellow', 'red', 'green', - 'blue', 'white', 'cyan', 'magenta', 'brightYellow', 'brightRed', - 'brightGreen', 'brightBlue', 'brightWhite', 'brightCyan', 'brightMagenta']; - return function(letter, i, exploded) { - return letter === ' ' ? letter : - colors[ - available[Math.round(Math.random() * (available.length - 2))] - ](letter); - }; -}; diff --git a/node_modules/@colors/colors/lib/maps/zebra.js b/node_modules/@colors/colors/lib/maps/zebra.js deleted file mode 100644 index fa73623544a82..0000000000000 --- a/node_modules/@colors/colors/lib/maps/zebra.js +++ /dev/null @@ -1,5 +0,0 @@ -module['exports'] = function(colors) { - return function(letter, i, exploded) { - return i % 2 === 0 ? letter : colors.inverse(letter); - }; -}; diff --git a/node_modules/@colors/colors/lib/styles.js b/node_modules/@colors/colors/lib/styles.js deleted file mode 100644 index 011dafd8c28f7..0000000000000 --- a/node_modules/@colors/colors/lib/styles.js +++ /dev/null @@ -1,95 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -var styles = {}; -module['exports'] = styles; - -var codes = { - reset: [0, 0], - - bold: [1, 22], - dim: [2, 22], - italic: [3, 23], - underline: [4, 24], - inverse: [7, 27], - hidden: [8, 28], - strikethrough: [9, 29], - - black: [30, 39], - red: [31, 39], - green: [32, 39], - yellow: [33, 39], - blue: [34, 39], - magenta: [35, 39], - cyan: [36, 39], - white: [37, 39], - gray: [90, 39], - grey: [90, 39], - - brightRed: [91, 39], - brightGreen: [92, 39], - brightYellow: [93, 39], - brightBlue: [94, 39], - brightMagenta: [95, 39], - brightCyan: [96, 39], - brightWhite: [97, 39], - - bgBlack: [40, 49], - bgRed: [41, 49], - bgGreen: [42, 49], - bgYellow: [43, 49], - bgBlue: [44, 49], - bgMagenta: [45, 49], - bgCyan: [46, 49], - bgWhite: [47, 49], - bgGray: [100, 49], - bgGrey: [100, 49], - - bgBrightRed: [101, 49], - bgBrightGreen: [102, 49], - bgBrightYellow: [103, 49], - bgBrightBlue: [104, 49], - bgBrightMagenta: [105, 49], - bgBrightCyan: [106, 49], - bgBrightWhite: [107, 49], - - // legacy styles for colors pre v1.0.0 - blackBG: [40, 49], - redBG: [41, 49], - greenBG: [42, 49], - yellowBG: [43, 49], - blueBG: [44, 49], - magentaBG: [45, 49], - cyanBG: [46, 49], - whiteBG: [47, 49], - -}; - -Object.keys(codes).forEach(function(key) { - var val = codes[key]; - var style = styles[key] = []; - style.open = '\u001b[' + val[0] + 'm'; - style.close = '\u001b[' + val[1] + 'm'; -}); diff --git a/node_modules/@colors/colors/lib/system/has-flag.js b/node_modules/@colors/colors/lib/system/has-flag.js deleted file mode 100644 index a347dd4d7a697..0000000000000 --- a/node_modules/@colors/colors/lib/system/has-flag.js +++ /dev/null @@ -1,35 +0,0 @@ -/* -MIT License - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -'use strict'; - -module.exports = function(flag, argv) { - argv = argv || process.argv; - - var terminatorPos = argv.indexOf('--'); - var prefix = /^-{1,2}/.test(flag) ? '' : '--'; - var pos = argv.indexOf(prefix + flag); - - return pos !== -1 && (terminatorPos === -1 ? true : pos < terminatorPos); -}; diff --git a/node_modules/@colors/colors/lib/system/supports-colors.js b/node_modules/@colors/colors/lib/system/supports-colors.js deleted file mode 100644 index f1f9c8ff3da28..0000000000000 --- a/node_modules/@colors/colors/lib/system/supports-colors.js +++ /dev/null @@ -1,151 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -'use strict'; - -var os = require('os'); -var hasFlag = require('./has-flag.js'); - -var env = process.env; - -var forceColor = void 0; -if (hasFlag('no-color') || hasFlag('no-colors') || hasFlag('color=false')) { - forceColor = false; -} else if (hasFlag('color') || hasFlag('colors') || hasFlag('color=true') - || hasFlag('color=always')) { - forceColor = true; -} -if ('FORCE_COLOR' in env) { - forceColor = env.FORCE_COLOR.length === 0 - || parseInt(env.FORCE_COLOR, 10) !== 0; -} - -function translateLevel(level) { - if (level === 0) { - return false; - } - - return { - level: level, - hasBasic: true, - has256: level >= 2, - has16m: level >= 3, - }; -} - -function supportsColor(stream) { - if (forceColor === false) { - return 0; - } - - if (hasFlag('color=16m') || hasFlag('color=full') - || hasFlag('color=truecolor')) { - return 3; - } - - if (hasFlag('color=256')) { - return 2; - } - - if (stream && !stream.isTTY && forceColor !== true) { - return 0; - } - - var min = forceColor ? 1 : 0; - - if (process.platform === 'win32') { - // Node.js 7.5.0 is the first version of Node.js to include a patch to - // libuv that enables 256 color output on Windows. Anything earlier and it - // won't work. However, here we target Node.js 8 at minimum as it is an LTS - // release, and Node.js 7 is not. Windows 10 build 10586 is the first - // Windows release that supports 256 colors. Windows 10 build 14931 is the - // first release that supports 16m/TrueColor. - var osRelease = os.release().split('.'); - if (Number(process.versions.node.split('.')[0]) >= 8 - && Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) { - return Number(osRelease[2]) >= 14931 ? 3 : 2; - } - - return 1; - } - - if ('CI' in env) { - if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(function(sign) { - return sign in env; - }) || env.CI_NAME === 'codeship') { - return 1; - } - - return min; - } - - if ('TEAMCITY_VERSION' in env) { - return (/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0 - ); - } - - if ('TERM_PROGRAM' in env) { - var version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10); - - switch (env.TERM_PROGRAM) { - case 'iTerm.app': - return version >= 3 ? 3 : 2; - case 'Hyper': - return 3; - case 'Apple_Terminal': - return 2; - // No default - } - } - - if (/-256(color)?$/i.test(env.TERM)) { - return 2; - } - - if (/^screen|^xterm|^vt100|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) { - return 1; - } - - if ('COLORTERM' in env) { - return 1; - } - - if (env.TERM === 'dumb') { - return min; - } - - return min; -} - -function getSupportLevel(stream) { - var level = supportsColor(stream); - return translateLevel(level); -} - -module.exports = { - supportsColor: getSupportLevel, - stdout: getSupportLevel(process.stdout), - stderr: getSupportLevel(process.stderr), -}; diff --git a/node_modules/@colors/colors/package.json b/node_modules/@colors/colors/package.json deleted file mode 100644 index cb87f20953886..0000000000000 --- a/node_modules/@colors/colors/package.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "name": "@colors/colors", - "description": "get colors in your node.js console", - "version": "1.5.0", - "author": "DABH", - "contributors": [ - { - "name": "DABH", - "url": "https://github.com/DABH" - } - ], - "homepage": "https://github.com/DABH/colors.js", - "bugs": "https://github.com/DABH/colors.js/issues", - "keywords": [ - "ansi", - "terminal", - "colors" - ], - "repository": { - "type": "git", - "url": "http://github.com/DABH/colors.js.git" - }, - "license": "MIT", - "scripts": { - "lint": "eslint . --fix", - "test": "export FORCE_COLOR=1 && node tests/basic-test.js && node tests/safe-test.js" - }, - "engines": { - "node": ">=0.1.90" - }, - "main": "lib/index.js", - "files": [ - "examples", - "lib", - "LICENSE", - "safe.js", - "themes", - "index.d.ts", - "safe.d.ts" - ], - "devDependencies": { - "eslint": "^5.2.0", - "eslint-config-google": "^0.11.0" - } -} diff --git a/node_modules/@colors/colors/safe.js b/node_modules/@colors/colors/safe.js deleted file mode 100644 index a013d54246485..0000000000000 --- a/node_modules/@colors/colors/safe.js +++ /dev/null @@ -1,10 +0,0 @@ -// -// Remark: Requiring this file will use the "safe" colors API, -// which will not touch String.prototype. -// -// var colors = require('colors/safe'); -// colors.red("foo") -// -// -var colors = require('./lib/colors'); -module['exports'] = colors; diff --git a/node_modules/@colors/colors/themes/generic-logging.js b/node_modules/@colors/colors/themes/generic-logging.js deleted file mode 100644 index 63adfe4ac31f9..0000000000000 --- a/node_modules/@colors/colors/themes/generic-logging.js +++ /dev/null @@ -1,12 +0,0 @@ -module['exports'] = { - silly: 'rainbow', - input: 'grey', - verbose: 'cyan', - prompt: 'grey', - info: 'green', - data: 'grey', - help: 'cyan', - warn: 'yellow', - debug: 'blue', - error: 'red', -}; diff --git a/node_modules/cli-table3/LICENSE b/node_modules/cli-table3/LICENSE deleted file mode 100644 index a09b7de012ac8..0000000000000 --- a/node_modules/cli-table3/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2014 James Talmage - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/node_modules/cli-table3/index.js b/node_modules/cli-table3/index.js deleted file mode 100644 index b49d920dd3ef6..0000000000000 --- a/node_modules/cli-table3/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./src/table'); \ No newline at end of file diff --git a/node_modules/cli-table3/package.json b/node_modules/cli-table3/package.json deleted file mode 100644 index 0bd5d31d10246..0000000000000 --- a/node_modules/cli-table3/package.json +++ /dev/null @@ -1,100 +0,0 @@ -{ - "name": "cli-table3", - "version": "0.6.4", - "description": "Pretty unicode tables for the command line. Based on the original cli-table.", - "main": "index.js", - "types": "index.d.ts", - "files": [ - "src/", - "index.d.ts", - "index.js" - ], - "directories": { - "test": "test" - }, - "dependencies": { - "string-width": "^4.2.0" - }, - "devDependencies": { - "cli-table": "^0.3.1", - "eslint": "^6.0.0", - "eslint-config-prettier": "^6.0.0", - "eslint-plugin-prettier": "^3.0.0", - "jest": "^25.2.4", - "jest-runner-eslint": "^0.7.0", - "lerna-changelog": "^1.0.1", - "prettier": "2.3.2" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" - }, - "scripts": { - "changelog": "lerna-changelog", - "docs": "node ./scripts/update-docs.js", - "prettier": "prettier --write '{examples,lib,scripts,src,test}/**/*.js'", - "test": "jest --color", - "test:watch": "jest --color --watchAll --notify" - }, - "repository": { - "type": "git", - "url": "https://github.com/cli-table/cli-table3.git" - }, - "keywords": [ - "node", - "command", - "line", - "cli", - "table", - "tables", - "tabular", - "unicode", - "colors", - "grid" - ], - "author": "James Talmage", - "license": "MIT", - "bugs": { - "url": "https://github.com/cli-table/cli-table3/issues" - }, - "homepage": "https://github.com/cli-table/cli-table3", - "engines": { - "node": "10.* || >= 12.*" - }, - "changelog": { - "repo": "cli-table/cli-table3", - "labels": { - "breaking": ":boom: Breaking Change", - "enhancement": ":rocket: Enhancement", - "bug": ":bug: Bug Fix", - "documentation": ":memo: Documentation", - "internal": ":house: Internal" - } - }, - "jest": { - "projects": [ - { - "displayName": "test", - "testMatch": [ - "/test/**/*.js" - ] - }, - { - "runner": "jest-runner-eslint", - "displayName": "lint", - "testMatch": [ - "/examples/**/*.js", - "/lib/**/*.js", - "/scripts/**/*.js", - "/src/**/*.js", - "/test/**/*.js" - ] - } - ] - }, - "prettier": { - "printWidth": 120, - "tabWidth": 2, - "singleQuote": true, - "trailingComma": "es5" - } -} diff --git a/node_modules/cli-table3/src/cell.js b/node_modules/cli-table3/src/cell.js deleted file mode 100644 index 8c3df35d19407..0000000000000 --- a/node_modules/cli-table3/src/cell.js +++ /dev/null @@ -1,409 +0,0 @@ -const { info, debug } = require('./debug'); -const utils = require('./utils'); - -class Cell { - /** - * A representation of a cell within the table. - * Implementations must have `init` and `draw` methods, - * as well as `colSpan`, `rowSpan`, `desiredHeight` and `desiredWidth` properties. - * @param options - * @constructor - */ - constructor(options) { - this.setOptions(options); - - /** - * Each cell will have it's `x` and `y` values set by the `layout-manager` prior to - * `init` being called; - * @type {Number} - */ - this.x = null; - this.y = null; - } - - setOptions(options) { - if (['boolean', 'number', 'string'].indexOf(typeof options) !== -1) { - options = { content: '' + options }; - } - options = options || {}; - this.options = options; - let content = options.content; - if (['boolean', 'number', 'string'].indexOf(typeof content) !== -1) { - this.content = String(content); - } else if (!content) { - this.content = this.options.href || ''; - } else { - throw new Error('Content needs to be a primitive, got: ' + typeof content); - } - this.colSpan = options.colSpan || 1; - this.rowSpan = options.rowSpan || 1; - if (this.options.href) { - Object.defineProperty(this, 'href', { - get() { - return this.options.href; - }, - }); - } - } - - mergeTableOptions(tableOptions, cells) { - this.cells = cells; - - let optionsChars = this.options.chars || {}; - let tableChars = tableOptions.chars; - let chars = (this.chars = {}); - CHAR_NAMES.forEach(function (name) { - setOption(optionsChars, tableChars, name, chars); - }); - - this.truncate = this.options.truncate || tableOptions.truncate; - - let style = (this.options.style = this.options.style || {}); - let tableStyle = tableOptions.style; - setOption(style, tableStyle, 'padding-left', this); - setOption(style, tableStyle, 'padding-right', this); - this.head = style.head || tableStyle.head; - this.border = style.border || tableStyle.border; - - this.fixedWidth = tableOptions.colWidths[this.x]; - this.lines = this.computeLines(tableOptions); - - this.desiredWidth = utils.strlen(this.content) + this.paddingLeft + this.paddingRight; - this.desiredHeight = this.lines.length; - } - - computeLines(tableOptions) { - const tableWordWrap = tableOptions.wordWrap || tableOptions.textWrap; - const { wordWrap = tableWordWrap } = this.options; - if (this.fixedWidth && wordWrap) { - this.fixedWidth -= this.paddingLeft + this.paddingRight; - if (this.colSpan) { - let i = 1; - while (i < this.colSpan) { - this.fixedWidth += tableOptions.colWidths[this.x + i]; - i++; - } - } - const { wrapOnWordBoundary: tableWrapOnWordBoundary = true } = tableOptions; - const { wrapOnWordBoundary = tableWrapOnWordBoundary } = this.options; - return this.wrapLines(utils.wordWrap(this.fixedWidth, this.content, wrapOnWordBoundary)); - } - return this.wrapLines(this.content.split('\n')); - } - - wrapLines(computedLines) { - const lines = utils.colorizeLines(computedLines); - if (this.href) { - return lines.map((line) => utils.hyperlink(this.href, line)); - } - return lines; - } - - /** - * Initializes the Cells data structure. - * - * @param tableOptions - A fully populated set of tableOptions. - * In addition to the standard default values, tableOptions must have fully populated the - * `colWidths` and `rowWidths` arrays. Those arrays must have lengths equal to the number - * of columns or rows (respectively) in this table, and each array item must be a Number. - * - */ - init(tableOptions) { - let x = this.x; - let y = this.y; - this.widths = tableOptions.colWidths.slice(x, x + this.colSpan); - this.heights = tableOptions.rowHeights.slice(y, y + this.rowSpan); - this.width = this.widths.reduce(sumPlusOne, -1); - this.height = this.heights.reduce(sumPlusOne, -1); - - this.hAlign = this.options.hAlign || tableOptions.colAligns[x]; - this.vAlign = this.options.vAlign || tableOptions.rowAligns[y]; - - this.drawRight = x + this.colSpan == tableOptions.colWidths.length; - } - - /** - * Draws the given line of the cell. - * This default implementation defers to methods `drawTop`, `drawBottom`, `drawLine` and `drawEmpty`. - * @param lineNum - can be `top`, `bottom` or a numerical line number. - * @param spanningCell - will be a number if being called from a RowSpanCell, and will represent how - * many rows below it's being called from. Otherwise it's undefined. - * @returns {String} The representation of this line. - */ - draw(lineNum, spanningCell) { - if (lineNum == 'top') return this.drawTop(this.drawRight); - if (lineNum == 'bottom') return this.drawBottom(this.drawRight); - let content = utils.truncate(this.content, 10, this.truncate); - if (!lineNum) { - info(`${this.y}-${this.x}: ${this.rowSpan - lineNum}x${this.colSpan} Cell ${content}`); - } else { - // debug(`${lineNum}-${this.x}: 1x${this.colSpan} RowSpanCell ${content}`); - } - let padLen = Math.max(this.height - this.lines.length, 0); - let padTop; - switch (this.vAlign) { - case 'center': - padTop = Math.ceil(padLen / 2); - break; - case 'bottom': - padTop = padLen; - break; - default: - padTop = 0; - } - if (lineNum < padTop || lineNum >= padTop + this.lines.length) { - return this.drawEmpty(this.drawRight, spanningCell); - } - let forceTruncation = this.lines.length > this.height && lineNum + 1 >= this.height; - return this.drawLine(lineNum - padTop, this.drawRight, forceTruncation, spanningCell); - } - - /** - * Renders the top line of the cell. - * @param drawRight - true if this method should render the right edge of the cell. - * @returns {String} - */ - drawTop(drawRight) { - let content = []; - if (this.cells) { - //TODO: cells should always exist - some tests don't fill it in though - this.widths.forEach(function (width, index) { - content.push(this._topLeftChar(index)); - content.push(utils.repeat(this.chars[this.y == 0 ? 'top' : 'mid'], width)); - }, this); - } else { - content.push(this._topLeftChar(0)); - content.push(utils.repeat(this.chars[this.y == 0 ? 'top' : 'mid'], this.width)); - } - if (drawRight) { - content.push(this.chars[this.y == 0 ? 'topRight' : 'rightMid']); - } - return this.wrapWithStyleColors('border', content.join('')); - } - - _topLeftChar(offset) { - let x = this.x + offset; - let leftChar; - if (this.y == 0) { - leftChar = x == 0 ? 'topLeft' : offset == 0 ? 'topMid' : 'top'; - } else { - if (x == 0) { - leftChar = 'leftMid'; - } else { - leftChar = offset == 0 ? 'midMid' : 'bottomMid'; - if (this.cells) { - //TODO: cells should always exist - some tests don't fill it in though - let spanAbove = this.cells[this.y - 1][x] instanceof Cell.ColSpanCell; - if (spanAbove) { - leftChar = offset == 0 ? 'topMid' : 'mid'; - } - if (offset == 0) { - let i = 1; - while (this.cells[this.y][x - i] instanceof Cell.ColSpanCell) { - i++; - } - if (this.cells[this.y][x - i] instanceof Cell.RowSpanCell) { - leftChar = 'leftMid'; - } - } - } - } - } - return this.chars[leftChar]; - } - - wrapWithStyleColors(styleProperty, content) { - if (this[styleProperty] && this[styleProperty].length) { - try { - let colors = require('@colors/colors/safe'); - for (let i = this[styleProperty].length - 1; i >= 0; i--) { - colors = colors[this[styleProperty][i]]; - } - return colors(content); - } catch (e) { - return content; - } - } else { - return content; - } - } - - /** - * Renders a line of text. - * @param lineNum - Which line of text to render. This is not necessarily the line within the cell. - * There may be top-padding above the first line of text. - * @param drawRight - true if this method should render the right edge of the cell. - * @param forceTruncationSymbol - `true` if the rendered text should end with the truncation symbol even - * if the text fits. This is used when the cell is vertically truncated. If `false` the text should - * only include the truncation symbol if the text will not fit horizontally within the cell width. - * @param spanningCell - a number of if being called from a RowSpanCell. (how many rows below). otherwise undefined. - * @returns {String} - */ - drawLine(lineNum, drawRight, forceTruncationSymbol, spanningCell) { - let left = this.chars[this.x == 0 ? 'left' : 'middle']; - if (this.x && spanningCell && this.cells) { - let cellLeft = this.cells[this.y + spanningCell][this.x - 1]; - while (cellLeft instanceof ColSpanCell) { - cellLeft = this.cells[cellLeft.y][cellLeft.x - 1]; - } - if (!(cellLeft instanceof RowSpanCell)) { - left = this.chars['rightMid']; - } - } - let leftPadding = utils.repeat(' ', this.paddingLeft); - let right = drawRight ? this.chars['right'] : ''; - let rightPadding = utils.repeat(' ', this.paddingRight); - let line = this.lines[lineNum]; - let len = this.width - (this.paddingLeft + this.paddingRight); - if (forceTruncationSymbol) line += this.truncate || '…'; - let content = utils.truncate(line, len, this.truncate); - content = utils.pad(content, len, ' ', this.hAlign); - content = leftPadding + content + rightPadding; - return this.stylizeLine(left, content, right); - } - - stylizeLine(left, content, right) { - left = this.wrapWithStyleColors('border', left); - right = this.wrapWithStyleColors('border', right); - if (this.y === 0) { - content = this.wrapWithStyleColors('head', content); - } - return left + content + right; - } - - /** - * Renders the bottom line of the cell. - * @param drawRight - true if this method should render the right edge of the cell. - * @returns {String} - */ - drawBottom(drawRight) { - let left = this.chars[this.x == 0 ? 'bottomLeft' : 'bottomMid']; - let content = utils.repeat(this.chars.bottom, this.width); - let right = drawRight ? this.chars['bottomRight'] : ''; - return this.wrapWithStyleColors('border', left + content + right); - } - - /** - * Renders a blank line of text within the cell. Used for top and/or bottom padding. - * @param drawRight - true if this method should render the right edge of the cell. - * @param spanningCell - a number of if being called from a RowSpanCell. (how many rows below). otherwise undefined. - * @returns {String} - */ - drawEmpty(drawRight, spanningCell) { - let left = this.chars[this.x == 0 ? 'left' : 'middle']; - if (this.x && spanningCell && this.cells) { - let cellLeft = this.cells[this.y + spanningCell][this.x - 1]; - while (cellLeft instanceof ColSpanCell) { - cellLeft = this.cells[cellLeft.y][cellLeft.x - 1]; - } - if (!(cellLeft instanceof RowSpanCell)) { - left = this.chars['rightMid']; - } - } - let right = drawRight ? this.chars['right'] : ''; - let content = utils.repeat(' ', this.width); - return this.stylizeLine(left, content, right); - } -} - -class ColSpanCell { - /** - * A Cell that doesn't do anything. It just draws empty lines. - * Used as a placeholder in column spanning. - * @constructor - */ - constructor() {} - - draw(lineNum) { - if (typeof lineNum === 'number') { - debug(`${this.y}-${this.x}: 1x1 ColSpanCell`); - } - return ''; - } - - init() {} - - mergeTableOptions() {} -} - -class RowSpanCell { - /** - * A placeholder Cell for a Cell that spans multiple rows. - * It delegates rendering to the original cell, but adds the appropriate offset. - * @param originalCell - * @constructor - */ - constructor(originalCell) { - this.originalCell = originalCell; - } - - init(tableOptions) { - let y = this.y; - let originalY = this.originalCell.y; - this.cellOffset = y - originalY; - this.offset = findDimension(tableOptions.rowHeights, originalY, this.cellOffset); - } - - draw(lineNum) { - if (lineNum == 'top') { - return this.originalCell.draw(this.offset, this.cellOffset); - } - if (lineNum == 'bottom') { - return this.originalCell.draw('bottom'); - } - debug(`${this.y}-${this.x}: 1x${this.colSpan} RowSpanCell for ${this.originalCell.content}`); - return this.originalCell.draw(this.offset + 1 + lineNum); - } - - mergeTableOptions() {} -} - -function firstDefined(...args) { - return args.filter((v) => v !== undefined && v !== null).shift(); -} - -// HELPER FUNCTIONS -function setOption(objA, objB, nameB, targetObj) { - let nameA = nameB.split('-'); - if (nameA.length > 1) { - nameA[1] = nameA[1].charAt(0).toUpperCase() + nameA[1].substr(1); - nameA = nameA.join(''); - targetObj[nameA] = firstDefined(objA[nameA], objA[nameB], objB[nameA], objB[nameB]); - } else { - targetObj[nameB] = firstDefined(objA[nameB], objB[nameB]); - } -} - -function findDimension(dimensionTable, startingIndex, span) { - let ret = dimensionTable[startingIndex]; - for (let i = 1; i < span; i++) { - ret += 1 + dimensionTable[startingIndex + i]; - } - return ret; -} - -function sumPlusOne(a, b) { - return a + b + 1; -} - -let CHAR_NAMES = [ - 'top', - 'top-mid', - 'top-left', - 'top-right', - 'bottom', - 'bottom-mid', - 'bottom-left', - 'bottom-right', - 'left', - 'left-mid', - 'mid', - 'mid-mid', - 'right', - 'right-mid', - 'middle', -]; - -module.exports = Cell; -module.exports.ColSpanCell = ColSpanCell; -module.exports.RowSpanCell = RowSpanCell; diff --git a/node_modules/cli-table3/src/debug.js b/node_modules/cli-table3/src/debug.js deleted file mode 100644 index 6acfb03032159..0000000000000 --- a/node_modules/cli-table3/src/debug.js +++ /dev/null @@ -1,28 +0,0 @@ -let messages = []; -let level = 0; - -const debug = (msg, min) => { - if (level >= min) { - messages.push(msg); - } -}; - -debug.WARN = 1; -debug.INFO = 2; -debug.DEBUG = 3; - -debug.reset = () => { - messages = []; -}; - -debug.setDebugLevel = (v) => { - level = v; -}; - -debug.warn = (msg) => debug(msg, debug.WARN); -debug.info = (msg) => debug(msg, debug.INFO); -debug.debug = (msg) => debug(msg, debug.DEBUG); - -debug.debugMessages = () => messages; - -module.exports = debug; diff --git a/node_modules/cli-table3/src/layout-manager.js b/node_modules/cli-table3/src/layout-manager.js deleted file mode 100644 index 3937452274d72..0000000000000 --- a/node_modules/cli-table3/src/layout-manager.js +++ /dev/null @@ -1,254 +0,0 @@ -const { warn, debug } = require('./debug'); -const Cell = require('./cell'); -const { ColSpanCell, RowSpanCell } = Cell; - -(function () { - function next(alloc, col) { - if (alloc[col] > 0) { - return next(alloc, col + 1); - } - return col; - } - - function layoutTable(table) { - let alloc = {}; - table.forEach(function (row, rowIndex) { - let col = 0; - row.forEach(function (cell) { - cell.y = rowIndex; - // Avoid erroneous call to next() on first row - cell.x = rowIndex ? next(alloc, col) : col; - const rowSpan = cell.rowSpan || 1; - const colSpan = cell.colSpan || 1; - if (rowSpan > 1) { - for (let cs = 0; cs < colSpan; cs++) { - alloc[cell.x + cs] = rowSpan; - } - } - col = cell.x + colSpan; - }); - Object.keys(alloc).forEach((idx) => { - alloc[idx]--; - if (alloc[idx] < 1) delete alloc[idx]; - }); - }); - } - - function maxWidth(table) { - let mw = 0; - table.forEach(function (row) { - row.forEach(function (cell) { - mw = Math.max(mw, cell.x + (cell.colSpan || 1)); - }); - }); - return mw; - } - - function maxHeight(table) { - return table.length; - } - - function cellsConflict(cell1, cell2) { - let yMin1 = cell1.y; - let yMax1 = cell1.y - 1 + (cell1.rowSpan || 1); - let yMin2 = cell2.y; - let yMax2 = cell2.y - 1 + (cell2.rowSpan || 1); - let yConflict = !(yMin1 > yMax2 || yMin2 > yMax1); - - let xMin1 = cell1.x; - let xMax1 = cell1.x - 1 + (cell1.colSpan || 1); - let xMin2 = cell2.x; - let xMax2 = cell2.x - 1 + (cell2.colSpan || 1); - let xConflict = !(xMin1 > xMax2 || xMin2 > xMax1); - - return yConflict && xConflict; - } - - function conflictExists(rows, x, y) { - let i_max = Math.min(rows.length - 1, y); - let cell = { x: x, y: y }; - for (let i = 0; i <= i_max; i++) { - let row = rows[i]; - for (let j = 0; j < row.length; j++) { - if (cellsConflict(cell, row[j])) { - return true; - } - } - } - return false; - } - - function allBlank(rows, y, xMin, xMax) { - for (let x = xMin; x < xMax; x++) { - if (conflictExists(rows, x, y)) { - return false; - } - } - return true; - } - - function addRowSpanCells(table) { - table.forEach(function (row, rowIndex) { - row.forEach(function (cell) { - for (let i = 1; i < cell.rowSpan; i++) { - let rowSpanCell = new RowSpanCell(cell); - rowSpanCell.x = cell.x; - rowSpanCell.y = cell.y + i; - rowSpanCell.colSpan = cell.colSpan; - insertCell(rowSpanCell, table[rowIndex + i]); - } - }); - }); - } - - function addColSpanCells(cellRows) { - for (let rowIndex = cellRows.length - 1; rowIndex >= 0; rowIndex--) { - let cellColumns = cellRows[rowIndex]; - for (let columnIndex = 0; columnIndex < cellColumns.length; columnIndex++) { - let cell = cellColumns[columnIndex]; - for (let k = 1; k < cell.colSpan; k++) { - let colSpanCell = new ColSpanCell(); - colSpanCell.x = cell.x + k; - colSpanCell.y = cell.y; - cellColumns.splice(columnIndex + 1, 0, colSpanCell); - } - } - } - } - - function insertCell(cell, row) { - let x = 0; - while (x < row.length && row[x].x < cell.x) { - x++; - } - row.splice(x, 0, cell); - } - - function fillInTable(table) { - let h_max = maxHeight(table); - let w_max = maxWidth(table); - debug(`Max rows: ${h_max}; Max cols: ${w_max}`); - for (let y = 0; y < h_max; y++) { - for (let x = 0; x < w_max; x++) { - if (!conflictExists(table, x, y)) { - let opts = { x: x, y: y, colSpan: 1, rowSpan: 1 }; - x++; - while (x < w_max && !conflictExists(table, x, y)) { - opts.colSpan++; - x++; - } - let y2 = y + 1; - while (y2 < h_max && allBlank(table, y2, opts.x, opts.x + opts.colSpan)) { - opts.rowSpan++; - y2++; - } - let cell = new Cell(opts); - cell.x = opts.x; - cell.y = opts.y; - warn(`Missing cell at ${cell.y}-${cell.x}.`); - insertCell(cell, table[y]); - } - } - } - } - - function generateCells(rows) { - return rows.map(function (row) { - if (!Array.isArray(row)) { - let key = Object.keys(row)[0]; - row = row[key]; - if (Array.isArray(row)) { - row = row.slice(); - row.unshift(key); - } else { - row = [key, row]; - } - } - return row.map(function (cell) { - return new Cell(cell); - }); - }); - } - - function makeTableLayout(rows) { - let cellRows = generateCells(rows); - layoutTable(cellRows); - fillInTable(cellRows); - addRowSpanCells(cellRows); - addColSpanCells(cellRows); - return cellRows; - } - - module.exports = { - makeTableLayout: makeTableLayout, - layoutTable: layoutTable, - addRowSpanCells: addRowSpanCells, - maxWidth: maxWidth, - fillInTable: fillInTable, - computeWidths: makeComputeWidths('colSpan', 'desiredWidth', 'x', 1), - computeHeights: makeComputeWidths('rowSpan', 'desiredHeight', 'y', 1), - }; -})(); - -function makeComputeWidths(colSpan, desiredWidth, x, forcedMin) { - return function (vals, table) { - let result = []; - let spanners = []; - let auto = {}; - table.forEach(function (row) { - row.forEach(function (cell) { - if ((cell[colSpan] || 1) > 1) { - spanners.push(cell); - } else { - result[cell[x]] = Math.max(result[cell[x]] || 0, cell[desiredWidth] || 0, forcedMin); - } - }); - }); - - vals.forEach(function (val, index) { - if (typeof val === 'number') { - result[index] = val; - } - }); - - //spanners.forEach(function(cell){ - for (let k = spanners.length - 1; k >= 0; k--) { - let cell = spanners[k]; - let span = cell[colSpan]; - let col = cell[x]; - let existingWidth = result[col]; - let editableCols = typeof vals[col] === 'number' ? 0 : 1; - if (typeof existingWidth === 'number') { - for (let i = 1; i < span; i++) { - existingWidth += 1 + result[col + i]; - if (typeof vals[col + i] !== 'number') { - editableCols++; - } - } - } else { - existingWidth = desiredWidth === 'desiredWidth' ? cell.desiredWidth - 1 : 1; - if (!auto[col] || auto[col] < existingWidth) { - auto[col] = existingWidth; - } - } - - if (cell[desiredWidth] > existingWidth) { - let i = 0; - while (editableCols > 0 && cell[desiredWidth] > existingWidth) { - if (typeof vals[col + i] !== 'number') { - let dif = Math.round((cell[desiredWidth] - existingWidth) / editableCols); - existingWidth += dif; - result[col + i] += dif; - editableCols--; - } - i++; - } - } - } - - Object.assign(vals, result, auto); - for (let j = 0; j < vals.length; j++) { - vals[j] = Math.max(forcedMin, vals[j] || 0); - } - }; -} diff --git a/node_modules/cli-table3/src/table.js b/node_modules/cli-table3/src/table.js deleted file mode 100644 index eb4a9bda9a364..0000000000000 --- a/node_modules/cli-table3/src/table.js +++ /dev/null @@ -1,106 +0,0 @@ -const debug = require('./debug'); -const utils = require('./utils'); -const tableLayout = require('./layout-manager'); - -class Table extends Array { - constructor(opts) { - super(); - - const options = utils.mergeOptions(opts); - Object.defineProperty(this, 'options', { - value: options, - enumerable: options.debug, - }); - - if (options.debug) { - switch (typeof options.debug) { - case 'boolean': - debug.setDebugLevel(debug.WARN); - break; - case 'number': - debug.setDebugLevel(options.debug); - break; - case 'string': - debug.setDebugLevel(parseInt(options.debug, 10)); - break; - default: - debug.setDebugLevel(debug.WARN); - debug.warn(`Debug option is expected to be boolean, number, or string. Received a ${typeof options.debug}`); - } - Object.defineProperty(this, 'messages', { - get() { - return debug.debugMessages(); - }, - }); - } - } - - toString() { - let array = this; - let headersPresent = this.options.head && this.options.head.length; - if (headersPresent) { - array = [this.options.head]; - if (this.length) { - array.push.apply(array, this); - } - } else { - this.options.style.head = []; - } - - let cells = tableLayout.makeTableLayout(array); - - cells.forEach(function (row) { - row.forEach(function (cell) { - cell.mergeTableOptions(this.options, cells); - }, this); - }, this); - - tableLayout.computeWidths(this.options.colWidths, cells); - tableLayout.computeHeights(this.options.rowHeights, cells); - - cells.forEach(function (row) { - row.forEach(function (cell) { - cell.init(this.options); - }, this); - }, this); - - let result = []; - - for (let rowIndex = 0; rowIndex < cells.length; rowIndex++) { - let row = cells[rowIndex]; - let heightOfRow = this.options.rowHeights[rowIndex]; - - if (rowIndex === 0 || !this.options.style.compact || (rowIndex == 1 && headersPresent)) { - doDraw(row, 'top', result); - } - - for (let lineNum = 0; lineNum < heightOfRow; lineNum++) { - doDraw(row, lineNum, result); - } - - if (rowIndex + 1 == cells.length) { - doDraw(row, 'bottom', result); - } - } - - return result.join('\n'); - } - - get width() { - let str = this.toString().split('\n'); - return str[0].length; - } -} - -Table.reset = () => debug.reset(); - -function doDraw(row, lineNum, result) { - let line = []; - row.forEach(function (cell) { - line.push(cell.draw(lineNum)); - }); - let str = line.join(''); - if (str.length) result.push(str); -} - -module.exports = Table; diff --git a/node_modules/cli-table3/src/utils.js b/node_modules/cli-table3/src/utils.js deleted file mode 100644 index c922c5b9adb62..0000000000000 --- a/node_modules/cli-table3/src/utils.js +++ /dev/null @@ -1,336 +0,0 @@ -const stringWidth = require('string-width'); - -function codeRegex(capture) { - return capture ? /\u001b\[((?:\d*;){0,5}\d*)m/g : /\u001b\[(?:\d*;){0,5}\d*m/g; -} - -function strlen(str) { - let code = codeRegex(); - let stripped = ('' + str).replace(code, ''); - let split = stripped.split('\n'); - return split.reduce(function (memo, s) { - return stringWidth(s) > memo ? stringWidth(s) : memo; - }, 0); -} - -function repeat(str, times) { - return Array(times + 1).join(str); -} - -function pad(str, len, pad, dir) { - let length = strlen(str); - if (len + 1 >= length) { - let padlen = len - length; - switch (dir) { - case 'right': { - str = repeat(pad, padlen) + str; - break; - } - case 'center': { - let right = Math.ceil(padlen / 2); - let left = padlen - right; - str = repeat(pad, left) + str + repeat(pad, right); - break; - } - default: { - str = str + repeat(pad, padlen); - break; - } - } - } - return str; -} - -let codeCache = {}; - -function addToCodeCache(name, on, off) { - on = '\u001b[' + on + 'm'; - off = '\u001b[' + off + 'm'; - codeCache[on] = { set: name, to: true }; - codeCache[off] = { set: name, to: false }; - codeCache[name] = { on: on, off: off }; -} - -//https://github.com/Marak/colors.js/blob/master/lib/styles.js -addToCodeCache('bold', 1, 22); -addToCodeCache('italics', 3, 23); -addToCodeCache('underline', 4, 24); -addToCodeCache('inverse', 7, 27); -addToCodeCache('strikethrough', 9, 29); - -function updateState(state, controlChars) { - let controlCode = controlChars[1] ? parseInt(controlChars[1].split(';')[0]) : 0; - if ((controlCode >= 30 && controlCode <= 39) || (controlCode >= 90 && controlCode <= 97)) { - state.lastForegroundAdded = controlChars[0]; - return; - } - if ((controlCode >= 40 && controlCode <= 49) || (controlCode >= 100 && controlCode <= 107)) { - state.lastBackgroundAdded = controlChars[0]; - return; - } - if (controlCode === 0) { - for (let i in state) { - /* istanbul ignore else */ - if (Object.prototype.hasOwnProperty.call(state, i)) { - delete state[i]; - } - } - return; - } - let info = codeCache[controlChars[0]]; - if (info) { - state[info.set] = info.to; - } -} - -function readState(line) { - let code = codeRegex(true); - let controlChars = code.exec(line); - let state = {}; - while (controlChars !== null) { - updateState(state, controlChars); - controlChars = code.exec(line); - } - return state; -} - -function unwindState(state, ret) { - let lastBackgroundAdded = state.lastBackgroundAdded; - let lastForegroundAdded = state.lastForegroundAdded; - - delete state.lastBackgroundAdded; - delete state.lastForegroundAdded; - - Object.keys(state).forEach(function (key) { - if (state[key]) { - ret += codeCache[key].off; - } - }); - - if (lastBackgroundAdded && lastBackgroundAdded != '\u001b[49m') { - ret += '\u001b[49m'; - } - if (lastForegroundAdded && lastForegroundAdded != '\u001b[39m') { - ret += '\u001b[39m'; - } - - return ret; -} - -function rewindState(state, ret) { - let lastBackgroundAdded = state.lastBackgroundAdded; - let lastForegroundAdded = state.lastForegroundAdded; - - delete state.lastBackgroundAdded; - delete state.lastForegroundAdded; - - Object.keys(state).forEach(function (key) { - if (state[key]) { - ret = codeCache[key].on + ret; - } - }); - - if (lastBackgroundAdded && lastBackgroundAdded != '\u001b[49m') { - ret = lastBackgroundAdded + ret; - } - if (lastForegroundAdded && lastForegroundAdded != '\u001b[39m') { - ret = lastForegroundAdded + ret; - } - - return ret; -} - -function truncateWidth(str, desiredLength) { - if (str.length === strlen(str)) { - return str.substr(0, desiredLength); - } - - while (strlen(str) > desiredLength) { - str = str.slice(0, -1); - } - - return str; -} - -function truncateWidthWithAnsi(str, desiredLength) { - let code = codeRegex(true); - let split = str.split(codeRegex()); - let splitIndex = 0; - let retLen = 0; - let ret = ''; - let myArray; - let state = {}; - - while (retLen < desiredLength) { - myArray = code.exec(str); - let toAdd = split[splitIndex]; - splitIndex++; - if (retLen + strlen(toAdd) > desiredLength) { - toAdd = truncateWidth(toAdd, desiredLength - retLen); - } - ret += toAdd; - retLen += strlen(toAdd); - - if (retLen < desiredLength) { - if (!myArray) { - break; - } // full-width chars may cause a whitespace which cannot be filled - ret += myArray[0]; - updateState(state, myArray); - } - } - - return unwindState(state, ret); -} - -function truncate(str, desiredLength, truncateChar) { - truncateChar = truncateChar || '…'; - let lengthOfStr = strlen(str); - if (lengthOfStr <= desiredLength) { - return str; - } - desiredLength -= strlen(truncateChar); - - let ret = truncateWidthWithAnsi(str, desiredLength); - - return ret + truncateChar; -} - -function defaultOptions() { - return { - chars: { - top: '─', - 'top-mid': '┬', - 'top-left': '┌', - 'top-right': '┐', - bottom: '─', - 'bottom-mid': '┴', - 'bottom-left': '└', - 'bottom-right': '┘', - left: '│', - 'left-mid': '├', - mid: '─', - 'mid-mid': '┼', - right: '│', - 'right-mid': '┤', - middle: '│', - }, - truncate: '…', - colWidths: [], - rowHeights: [], - colAligns: [], - rowAligns: [], - style: { - 'padding-left': 1, - 'padding-right': 1, - head: ['red'], - border: ['grey'], - compact: false, - }, - head: [], - }; -} - -function mergeOptions(options, defaults) { - options = options || {}; - defaults = defaults || defaultOptions(); - let ret = Object.assign({}, defaults, options); - ret.chars = Object.assign({}, defaults.chars, options.chars); - ret.style = Object.assign({}, defaults.style, options.style); - return ret; -} - -// Wrap on word boundary -function wordWrap(maxLength, input) { - let lines = []; - let split = input.split(/(\s+)/g); - let line = []; - let lineLength = 0; - let whitespace; - for (let i = 0; i < split.length; i += 2) { - let word = split[i]; - let newLength = lineLength + strlen(word); - if (lineLength > 0 && whitespace) { - newLength += whitespace.length; - } - if (newLength > maxLength) { - if (lineLength !== 0) { - lines.push(line.join('')); - } - line = [word]; - lineLength = strlen(word); - } else { - line.push(whitespace || '', word); - lineLength = newLength; - } - whitespace = split[i + 1]; - } - if (lineLength) { - lines.push(line.join('')); - } - return lines; -} - -// Wrap text (ignoring word boundaries) -function textWrap(maxLength, input) { - let lines = []; - let line = ''; - function pushLine(str, ws) { - if (line.length && ws) line += ws; - line += str; - while (line.length > maxLength) { - lines.push(line.slice(0, maxLength)); - line = line.slice(maxLength); - } - } - let split = input.split(/(\s+)/g); - for (let i = 0; i < split.length; i += 2) { - pushLine(split[i], i && split[i - 1]); - } - if (line.length) lines.push(line); - return lines; -} - -function multiLineWordWrap(maxLength, input, wrapOnWordBoundary = true) { - let output = []; - input = input.split('\n'); - const handler = wrapOnWordBoundary ? wordWrap : textWrap; - for (let i = 0; i < input.length; i++) { - output.push.apply(output, handler(maxLength, input[i])); - } - return output; -} - -function colorizeLines(input) { - let state = {}; - let output = []; - for (let i = 0; i < input.length; i++) { - let line = rewindState(state, input[i]); - state = readState(line); - let temp = Object.assign({}, state); - output.push(unwindState(temp, line)); - } - return output; -} - -/** - * Credit: Matheus Sampaio https://github.com/matheussampaio - */ -function hyperlink(url, text) { - const OSC = '\u001B]'; - const BEL = '\u0007'; - const SEP = ';'; - - return [OSC, '8', SEP, SEP, url || text, BEL, text, OSC, '8', SEP, SEP, BEL].join(''); -} - -module.exports = { - strlen: strlen, - repeat: repeat, - pad: pad, - truncate: truncate, - mergeOptions: mergeOptions, - wordWrap: multiLineWordWrap, - colorizeLines: colorizeLines, - hyperlink, -}; diff --git a/package-lock.json b/package-lock.json index ae6ee87388514..5c73befceed2d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,7 +24,6 @@ "chalk", "ci-info", "cli-columns", - "cli-table3", "columnify", "fastest-levenshtein", "fs-minipass", @@ -105,7 +104,6 @@ "chalk": "^5.3.0", "ci-info": "^4.0.0", "cli-columns": "^4.0.0", - "cli-table3": "^0.6.4", "columnify": "^1.6.0", "fastest-levenshtein": "^1.0.16", "fs-minipass": "^3.0.3", @@ -176,6 +174,7 @@ "ajv": "^8.12.0", "ajv-formats": "^2.1.1", "ajv-formats-draft2019": "^1.6.1", + "cli-table3": "^0.6.4", "diff": "^5.2.0", "licensee": "^10.0.0", "nock": "^13.4.0", @@ -698,7 +697,7 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "inBundle": true, + "dev": true, "optional": true, "engines": { "node": ">=0.1.90" @@ -3261,7 +3260,7 @@ "version": "0.6.4", "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.4.tgz", "integrity": "sha512-Lm3L0p+/npIQWNIiyF/nAn7T5dnOwR3xNTHXYEBFBFVPXzCVNZ5lqEC/1eo/EVfpDsQ1I+TX4ORPQgp+UI0CRw==", - "inBundle": true, + "dev": true, "dependencies": { "string-width": "^4.2.0" }, diff --git a/package.json b/package.json index 7090dd882e276..7a8212d5f056e 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,6 @@ "chalk": "^5.3.0", "ci-info": "^4.0.0", "cli-columns": "^4.0.0", - "cli-table3": "^0.6.4", "columnify": "^1.6.0", "fastest-levenshtein": "^1.0.16", "fs-minipass": "^3.0.3", @@ -140,7 +139,6 @@ "chalk", "ci-info", "cli-columns", - "cli-table3", "columnify", "fastest-levenshtein", "fs-minipass", @@ -207,6 +205,7 @@ "ajv": "^8.12.0", "ajv-formats": "^2.1.1", "ajv-formats-draft2019": "^1.6.1", + "cli-table3": "^0.6.4", "diff": "^5.2.0", "licensee": "^10.0.0", "nock": "^13.4.0", diff --git a/tap-snapshots/test/lib/commands/doctor.js.test.cjs b/tap-snapshots/test/lib/commands/doctor.js.test.cjs index ded43c37a693f..985d76e5d12a5 100644 --- a/tap-snapshots/test/lib/commands/doctor.js.test.cjs +++ b/tap-snapshots/test/lib/commands/doctor.js.test.cjs @@ -30,35 +30,69 @@ Object { ` exports[`test/lib/commands/doctor.js TAP all clear > output 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP all clear in color > everything is ok in color 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP all clear in color > logs 1`] = ` @@ -110,35 +144,70 @@ Object { ` exports[`test/lib/commands/doctor.js TAP bad proxy > output 1`] = ` -Check Value Recommendation/Notes -npm ping not ok Invalid protocol \`ssh:\` connecting to proxy \`npmjs.org\` -npm -v not ok Error: Invalid protocol \`ssh:\` connecting to proxy \`npmjs.org\` -node -v not ok Error: Invalid protocol \`ssh:\` connecting to proxy \`npmjs.org\` -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Not ok +Invalid protocol \`ssh:\` connecting to proxy \`npmjs.org\` +Checking npm version +Not ok +Error: Invalid protocol \`ssh:\` connecting to proxy \`npmjs.org\` +Checking node version +Not ok +Error: Invalid protocol \`ssh:\` connecting to proxy \`npmjs.org\` +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP cacache badContent > corrupted cache content 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 2 tarballs +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 2 tarballs ` exports[`test/lib/commands/doctor.js TAP cacache badContent > logs 1`] = ` @@ -196,35 +265,69 @@ Object { ` exports[`test/lib/commands/doctor.js TAP cacache missingContent > missing content 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 2 tarballs +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 2 tarballs ` exports[`test/lib/commands/doctor.js TAP cacache reclaimedCount > content garbage collected 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 2 tarballs +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 2 tarballs ` exports[`test/lib/commands/doctor.js TAP cacache reclaimedCount > logs 1`] = ` @@ -274,9 +377,11 @@ Object { ` exports[`test/lib/commands/doctor.js TAP discrete checks cache > output 1`] = ` -Check Value Recommendation/Notes -Perms check on cached files ok -Verify cache contents ok verified 0 tarballs +Checking permissions on cached files (this may take awhile) +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP discrete checks git > logs 1`] = ` @@ -290,7 +395,7 @@ Object { ` exports[`test/lib/commands/doctor.js TAP discrete checks git > output 1`] = ` -Check Value Recommendation/Notes + ` exports[`test/lib/commands/doctor.js TAP discrete checks invalid environment > logs 1`] = ` @@ -306,9 +411,12 @@ Object { ` exports[`test/lib/commands/doctor.js TAP discrete checks invalid environment > output 1`] = ` -Check Value Recommendation/Notes -git executable in PATH ok /path/to/git -global bin folder in PATH not ok Error: Add {CWD}/global/bin to your $PATH +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Not ok +Error: Add {CWD}/global/bin to your $PATH ` exports[`test/lib/commands/doctor.js TAP discrete checks permissions - not windows > logs 1`] = ` @@ -322,12 +430,16 @@ Object { ` exports[`test/lib/commands/doctor.js TAP discrete checks permissions - not windows > output 1`] = ` -Check Value Recommendation/Notes -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok ` exports[`test/lib/commands/doctor.js TAP discrete checks permissions - windows > logs 1`] = ` @@ -341,7 +453,7 @@ Object { ` exports[`test/lib/commands/doctor.js TAP discrete checks permissions - windows > output 1`] = ` -Check Value Recommendation/Notes + ` exports[`test/lib/commands/doctor.js TAP discrete checks ping > logs 1`] = ` @@ -356,8 +468,8 @@ Object { ` exports[`test/lib/commands/doctor.js TAP discrete checks ping > output 1`] = ` -Check Value Recommendation/Notes -npm ping ok +Connecting to the registry +Ok ` exports[`test/lib/commands/doctor.js TAP discrete checks registry > logs 1`] = ` @@ -372,9 +484,11 @@ Object { ` exports[`test/lib/commands/doctor.js TAP discrete checks registry > output 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm config get registry ok using default registry (https://registry.npmjs.org/) +Connecting to the registry +Ok +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) ` exports[`test/lib/commands/doctor.js TAP discrete checks versions > logs 1`] = ` @@ -390,9 +504,12 @@ Object { ` exports[`test/lib/commands/doctor.js TAP discrete checks versions > output 1`] = ` -Check Value Recommendation/Notes -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 ` exports[`test/lib/commands/doctor.js TAP error reading directory > logs 1`] = ` @@ -426,35 +543,75 @@ Object { ` exports[`test/lib/commands/doctor.js TAP error reading directory > readdir error 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files not ok Check the permissions of files in {CWD}/cache (should be owned by current user) -Perms check on local node_modules not ok Check the permissions of files in {CWD}/prefix/node_modules (should be owned by current user) -Perms check on global node_modules not ok Check the permissions of files in {CWD}/global/node_modules -Perms check on local bin folder not ok Check the permissions of files in {CWD}/prefix/node_modules/.bin -Perms check on global bin folder not ok Check the permissions of files in {CWD}/global/bin -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Not ok +Check the permissions of files in {CWD}/cache (should be owned by current user) +Checking permissions on local node_modules (this may take awhile) +Not ok +Check the permissions of files in {CWD}/prefix/node_modules (should be owned by current user) +Checking permissions on global node_modules (this may take awhile) +Not ok +Check the permissions of files in {CWD}/global/node_modules +Checking permissions on local bin folder +Not ok +Check the permissions of files in {CWD}/prefix/node_modules/.bin +Checking permissions on global bin folder +Not ok +Check the permissions of files in {CWD}/global/bin +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP incorrect owner > incorrect owner 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files not ok Check the permissions of files in {CWD}/cache (should be owned by current user) -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Not ok +Check the permissions of files in {CWD}/cache (should be owned by current user) +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP incorrect owner > logs 1`] = ` @@ -484,19 +641,41 @@ Object { ` exports[`test/lib/commands/doctor.js TAP incorrect permissions > incorrect owner 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files not ok Check the permissions of files in {CWD}/cache (should be owned by current user) -Perms check on local node_modules not ok Check the permissions of files in {CWD}/prefix/node_modules (should be owned by current user) -Perms check on global node_modules not ok Check the permissions of files in {CWD}/global/node_modules -Perms check on local bin folder not ok Check the permissions of files in {CWD}/prefix/node_modules/.bin -Perms check on global bin folder not ok Check the permissions of files in {CWD}/global/bin -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Not ok +Check the permissions of files in {CWD}/cache (should be owned by current user) +Checking permissions on local node_modules (this may take awhile) +Not ok +Check the permissions of files in {CWD}/prefix/node_modules (should be owned by current user) +Checking permissions on global node_modules (this may take awhile) +Not ok +Check the permissions of files in {CWD}/global/node_modules +Checking permissions on local bin folder +Not ok +Check the permissions of files in {CWD}/prefix/node_modules/.bin +Checking permissions on global bin folder +Not ok +Check the permissions of files in {CWD}/global/bin +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP incorrect permissions > logs 1`] = ` @@ -553,8 +732,8 @@ Object { String( doctor getGitPath Error: test error doctor at which ({CWD}/{TESTDIR}/doctor.js:313:15) - doctor at Doctor.getGitPath ({CWD}/lib/commands/doctor.js:300:18) - doctor at Doctor.exec ({CWD}/lib/commands/doctor.js:130:40) + doctor at Doctor.getGitPath ({CWD}/lib/commands/doctor.js:286:18) + doctor at Doctor.exec ({CWD}/lib/commands/doctor.js:125:33) doctor at processTicksAndRejections (node:internal/process/task_queues:95:5) doctor at MockNpm.exec ({CWD}/test/fixtures/mock-npm.js:80:26) ), @@ -563,19 +742,36 @@ Object { ` exports[`test/lib/commands/doctor.js TAP missing git > missing git 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH not ok Error: Install git and ensure it's in your PATH. -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Not ok +Error: Install git and ensure it's in your PATH. +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP missing global directories > logs 1`] = ` @@ -606,19 +802,38 @@ Object { ` exports[`test/lib/commands/doctor.js TAP missing global directories > missing global directories 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules not ok Check the permissions of files in {CWD}/global/node_modules -Perms check on local bin folder ok -Perms check on global bin folder not ok Check the permissions of files in {CWD}/global/bin -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Not ok +Check the permissions of files in {CWD}/global/node_modules +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Not ok +Check the permissions of files in {CWD}/global/bin +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP missing local node_modules > logs 1`] = ` @@ -646,19 +861,36 @@ Object { ` exports[`test/lib/commands/doctor.js TAP missing local node_modules > missing local node_modules 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP node out of date - current > logs 1`] = ` @@ -686,19 +918,36 @@ Object { ` exports[`test/lib/commands/doctor.js TAP node out of date - current > node is out of date 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v not ok Use node v2.0.1 (current: v2.0.0) -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Not ok +Use node v2.0.1 (current: v2.0.0) +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP node out of date - lts > logs 1`] = ` @@ -726,19 +975,36 @@ Object { ` exports[`test/lib/commands/doctor.js TAP node out of date - lts > node is out of date 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v not ok Use node v1.0.0 (current: v0.0.1) -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Not ok +Use node v1.0.0 (current: v0.0.1) +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP non-default registry > logs 1`] = ` @@ -766,19 +1032,36 @@ Object { ` exports[`test/lib/commands/doctor.js TAP non-default registry > non default registry 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry not ok Try \`npm config set registry=https://registry.npmjs.org/\` -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Not ok +Try \`npm config set registry=https://registry.npmjs.org/\` +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP npm out of date > logs 1`] = ` @@ -806,19 +1089,36 @@ Object { ` exports[`test/lib/commands/doctor.js TAP npm out of date > npm is out of date 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v not ok Use npm v2.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Ok +Checking npm version +Not ok +Use npm v2.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP ping 404 > logs 1`] = ` @@ -846,19 +1146,37 @@ Object { ` exports[`test/lib/commands/doctor.js TAP ping 404 > ping 404 1`] = ` -Check Value Recommendation/Notes -npm ping not ok 404 404 Not Found - GET https://registry.npmjs.org/-/ping?write=true -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Not ok +404 404 Not Found - GET https://registry.npmjs.org/-/ping?write=true +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP ping 404 in color > logs 1`] = ` @@ -886,19 +1204,37 @@ Object { ` exports[`test/lib/commands/doctor.js TAP ping 404 in color > ping 404 in color 1`] = ` -Check Value Recommendation/Notes -npm ping not ok 404 404 Not Found - GET https://registry.npmjs.org/-/ping?write=true -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Not ok +404 404 Not Found - GET https://registry.npmjs.org/-/ping?write=true +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP ping exception with code > logs 1`] = ` @@ -926,19 +1262,37 @@ Object { ` exports[`test/lib/commands/doctor.js TAP ping exception with code > ping failure 1`] = ` -Check Value Recommendation/Notes -npm ping not ok request to https://registry.npmjs.org/-/ping?write=true failed, reason: Test Error -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Not ok +request to https://registry.npmjs.org/-/ping?write=true failed, reason: Test Error +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP ping exception without code > logs 1`] = ` @@ -966,19 +1320,37 @@ Object { ` exports[`test/lib/commands/doctor.js TAP ping exception without code > ping failure 1`] = ` -Check Value Recommendation/Notes -npm ping not ok request to https://registry.npmjs.org/-/ping?write=true failed, reason: Test Error -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Not ok +request to https://registry.npmjs.org/-/ping?write=true failed, reason: Test Error +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP silent errors > logs 1`] = ` @@ -1021,11 +1393,21 @@ Object { ` exports[`test/lib/commands/doctor.js TAP windows skips permissions checks > no permissions checks 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global ` diff --git a/tap-snapshots/test/lib/commands/profile.js.test.cjs b/tap-snapshots/test/lib/commands/profile.js.test.cjs index 4530dbf95cec2..1fbb09de29f3c 100644 --- a/tap-snapshots/test/lib/commands/profile.js.test.cjs +++ b/tap-snapshots/test/lib/commands/profile.js.test.cjs @@ -31,19 +31,6 @@ exports[`test/lib/commands/profile.js TAP profile get multiple args default outp foo foo@github.com (verified) https://github.com/npm ` -exports[`test/lib/commands/profile.js TAP profile get no args --color > should output all profile info with color result 1`] = ` -name: foo -email: foo@github.com (verified) -two-factor auth: auth-and-writes -fullname: Foo Bar -homepage: https://github.com -freenode: foobar -twitter: https://twitter.com/npmjs -github: https://github.com/npm -created: 2015-02-26T01:26:37.384Z -updated: 2020-08-12T16:19:35.326Z -` - exports[`test/lib/commands/profile.js TAP profile get no args --parseable > should output all profile info as parseable result 1`] = ` tfa auth-and-writes name foo diff --git a/tap-snapshots/test/lib/docs.js.test.cjs b/tap-snapshots/test/lib/docs.js.test.cjs index ad20cfa5069e0..671e614851074 100644 --- a/tap-snapshots/test/lib/docs.js.test.cjs +++ b/tap-snapshots/test/lib/docs.js.test.cjs @@ -2958,7 +2958,7 @@ exports[`test/lib/docs.js TAP usage doctor > must match snapshot 1`] = ` Check the health of your npm environment Usage: -npm doctor [ping] [registry] [versions] [environment] [permissions] [cache] +npm doctor [connection] [registry] [versions] [environment] [permissions] [cache] Options: [--registry ] @@ -2966,7 +2966,7 @@ Options: Run "npm help doctor" for more info \`\`\`bash -npm doctor [ping] [registry] [versions] [environment] [permissions] [cache] +npm doctor [connection] [registry] [versions] [environment] [permissions] [cache] \`\`\` Note: This command is unaware of workspaces. diff --git a/tap-snapshots/test/lib/utils/reify-output.js.test.cjs b/tap-snapshots/test/lib/utils/reify-output.js.test.cjs index 5983ac224e26e..d653d4c1fadc0 100644 --- a/tap-snapshots/test/lib/utils/reify-output.js.test.cjs +++ b/tap-snapshots/test/lib/utils/reify-output.js.test.cjs @@ -1634,19 +1634,17 @@ exports[`test/lib/utils/reify-output.js TAP packages changed message > {"added" ` exports[`test/lib/utils/reify-output.js TAP prints dedupe difference on dry-run > diff table 1`] = ` - -change bar 1.0.0 -> 2.1.0 -remove bar 1.0.0 -add foo 1.0.0 +change bar 1.0.0 => 2.1.0 +remove bar 1.0.0 +add foo 1.0.0 removed 1 package, and changed 1 package in {TIME} ` exports[`test/lib/utils/reify-output.js TAP prints dedupe difference on long > diff table 1`] = ` - -change bar 1.0.0 -> 2.1.0 -remove bar 1.0.0 -add foo 1.0.0 +change bar 1.0.0 => 2.1.0 +remove bar 1.0.0 +add foo 1.0.0 removed 1 package, and changed 1 package in {TIME} ` diff --git a/test/lib/commands/hook.js b/test/lib/commands/hook.js index a93b0c99f5267..003dae647a35a 100644 --- a/test/lib/commands/hook.js +++ b/test/lib/commands/hook.js @@ -1,6 +1,5 @@ const t = require('tap') const mockNpm = require('../../fixtures/mock-npm') -const { stripVTControlCharacters } = require('node:util') const mockHook = async (t, { hookResponse, ...npmOpts } = {}) => { const now = Date.now() @@ -31,6 +30,7 @@ const mockHook = async (t, { hookResponse, ...npmOpts } = {}) => { type: pkgTypes[name], endpoint: 'https://google.com', last_delivery: id % 2 === 0 ? now : undefined, + response_code: 200, })) }, rm: async (id, opts) => { @@ -243,11 +243,18 @@ t.test('npm hook ls', async t => { }, 'received the correct arguments' ) - t.equal(outputs[0], 'You have 3 hooks configured.', 'prints the correct header') - const out = stripVTControlCharacters(outputs[1]) - t.match(out, /semver.*https:\/\/google.com.*\n.*\n.*never triggered/, 'prints package hook') - t.match(out, /@npmcli.*https:\/\/google.com.*\n.*\n.*triggered just now/, 'prints scope hook') - t.match(out, /~npm.*https:\/\/google.com.*\n.*\n.*never triggered/, 'prints owner hook') + t.strictSame(outputs, [ + 'You have 3 hooks configured.', + 'Hook 1: semver', + 'Endpoint: https://google.com', + 'Never triggered\n', + 'Hook 2: @npmcli', + 'Endpoint: https://google.com', + 'Triggered just now, response code was "200"\n', + 'Hook 3: ~npm', + 'Endpoint: https://google.com', + 'Never triggered\n', + ]) }) t.test('npm hook ls, no results', async t => { @@ -266,7 +273,7 @@ t.test('npm hook ls, no results', async t => { }, 'received the correct arguments' ) - t.equal(outputs[0], "You don't have any hooks configured yet.", 'prints the correct result') + t.strictSame(outputs, [`You don't have any hooks configured yet.`]) }) t.test('npm hook ls, single result', async t => { @@ -292,9 +299,12 @@ t.test('npm hook ls, single result', async t => { }, 'received the correct arguments' ) - t.equal(outputs[0], 'You have one hook configured.', 'prints the correct header') - const out = stripVTControlCharacters(outputs[1]) - t.match(out, /semver.*https:\/\/google.com.*\n.*\n.*never triggered/, 'prints package hook') + t.strictSame(outputs, [ + 'You have 1 hook configured.', + 'Hook 1: semver', + 'Endpoint: https://google.com', + 'Never triggered\n', + ]) }) t.test('npm hook ls - json output', async t => { @@ -363,10 +373,10 @@ t.test('npm hook ls - parseable output', async t => { t.strictSame( outputs.map(line => line.split(/\t/)), [ - ['id', 'name', 'type', 'endpoint', 'last_delivery'], - ['1', 'semver', 'package', 'https://google.com', ''], - ['2', '@npmcli', 'scope', 'https://google.com', `${now}`], - ['3', 'npm', 'owner', 'https://google.com', ''], + ['id', 'name', 'type', 'endpoint', 'last_delivery', 'response_code'], + ['1', 'semver', 'package', 'https://google.com', '', '200'], + ['2', '@npmcli', 'scope', 'https://google.com', `${now}`, '200'], + ['3', 'npm', 'owner', 'https://google.com', '', '200'], ], 'prints the correct result' ) diff --git a/test/lib/commands/login.js b/test/lib/commands/login.js index b42d3001ebb90..a55637f9e00e2 100644 --- a/test/lib/commands/login.js +++ b/test/lib/commands/login.js @@ -1,12 +1,12 @@ const t = require('tap') -const fs = require('fs') -const path = require('path') +const fs = require('node:fs') +const path = require('node:path') +const stream = require('node:stream') const ini = require('ini') const { load: loadMockNpm } = require('../../fixtures/mock-npm.js') const mockGlobals = require('@npmcli/mock-globals') const MockRegistry = require('@npmcli/mock-registry') -const stream = require('stream') const mockLogin = async (t, { stdin: stdinLines, registry: registryUrl, ...options } = {}) => { let stdin diff --git a/test/lib/commands/org.js b/test/lib/commands/org.js index 576a16d19303d..7a1538d9c69e4 100644 --- a/test/lib/commands/org.js +++ b/test/lib/commands/org.js @@ -1,6 +1,5 @@ const t = require('tap') const mockNpm = require('../../fixtures/mock-npm') -const { stripVTControlCharacters } = require('node:util') const mockOrg = async (t, { orgSize = 1, orgList = {}, ...npmOpts } = {}) => { let setArgs = null @@ -427,10 +426,11 @@ t.test('npm org ls', async t => { }, 'receieved the correct args' ) - const out = stripVTControlCharacters(outputs[0]) - t.match(out, /one.*developer/, 'contains the developer member') - t.match(out, /two.*admin/, 'contains the admin member') - t.match(out, /three.*owner/, 'contains the owner member') + t.strictSame(outputs, [ + 'one - developer', + 'three - owner', + 'two - admin', + ]) }) t.test('npm org ls - user filter', async t => { @@ -452,9 +452,9 @@ t.test('npm org ls - user filter', async t => { }, 'receieved the correct args' ) - const out = stripVTControlCharacters(outputs[0]) - t.match(out, /username.*admin/, 'contains the filtered member') - t.notMatch(out, /missing.*admin/, 'does not contain other members') + t.strictSame(outputs, [ + 'username - admin', + ]) }) t.test('npm org ls - user filter, missing user', async t => { @@ -475,9 +475,7 @@ t.test('npm org ls - user filter, missing user', async t => { }, 'receieved the correct args' ) - const out = stripVTControlCharacters(outputs[0][0]) - t.notMatch(out, /username/, 'does not contain the requested member') - t.notMatch(out, /missing.*admin/, 'does not contain other members') + t.strictSame(outputs, []) }) t.test('npm org ls - no org', async t => { diff --git a/test/lib/commands/profile.js b/test/lib/commands/profile.js index c6cf2a071dcfa..4cf0908aae816 100644 --- a/test/lib/commands/profile.js +++ b/test/lib/commands/profile.js @@ -9,13 +9,6 @@ const mockProfile = async (t, { npmProfile, readUserInfo, qrcode, config, ...opt async createToken () {}, }, 'qrcode-terminal': qrcode || { generate: (url, cb) => cb() }, - 'cli-table3': class extends Array { - toString () { - return this.filter(Boolean) - .map(i => [...Object.entries(i)].map(v => v.join(': '))) - .join('\n') - } - }, '{LIB}/utils/read-user-info.js': readUserInfo || { async password () {}, async otp () {}, @@ -96,16 +89,6 @@ t.test('profile get no args', async t => { t.matchSnapshot(result(), 'should output all profile info as parseable result') }) - t.test('--color', async t => { - const { profile, result } = await mockProfile(t, { - npmProfile: defaultNpmProfile, - config: { color: 'always' }, - }) - - await profile.exec(['get']) - t.matchSnapshot(result(), 'should output all profile info with color result') - }) - t.test('no tfa enabled', async t => { const npmProfile = { async get () { diff --git a/test/lib/commands/token.js b/test/lib/commands/token.js index 33759d01d1b71..1290a5ee9cb17 100644 --- a/test/lib/commands/token.js +++ b/test/lib/commands/token.js @@ -1,33 +1,38 @@ const t = require('tap') -const mockNpm = require('../../fixtures/mock-npm') +const { load: loadMockNpm } = require('../../fixtures/mock-npm.js') +const MockRegistry = require('@npmcli/mock-registry') +const mockGlobals = require('@npmcli/mock-globals') +const stream = require('node:stream') -const mockToken = async (t, { profile, getCredentialsByURI, readUserInfo, ...opts } = {}) => { - const mocks = {} +const authToken = 'abcd1234' +const password = 'this is not really a password' - if (profile) { - mocks['npm-profile'] = profile - } - - if (readUserInfo) { - mocks['{LIB}/utils/read-user-info.js'] = readUserInfo - } - - const mock = await mockNpm(t, { - ...opts, - command: 'token', - mocks, - }) - - // XXX: replace with mock registry - if (getCredentialsByURI) { - mock.npm.config.getCredentialsByURI = getCredentialsByURI - } - - return mock +const auth = { + '//registry.npmjs.org/:_authToken': authToken, } +const now = new Date().toISOString() +const tokens = [ + { + key: 'abcd1234abcd1234', + token: 'efgh5678efgh5678', + cidr_whitelist: null, + readonly: false, + created: now, + updated: now, + }, + { + key: 'abcd1256', + token: 'hgfe8765', + cidr_whitelist: ['192.168.1.1/32'], + readonly: true, + created: now, + updated: now, + }, +] + t.test('completion', async t => { - const { token } = await mockToken(t) + const { token } = await loadMockNpm(t, { command: 'token' }) const testComp = (argv, expect) => { t.resolveMatch(token.completion({ conf: { argv: { remain: argv } } }), expect, argv.join(' ')) @@ -44,476 +49,332 @@ t.test('completion', async t => { }) t.test('token foobar', async t => { - const { token } = await mockToken(t) + const { npm } = await loadMockNpm(t) - await t.rejects(token.exec(['foobar']), /foobar is not a recognized subcommand/) + await t.rejects(npm.exec('token', ['foobar']), /foobar is not a recognized subcommand/) }) t.test('token list', async t => { - const now = new Date().toISOString() - const tokens = [ - { - key: 'abcd1234abcd1234', - token: 'efgh5678efgh5678', - cidr_whitelist: null, - readonly: false, - created: now, - updated: now, - }, - { - key: 'abcd1256', - token: 'hgfe8765', - cidr_whitelist: ['192.168.1.1/32'], - readonly: true, - created: now, - updated: now, - }, - ] - - const { token, joinedOutput } = await mockToken(t, { - config: { registry: 'https://registry.npmjs.org', otp: '123456' }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return { token: 'thisisnotarealtoken' } - }, - profile: { - listTokens: async conf => { - t.same(conf.auth, { token: 'thisisnotarealtoken', otp: '123456' }) - return tokens - }, - }, + const { npm, outputs } = await loadMockNpm(t, { + config: { ...auth }, }) - - await token.exec([]) - - const lines = joinedOutput().split(/\r?\n/) - t.match(lines[3], ' abcd123 ', 'includes the trimmed key') - t.match(lines[3], ' efgh56… ', 'includes the trimmed token') - t.match(lines[3], ` ${now.slice(0, 10)} `, 'includes the trimmed creation timestamp') - t.match(lines[3], ' no ', 'includes the "no" string for readonly state') - t.match(lines[5], ' abcd125 ', 'includes the trimmed key') - t.match(lines[5], ' hgfe87… ', 'includes the trimmed token') - t.match(lines[5], ` ${now.slice(0, 10)} `, 'includes the trimmed creation timestamp') - t.match(lines[5], ' yes ', 'includes the "no" string for readonly state') - t.match(lines[5], ` ${tokens[1].cidr_whitelist.join(',')} `, 'includes the cidr whitelist') + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: authToken, + }) + registry.getTokens(tokens) + await npm.exec('token', []) + t.strictSame(outputs, [ + `Publish token efgh5678efgh5678… with id abcd123 created ${now.slice(0, 10)}`, + '', + `Read only token hgfe8765… with id abcd125 created ${now.slice(0, 10)}`, + 'with IP whitelist: 192.168.1.1/32', + '', + ]) }) t.test('token list json output', async t => { - const now = new Date().toISOString() - const tokens = [ - { - key: 'abcd1234abcd1234', - token: 'efgh5678efgh5678', - cidr_whitelist: null, - readonly: false, - created: now, - updated: now, - }, - ] - - const { token, joinedOutput } = await mockToken(t, { - config: { registry: 'https://registry.npmjs.org', json: true }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return { username: 'foo', password: 'bar' } - }, - profile: { - listTokens: async conf => { - t.same( - conf.auth, - { basic: { username: 'foo', password: 'bar' } }, - 'passes the correct auth' - ) - return tokens - }, + const { npm, joinedOutput } = await loadMockNpm(t, { + config: { + ...auth, + json: true, }, - }) - - await token.exec(['list']) - + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: authToken, + }) + registry.getTokens(tokens) + await npm.exec('token', ['list']) const parsed = JSON.parse(joinedOutput()) t.match(parsed, tokens, 'prints the json parsed tokens') }) t.test('token list parseable output', async t => { - const now = new Date().toISOString() - const tokens = [ - { - key: 'abcd1234abcd1234', - token: 'efgh5678efgh5678', - cidr_whitelist: null, - readonly: false, - created: now, - updated: now, - }, - { - key: 'efgh5678ijkl9101', - token: 'hgfe8765', - cidr_whitelist: ['192.168.1.1/32'], - readonly: true, - created: now, - updated: now, - }, - ] - - const { token, joinedOutput } = await mockToken(t, { - config: { registry: 'https://registry.npmjs.org', parseable: true }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return { auth: Buffer.from('foo:bar').toString('base64') } - }, - profile: { - listTokens: async conf => { - t.same( - conf.auth, - { basic: { username: 'foo', password: 'bar' } }, - 'passes the correct auth' - ) - return tokens - }, + const { npm, outputs } = await loadMockNpm(t, { + config: { + ...auth, + parseable: true, }, }) - - await token.exec(['list']) - - const lines = joinedOutput().split(/\r?\n/) - - t.equal( - lines[0], - ['key', 'token', 'created', 'readonly', 'CIDR whitelist'].join('\t'), - 'prints header' - ) - - t.equal( - lines[1], - [tokens[0].key, tokens[0].token, tokens[0].created, tokens[0].readonly, ''].join('\t'), - 'prints token info' - ) - - t.equal( - lines[2], - [ - tokens[1].key, - tokens[1].token, - tokens[1].created, - tokens[1].readonly, - tokens[1].cidr_whitelist.join(','), - ].join('\t'), - 'prints token info' - ) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: authToken, + }) + registry.getTokens(tokens) + await npm.exec('token', []) + t.strictSame(outputs, [ + 'key\ttoken\tcreated\treadonly\tCIDR whitelist', + `abcd1234abcd1234\tefgh5678efgh5678\t${now}\tfalse\t`, + `abcd1256\thgfe8765\t${now}\ttrue\t192.168.1.1/32`, + ]) }) t.test('token revoke', async t => { - const { token, joinedOutput } = await mockToken(t, { - config: { registry: 'https://registry.npmjs.org' }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return {} - }, - profile: { - listTokens: async conf => { - t.same(conf.auth, {}, 'passes the correct empty auth') - return Promise.resolve([{ key: 'abcd1234' }]) - }, - removeToken: async key => { - t.equal(key, 'abcd1234', 'deletes the correct token') - }, - }, + const { npm, joinedOutput } = await loadMockNpm(t, { + config: { ...auth }, + }) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: authToken, }) - await token.exec(['rm', 'abcd']) + registry.getTokens(tokens) + registry.nock.delete(`/-/npm/v1/tokens/token/${tokens[0].key}`).reply(200) + await npm.exec('token', ['rm', tokens[0].key.slice(0, 8)]) t.equal(joinedOutput(), 'Removed 1 token') }) t.test('token revoke multiple tokens', async t => { - const { token, joinedOutput } = await mockToken(t, { - config: { registry: 'https://registry.npmjs.org' }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return { token: 'thisisnotarealtoken' } - }, - profile: { - listTokens: async () => ([{ key: 'abcd1234' }, { key: 'efgh5678' }]), - removeToken: async key => { - // this will run twice - t.ok(['abcd1234', 'efgh5678'].includes(key), 'deletes the correct token') - }, - }, + const { npm, joinedOutput } = await loadMockNpm(t, { + config: { ...auth }, + }) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: authToken, }) - await token.exec(['revoke', 'abcd', 'efgh']) + registry.getTokens(tokens) + registry.nock.delete(`/-/npm/v1/tokens/token/${tokens[0].key}`).reply(200) + registry.nock.delete(`/-/npm/v1/tokens/token/${tokens[1].key}`).reply(200) + await npm.exec('token', ['rm', tokens[0].key.slice(0, 8), tokens[1].key.slice(0, 8)]) t.equal(joinedOutput(), 'Removed 2 tokens') }) t.test('token revoke json output', async t => { - const { token, joinedOutput } = await mockToken(t, { - config: { registry: 'https://registry.npmjs.org', json: true }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return { token: 'thisisnotarealtoken' } - }, - profile: { - listTokens: async () => ([{ key: 'abcd1234' }]), - removeToken: async key => { - t.equal(key, 'abcd1234', 'deletes the correct token') - }, + const { npm, joinedOutput } = await loadMockNpm(t, { + config: { + ...auth, + json: true, }, - + }) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: authToken, }) - await token.exec(['delete', 'abcd']) + registry.getTokens(tokens) + registry.nock.delete(`/-/npm/v1/tokens/token/${tokens[0].key}`).reply(200) + await npm.exec('token', ['rm', tokens[0].key.slice(0, 8)]) const parsed = JSON.parse(joinedOutput()) - t.same(parsed, ['abcd1234'], 'logs the token as json') + t.same(parsed, [tokens[0].key], 'logs the token as json') }) t.test('token revoke parseable output', async t => { - const { token, joinedOutput } = await mockToken(t, { - config: { registry: 'https://registry.npmjs.org', parseable: true }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return { token: 'thisisnotarealtoken' } - }, - profile: { - listTokens: async () => ([{ key: 'abcd1234' }]), - removeToken: async key => { - t.equal(key, 'abcd1234', 'deletes the correct token') - }, + const { npm, joinedOutput } = await loadMockNpm(t, { + config: { + ...auth, + parseable: true, }, }) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: authToken, + }) - await token.exec(['remove', 'abcd']) - - t.equal(joinedOutput(), 'abcd1234', 'logs the token as a string') + registry.getTokens(tokens) + registry.nock.delete(`/-/npm/v1/tokens/token/${tokens[0].key}`).reply(200) + await npm.exec('token', ['rm', tokens[0].key.slice(0, 8)]) + t.equal(joinedOutput(), tokens[0].key, 'logs the token as a string') }) t.test('token revoke by token', async t => { - const { token, joinedOutput } = await mockToken(t, { - config: { registry: 'https://registry.npmjs.org' }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return { token: 'thisisnotarealtoken' } - }, - profile: { - listTokens: async () => ([{ key: 'abcd1234', token: 'efgh5678' }]), - removeToken: async key => { - t.equal(key, 'efgh5678', 'passes through user input') - }, - }, + const { npm, joinedOutput } = await loadMockNpm(t, { + config: { ...auth }, }) - - await token.exec(['rm', 'efgh5678']) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: authToken, + }) + registry.getTokens(tokens) + registry.nock.delete(`/-/npm/v1/tokens/token/${tokens[0].token}`).reply(200) + await npm.exec('token', ['rm', tokens[0].token]) t.equal(joinedOutput(), 'Removed 1 token') }) t.test('token revoke requires an id', async t => { - const { token } = await mockToken(t) + const { npm } = await loadMockNpm(t) - await t.rejects(token.exec(['rm']), /`` argument is required/) + await t.rejects(npm.exec('token', ['rm']), { + code: 'EUSAGE', + message: '`` argument is required', + }) }) t.test('token revoke ambiguous id errors', async t => { - const { token } = await mockToken(t, { - config: { registry: 'https://registry.npmjs.org' }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return { token: 'thisisnotarealtoken' } - }, - profile: { - listTokens: async () => ([{ key: 'abcd1234' }, { key: 'abcd5678' }]), - }, + const { npm } = await loadMockNpm(t, { + config: { ...auth }, + }) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: authToken, + }) + registry.getTokens(tokens) + await t.rejects(npm.exec('token', ['rm', 'abcd']), { + message: /Token ID "abcd" was ambiguous/, }) - - await t.rejects(token.exec(['rm', 'abcd']), /Token ID "abcd" was ambiguous/) }) -t.test('token revoke unknown id errors', async t => { - const { token } = await mockToken(t, { - config: { registry: 'https://registry.npmjs.org' }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return { token: 'thisisnotarealtoken' } - }, - profile: { - listTokens: async () => ([{ key: 'abcd1234' }]), - }, +t.test('token revoke unknown token', async t => { + const { npm } = await loadMockNpm(t, { + config: { ...auth }, + }) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: authToken, }) - await t.rejects(token.exec(['rm', 'efgh']), /Unknown token id or value "efgh"./) + registry.getTokens(tokens) + await t.rejects(npm.exec('token', ['rm', '0xnotreal']), + 'Unknown token id or value 0xnotreal' + ) }) t.test('token create', async t => { - const now = new Date().toISOString() - const password = 'thisisnotreallyapassword' - - const { token, joinedOutput } = await mockToken(t, { + const cidr = ['10.0.0.0/8', '192.168.1.0/24'] + const { npm, outputs } = await loadMockNpm(t, { config: { - registry: 'https://registry.npmjs.org', - cidr: ['10.0.0.0/8', '192.168.1.0/24'], - }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return { token: 'thisisnotarealtoken' } - }, - readUserInfo: { - password: () => Promise.resolve(password), + ...auth, + cidr, }, - profile: { - createToken: async (pw, readonly, cidr) => { - t.equal(pw, password) - t.equal(readonly, false) - t.same(cidr, ['10.0.0.0/8', '192.168.1.0/24'], 'defaults to empty array') - return { - key: 'abcd1234', - token: 'efgh5678', - created: now, - updated: now, - readonly: false, - cidr_whitelist: [], - } - }, - }, - }) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: authToken, + }) + const stdin = new stream.PassThrough() + stdin.write(`${password}\n`) + mockGlobals(t, { + 'process.stdin': stdin, + 'process.stdout': new stream.PassThrough(), // to quiet readline + }, { replace: true }) + registry.createToken({ password, cidr }) + await npm.exec('token', ['create']) + t.strictSame(outputs, [ + 'Created publish token n3wt0k3n', + 'with IP whitelist: 10.0.0.0/8,192.168.1.0/24', + ]) +}) - await token.exec(['create']) - - const lines = joinedOutput().split(/\r?\n/) - t.match(lines[1], 'token') - t.match(lines[1], 'efgh5678', 'prints the whole token') - t.match(lines[3], 'created') - t.match(lines[3], now, 'prints the correct timestamp') - t.match(lines[5], 'readonly') - t.match(lines[5], 'false', 'prints the readonly flag') - t.match(lines[7], 'cidr_whitelist') +t.test('token create read only', async t => { + const { npm, outputs } = await loadMockNpm(t, { + config: { + ...auth, + 'read-only': true, + }, + }) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: authToken, + }) + const stdin = new stream.PassThrough() + stdin.write(`${password}\n`) + mockGlobals(t, { + 'process.stdin': stdin, + 'process.stdout': new stream.PassThrough(), // to quiet readline + }, { replace: true }) + registry.createToken({ readonly: true, password }) + await npm.exec('token', ['create']) + t.strictSame(outputs, [ + 'Created read only token n3wt0k3n', + ]) }) t.test('token create json output', async t => { - const now = new Date().toISOString() - const password = 'thisisnotreallyapassword' - - const { token } = await mockToken(t, { - config: { registry: 'https://registry.npmjs.org', json: true }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return { token: 'thisisnotarealtoken' } - }, - readUserInfo: { - password: () => Promise.resolve(password), - }, - profile: { - createToken: async (pw, readonly, cidr) => { - t.equal(pw, password) - t.equal(readonly, false) - t.same(cidr, [], 'defaults to empty array') - return { - key: 'abcd1234', - token: 'efgh5678', - created: now, - updated: now, - readonly: false, - cidr_whitelist: [], - } - }, - }, - output: spec => { - t.type(spec, 'string', 'outputs a string') - const parsed = JSON.parse(spec) - t.same( - parsed, - { token: 'efgh5678', created: now, readonly: false, cidr_whitelist: [] }, - 'outputs the correct object' - ) + const cidr = ['10.0.0.0/8', '192.168.1.0/24'] + const { npm, joinedOutput } = await loadMockNpm(t, { + config: { + ...auth, + json: true, + cidr, }, }) - - await token.exec(['create']) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: authToken, + }) + const stdin = new stream.PassThrough() + stdin.write(`${password}\n`) + mockGlobals(t, { + 'process.stdin': stdin, + 'process.stdout': new stream.PassThrough(), // to quiet readline + }, { replace: true }) + registry.createToken({ password, cidr }) + await npm.exec('token', ['create']) + const parsed = JSON.parse(joinedOutput()) + t.match( + parsed, + { token: 'n3wt0k3n', readonly: false, cidr_whitelist: cidr } + ) + t.ok(parsed.created, 'also returns created') }) t.test('token create parseable output', async t => { - const now = new Date().toISOString() - const password = 'thisisnotreallyapassword' - - const { token, joinedOutput } = await mockToken(t, { - config: { registry: 'https://registry.npmjs.org', parseable: true }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return { token: 'thisisnotarealtoken' } - }, - readUserInfo: { - password: () => Promise.resolve(password), - }, - profile: { - createToken: async (pw, readonly, cidr) => { - t.equal(pw, password) - t.equal(readonly, false) - t.same(cidr, [], 'defaults to empty array') - return { - key: 'abcd1234', - token: 'efgh5678', - created: now, - updated: now, - readonly: false, - cidr_whitelist: [], - } - }, + const cidr = ['10.0.0.0/8', '192.168.1.0/24'] + const { npm, outputs } = await loadMockNpm(t, { + config: { + ...auth, + parseable: true, + cidr, }, }) - - await token.exec(['create']) - - const spec = joinedOutput().split(/\r?\n/) - - t.match(spec[0], 'token\tefgh5678', 'prints the token') - t.match(spec[1], `created\t${now}`, 'prints the created timestamp') - t.match(spec[2], 'readonly\tfalse', 'prints the readonly flag') - t.match(spec[3], 'cidr_whitelist\t', 'prints the cidr whitelist') + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: authToken, + }) + const stdin = new stream.PassThrough() + stdin.write(`${password}\n`) + mockGlobals(t, { + 'process.stdin': stdin, + 'process.stdout': new stream.PassThrough(), // to quiet readline + }, { replace: true }) + registry.createToken({ password, cidr }) + await npm.exec('token', ['create']) + t.equal(outputs[0], 'token\tn3wt0k3n') + t.ok(outputs[1].startsWith('created\t')) + t.equal(outputs[2], 'readonly\tfalse') + t.equal(outputs[3], 'cidr_whitelist\t10.0.0.0/8,192.168.1.0/24') }) t.test('token create ipv6 cidr', async t => { - const password = 'thisisnotreallyapassword' - - const { token } = await mockToken(t, { - config: { registry: 'https://registry.npmjs.org', cidr: '::1/128' }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return { token: 'thisisnotarealtoken' } - }, - readUserInfo: { - password: () => Promise.resolve(password), + const { npm } = await loadMockNpm(t, { + config: { + ...auth, + cidr: '::1/128', }, }) - - await t.rejects( - token.exec(['create']), - { - code: 'EINVALIDCIDR', - message: /CIDR whitelist can only contain IPv4 addresses, ::1\/128 is IPv6/, - }, - 'returns correct error' - ) + await t.rejects(npm.exec('token', ['create'], { + code: 'EINVALIDCIDR', + message: /CIDR whitelist can only contain IPv4 addresses, ::1\/128 is IPv6/, + })) }) t.test('token create invalid cidr', async t => { - const password = 'thisisnotreallyapassword' - - const { token } = await mockToken(t, { - config: { registry: 'https://registry.npmjs.org', cidr: 'apple/cider' }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return { token: 'thisisnotarealtoken' } - }, - readUserInfo: { - password: () => Promise.resolve(password), + const { npm } = await loadMockNpm(t, { + config: { + ...auth, + cidr: 'apple/cider', }, }) - - await t.rejects( - token.exec(['create']), - { code: 'EINVALIDCIDR', message: /CIDR whitelist contains invalid CIDR entry: apple\/cider/ }, - 'returns correct error' - ) + await t.rejects(npm.exec('token', ['create'], { + code: 'EINVALIDCIDR', + message: 'CIDR whitelist contains invalid CIDR entry: apple/cider', + })) })