diff options
author | Ruy Adorno <ruyadorno@hotmail.com> | 2021-02-05 02:15:54 +0300 |
---|---|---|
committer | Ruy Adorno <ruyadorno@hotmail.com> | 2021-02-05 17:45:09 +0300 |
commit | df4f65acc4ceaf15db4c227670e80f94584c055c (patch) | |
tree | 95556ad897f26c5ddbd74956499f10f57e0349c6 /node_modules | |
parent | 6f46b0f7fef9891e6de4af3547c70a67cb3a7a13 (diff) |
@npmcli/arborist@2.2.0
Diffstat (limited to 'node_modules')
-rw-r--r-- | node_modules/@npmcli/arborist/bin/actual.js | 21 | ||||
-rw-r--r-- | node_modules/@npmcli/arborist/bin/audit.js | 48 | ||||
-rw-r--r-- | node_modules/@npmcli/arborist/bin/funding.js | 32 | ||||
-rw-r--r-- | node_modules/@npmcli/arborist/bin/ideal.js | 68 | ||||
-rwxr-xr-x | node_modules/@npmcli/arborist/bin/index.js | 77 | ||||
-rw-r--r-- | node_modules/@npmcli/arborist/bin/lib/logging.js | 33 | ||||
-rw-r--r-- | node_modules/@npmcli/arborist/bin/lib/options.js | 49 | ||||
-rw-r--r-- | node_modules/@npmcli/arborist/bin/lib/print-tree.js | 5 | ||||
-rw-r--r-- | node_modules/@npmcli/arborist/bin/lib/timers.js | 22 | ||||
-rw-r--r-- | node_modules/@npmcli/arborist/bin/license.js | 34 | ||||
-rw-r--r-- | node_modules/@npmcli/arborist/bin/reify.js | 46 | ||||
-rw-r--r-- | node_modules/@npmcli/arborist/bin/shrinkwrap.js | 12 | ||||
-rw-r--r-- | node_modules/@npmcli/arborist/bin/virtual.js | 15 | ||||
-rw-r--r-- | node_modules/@npmcli/arborist/lib/arborist/reify.js | 2 | ||||
-rw-r--r-- | node_modules/@npmcli/arborist/lib/update-root-package-json.js | 12 | ||||
-rw-r--r-- | node_modules/@npmcli/arborist/package.json | 12 |
16 files changed, 482 insertions, 6 deletions
diff --git a/node_modules/@npmcli/arborist/bin/actual.js b/node_modules/@npmcli/arborist/bin/actual.js new file mode 100644 index 000000000..ef254e1d4 --- /dev/null +++ b/node_modules/@npmcli/arborist/bin/actual.js @@ -0,0 +1,21 @@ +const Arborist = require('../') +const print = require('./lib/print-tree.js') +const options = require('./lib/options.js') +require('./lib/logging.js') +require('./lib/timers.js') + +const start = process.hrtime() +new Arborist(options).loadActual(options).then(tree => { + const end = process.hrtime(start) + if (!process.argv.includes('--quiet')) + print(tree) + + console.error(`read ${tree.inventory.size} deps in ${end[0] * 1000 + end[1] / 1e6}ms`) + if (options.save) + tree.meta.save() + if (options.saveHidden) { + tree.meta.hiddenLockfile = true + tree.meta.filename = options.path + '/node_modules/.package-lock.json' + tree.meta.save() + } +}).catch(er => console.error(er)) diff --git a/node_modules/@npmcli/arborist/bin/audit.js b/node_modules/@npmcli/arborist/bin/audit.js new file mode 100644 index 000000000..5075724e2 --- /dev/null +++ b/node_modules/@npmcli/arborist/bin/audit.js @@ -0,0 +1,48 @@ +const Arborist = require('../') + +const print = require('./lib/print-tree.js') +const options = require('./lib/options.js') +require('./lib/timers.js') +require('./lib/logging.js') + +const Vuln = require('../lib/vuln.js') +const printReport = report => { + for (const vuln of report.values()) + console.log(printVuln(vuln)) + if (report.topVulns.size) { + console.log('\n# top-level vulnerabilities') + for (const vuln of report.topVulns.values()) + console.log(printVuln(vuln)) + } +} + +const printVuln = vuln => { + return { + __proto__: { constructor: Vuln }, + name: vuln.name, + issues: [...vuln.advisories].map(a => printAdvisory(a)), + range: vuln.simpleRange, + nodes: [...vuln.nodes].map(node => `${node.name} ${node.location || '#ROOT'}`), + ...(vuln.topNodes.size === 0 ? {} : { + topNodes: [...vuln.topNodes].map(node => `${node.location || '#ROOT'}`), + }), + } +} + +const printAdvisory = a => `${a.title}${a.url ? ' ' + a.url : ''}` + +const start = process.hrtime() +process.emit('time', 'audit script') +const arb = new Arborist(options) +arb.audit(options).then(tree => { + process.emit('timeEnd', 'audit script') + const end = process.hrtime(start) + if (options.fix) + print(tree) + if (!options.quiet) + printReport(arb.auditReport) + if (options.fix) + console.error(`resolved ${tree.inventory.size} deps in ${end[0] + end[1] / 1e9}s`) + if (tree.meta && options.save) + tree.meta.save() +}).catch(er => console.error(er)) diff --git a/node_modules/@npmcli/arborist/bin/funding.js b/node_modules/@npmcli/arborist/bin/funding.js new file mode 100644 index 000000000..fa1237e87 --- /dev/null +++ b/node_modules/@npmcli/arborist/bin/funding.js @@ -0,0 +1,32 @@ +const options = require('./lib/options.js') +require('./lib/logging.js') +require('./lib/timers.js') + +const Arborist = require('../') +const a = new Arborist(options) +const query = options._.shift() +const start = process.hrtime() +a.loadVirtual().then(tree => { + // only load the actual tree if the virtual one doesn't have modern metadata + if (!tree.meta || !(tree.meta.originalLockfileVersion >= 2)) { + console.error('old metadata, load actual') + throw 'load actual' + } else { + console.error('meta ok, return virtual tree') + return tree + } +}).catch(() => a.loadActual()).then(tree => { + const end = process.hrtime(start) + if (!query) { + for (const node of tree.inventory.values()) { + if (node.package.funding) + console.log(node.name, node.location, node.package.funding) + } + } else { + for (const node of tree.inventory.query('name', query)) { + if (node.package.funding) + console.log(node.name, node.location, node.package.funding) + } + } + console.error(`read ${tree.inventory.size} deps in ${end[0] * 1000 + end[1] / 1e6}ms`) +}) diff --git a/node_modules/@npmcli/arborist/bin/ideal.js b/node_modules/@npmcli/arborist/bin/ideal.js new file mode 100644 index 000000000..18a5b9eb3 --- /dev/null +++ b/node_modules/@npmcli/arborist/bin/ideal.js @@ -0,0 +1,68 @@ +const Arborist = require('../') + +const options = require('./lib/options.js') +const print = require('./lib/print-tree.js') +require('./lib/logging.js') +require('./lib/timers.js') + +const c = require('chalk') + +const whichIsA = (name, dependents, indent = ' ') => { + if (!dependents || dependents.length === 0) + return '' + const str = `\nfor: ` + + dependents.map(dep => { + return dep.more ? `${dep.more} more (${dep.names.join(', ')})` + : `${dep.type} dependency ` + + `${c.bold(name)}@"${c.bold(dep.spec)}"` + `\nfrom:` + + (dep.from.location ? (dep.from.name + ? ` ${c.bold(dep.from.name)}@${c.bold(dep.from.version)} ` + + c.dim(`at ${dep.from.location}`) + : ' the root project') + : ` ${c.bold(dep.from.name)}@${c.bold(dep.from.version)}`) + + whichIsA(dep.from.name, dep.from.dependents, ' ') + }).join('\nand: ') + + return str.split(/\n/).join(`\n${indent}`) +} + +const explainEresolve = ({ dep, current, peerConflict, fixWithForce }) => { + return (!dep.whileInstalling ? '' : `While resolving: ` + + `${c.bold(dep.whileInstalling.name)}@${c.bold(dep.whileInstalling.version)}\n`) + + + `Found: ` + + `${c.bold(current.name)}@${c.bold(current.version)} ` + + c.dim(`at ${current.location}`) + + `${whichIsA(current.name, current.dependents)}` + + + `\n\nCould not add conflicting dependency: ` + + `${c.bold(dep.name)}@${c.bold(dep.version)} ` + + c.dim(`at ${dep.location}`) + + `${whichIsA(dep.name, dep.dependents)}\n` + + + (!peerConflict ? '' : + `\nConflicting peer dependency: ` + + `${c.bold(peerConflict.name)}@${c.bold(peerConflict.version)} ` + + c.dim(`at ${peerConflict.location}`) + + `${whichIsA(peerConflict.name, peerConflict.dependents)}\n` + ) + + + `\nFix the upstream dependency conflict, or +run this command with --legacy-peer-deps${ + fixWithForce ? ' or --force' : ''} +to accept an incorrect (and potentially broken) dependency resolution. +` +} + +const start = process.hrtime() +new Arborist(options).buildIdealTree(options).then(tree => { + const end = process.hrtime(start) + print(tree) + console.error(`resolved ${tree.inventory.size} deps in ${end[0] + end[1] / 10e9}s`) + if (tree.meta && options.save) + tree.meta.save() +}).catch(er => { + console.error(er) + if (er.code === 'ERESOLVE') + console.error(explainEresolve(er)) +}) diff --git a/node_modules/@npmcli/arborist/bin/index.js b/node_modules/@npmcli/arborist/bin/index.js new file mode 100755 index 000000000..3cedc91d7 --- /dev/null +++ b/node_modules/@npmcli/arborist/bin/index.js @@ -0,0 +1,77 @@ +#!/usr/bin/env node +const [cmd] = process.argv.splice(2, 1) + +const usage = () => `Arborist - the npm tree doctor + +Version: ${require('../package.json').version} + +# USAGE + arborist <cmd> [path] [options...] + +# COMMANDS + +* reify: reify ideal tree to node_modules (install, update, rm, ...) +* ideal: generate and print the ideal tree +* actual: read and print the actual tree in node_modules +* virtual: read and print the virtual tree in the local shrinkwrap file +* shrinkwrap: load a local shrinkwrap and print its data +* audit: perform a security audit on project dependencies +* funding: query funding information in the local package tree. A second + positional argument after the path name can limit to a package name. +* license: query license information in the local package tree. A second + positional argument after the path name can limit to a license type. +* help: print this text + +# OPTIONS + +Most npm options are supported, but in camelCase rather than css-case. For +example, instead of '--dry-run', use '--dryRun'. + +Additionally: + +* --quiet will supppress the printing of package trees +* Instead of 'npm install <pkg>', use 'arborist reify --add=<pkg>'. + The '--add=<pkg>' option can be specified multiple times. +* Instead of 'npm rm <pkg>', use 'arborist reify --rm=<pkg>'. + The '--rm=<pkg>' option can be specified multiple times. +* Instead of 'npm update', use 'arborist reify --update-all'. +* 'npm audit fix' is 'arborist audit --fix' +` + +const help = () => console.log(usage()) + +switch (cmd) { + case 'actual': + require('./actual.js') + break + case 'virtual': + require('./virtual.js') + break + case 'ideal': + require('./ideal.js') + break + case 'reify': + require('./reify.js') + break + case 'audit': + require('./audit.js') + break + case 'funding': + require('./funding.js') + break + case 'license': + require('./license.js') + break + case 'shrinkwrap': + require('./shrinkwrap.js') + break + case 'help': + case '-h': + case '--help': + help() + break + default: + process.exitCode = 1 + console.error(usage()) + break +} diff --git a/node_modules/@npmcli/arborist/bin/lib/logging.js b/node_modules/@npmcli/arborist/bin/lib/logging.js new file mode 100644 index 000000000..57597b2e5 --- /dev/null +++ b/node_modules/@npmcli/arborist/bin/lib/logging.js @@ -0,0 +1,33 @@ +const options = require('./options.js') +const { quiet = false } = options +const { loglevel = quiet ? 'warn' : 'silly' } = options + +const levels = [ + 'silly', + 'verbose', + 'info', + 'timing', + 'http', + 'notice', + 'warn', + 'error', + 'silent', +] + +const levelMap = new Map(levels.reduce((set, level, index) => { + set.push([level, index], [index, level]) + return set +}, [])) + +const { inspect, format } = require('util') +if (loglevel !== 'silent') { + process.on('log', (level, ...args) => { + if (levelMap.get(level) < levelMap.get(loglevel)) + return + const pref = `${process.pid} ${level} ` + if (level === 'warn' && args[0] === 'ERESOLVE') + args[2] = inspect(args[2], { depth: Infinity }) + const msg = pref + format(...args).trim().split('\n').join(`\n${pref}`) + console.error(msg) + }) +} diff --git a/node_modules/@npmcli/arborist/bin/lib/options.js b/node_modules/@npmcli/arborist/bin/lib/options.js new file mode 100644 index 000000000..8f0dc2f12 --- /dev/null +++ b/node_modules/@npmcli/arborist/bin/lib/options.js @@ -0,0 +1,49 @@ +const options = module.exports = { + path: undefined, + cache: `${process.env.HOME}/.npm/_cacache`, + _: [], +} + +for (const arg of process.argv.slice(2)) { + if (/^--add=/.test(arg)) { + options.add = options.add || [] + options.add.push(arg.substr('--add='.length)) + } else if (/^--rm=/.test(arg)) { + options.rm = options.rm || [] + options.rm.push(arg.substr('--rm='.length)) + } else if (arg === '--global') + options.global = true + else if (arg === '--global-style') + options.globalStyle = true + else if (arg === '--prefer-dedupe') + options.preferDedupe = true + else if (arg === '--legacy-peer-deps') + options.legacyPeerDeps = true + else if (arg === '--force') + options.force = true + else if (arg === '--update-all') { + options.update = options.update || {} + options.update.all = true + } else if (/^--update=/.test(arg)) { + options.update = options.update || {} + options.update.names = options.update.names || [] + options.update.names.push(arg.substr('--update='.length)) + } else if (/^--omit=/.test(arg)) { + options.omit = options.omit || [] + options.omit.push(arg.substr('--omit='.length)) + } else if (/^--[^=]+=/.test(arg)) { + const [key, ...v] = arg.replace(/^--/, '').split('=') + const val = v.join('=') + options[key] = val === 'false' ? false : val === 'true' ? true : val + } else if (/^--.+/.test(arg)) + options[arg.replace(/^--/, '')] = true + else if (options.path === undefined) + options.path = arg + else + options._.push(arg) +} + +if (options.path === undefined) + options.path = '.' + +console.error(options) diff --git a/node_modules/@npmcli/arborist/bin/lib/print-tree.js b/node_modules/@npmcli/arborist/bin/lib/print-tree.js new file mode 100644 index 000000000..1ea2a7218 --- /dev/null +++ b/node_modules/@npmcli/arborist/bin/lib/print-tree.js @@ -0,0 +1,5 @@ +const { inspect } = require('util') +const { quiet } = require('./options.js') + +module.exports = quiet ? () => {} + : tree => console.log(inspect(tree.toJSON(), { depth: Infinity })) diff --git a/node_modules/@npmcli/arborist/bin/lib/timers.js b/node_modules/@npmcli/arborist/bin/lib/timers.js new file mode 100644 index 000000000..3b73c0bf6 --- /dev/null +++ b/node_modules/@npmcli/arborist/bin/lib/timers.js @@ -0,0 +1,22 @@ +const timers = Object.create(null) + +process.on('time', name => { + if (timers[name]) + throw new Error('conflicting timer! ' + name) + timers[name] = process.hrtime() +}) + +process.on('timeEnd', name => { + if (!timers[name]) + throw new Error('timer not started! ' + name) + const res = process.hrtime(timers[name]) + delete timers[name] + console.error(`${process.pid} ${name}`, res[0] * 1e3 + res[1] / 1e6) +}) + +process.on('exit', () => { + for (const name of Object.keys(timers)) { + console.error('Dangling timer: ', name) + process.exitCode = 1 + } +}) diff --git a/node_modules/@npmcli/arborist/bin/license.js b/node_modules/@npmcli/arborist/bin/license.js new file mode 100644 index 000000000..4083ddc69 --- /dev/null +++ b/node_modules/@npmcli/arborist/bin/license.js @@ -0,0 +1,34 @@ +const Arborist = require('../') +const options = require('./lib/options.js') +require('./lib/logging.js') +require('./lib/timers.js') + +const a = new Arborist(options) +const query = options._.shift() + +a.loadVirtual().then(tree => { + // only load the actual tree if the virtual one doesn't have modern metadata + if (!tree.meta || !(tree.meta.originalLockfileVersion >= 2)) + throw 'load actual' + else + return tree +}).catch((er) => { + console.error('loading actual tree', er) + return a.loadActual() +}).then(tree => { + if (!query) { + const set = [] + for (const license of tree.inventory.query('license')) + set.push([tree.inventory.query('license', license).size, license]) + + for (const [count, license] of set.sort((a, b) => + a[1] && b[1] ? b[0] - a[0] || a[1].localeCompare(b[1]) + : a[1] ? -1 + : b[1] ? 1 + : 0)) + console.log(count, license) + } else { + for (const node of tree.inventory.query('license', query === 'undefined' ? undefined : query)) + console.log(`${node.name} ${node.location} ${node.package.description || ''}`) + } +}) diff --git a/node_modules/@npmcli/arborist/bin/reify.js b/node_modules/@npmcli/arborist/bin/reify.js new file mode 100644 index 000000000..d17a0e03b --- /dev/null +++ b/node_modules/@npmcli/arborist/bin/reify.js @@ -0,0 +1,46 @@ +const Arborist = require('../') + +const options = require('./lib/options.js') +const print = require('./lib/print-tree.js') +require('./lib/logging.js') +require('./lib/timers.js') + +const printDiff = diff => { + const {depth} = require('treeverse') + depth({ + tree: diff, + visit: d => { + if (d.location === '') + return + switch (d.action) { + case 'REMOVE': + console.error('REMOVE', d.actual.location) + break + case 'ADD': + console.error('ADD', d.ideal.location, d.ideal.resolved) + break + case 'CHANGE': + console.error('CHANGE', d.actual.location, { + from: d.actual.resolved, + to: d.ideal.resolved, + }) + break + } + }, + getChildren: d => d.children, + }) +} + +const start = process.hrtime() +process.emit('time', 'install') +const arb = new Arborist(options) +arb.reify(options).then(tree => { + process.emit('timeEnd', 'install') + const end = process.hrtime(start) + print(tree) + if (options.dryRun) + printDiff(arb.diff) + console.error(`resolved ${tree.inventory.size} deps in ${end[0] + end[1] / 1e9}s`) + if (tree.meta && options.save) + tree.meta.save() +}).catch(er => console.error(require('util').inspect(er, { depth: Infinity }))) diff --git a/node_modules/@npmcli/arborist/bin/shrinkwrap.js b/node_modules/@npmcli/arborist/bin/shrinkwrap.js new file mode 100644 index 000000000..ee5ec2455 --- /dev/null +++ b/node_modules/@npmcli/arborist/bin/shrinkwrap.js @@ -0,0 +1,12 @@ +const Shrinkwrap = require('../lib/shrinkwrap.js') +const options = require('./lib/options.js') +require('./lib/logging.js') +require('./lib/timers.js') + +const { quiet } = options +Shrinkwrap.load(options) + .then(s => quiet || console.log(JSON.stringify(s.data, 0, 2))) + .catch(er => { + console.error('shrinkwrap load failure', er) + process.exit(1) + }) diff --git a/node_modules/@npmcli/arborist/bin/virtual.js b/node_modules/@npmcli/arborist/bin/virtual.js new file mode 100644 index 000000000..7f90f20cf --- /dev/null +++ b/node_modules/@npmcli/arborist/bin/virtual.js @@ -0,0 +1,15 @@ +const Arborist = require('../') + +const print = require('./lib/print-tree.js') +const options = require('./lib/options.js') +require('./lib/logging.js') +require('./lib/timers.js') + +const start = process.hrtime() +new Arborist(options).loadVirtual().then(tree => { + const end = process.hrtime(start) + print(tree) + if (options.save) + tree.meta.save() + console.error(`read ${tree.inventory.size} deps in ${end[0] * 1000 + end[1] / 1e6}ms`) +}).catch(er => console.error(er)) diff --git a/node_modules/@npmcli/arborist/lib/arborist/reify.js b/node_modules/@npmcli/arborist/lib/arborist/reify.js index 6cc129a7c..1dd4b4b0f 100644 --- a/node_modules/@npmcli/arborist/lib/arborist/reify.js +++ b/node_modules/@npmcli/arborist/lib/arborist/reify.js @@ -907,7 +907,7 @@ module.exports = cls => class Reifier extends cls { return Promise.all([ this[_saveLockFile](saveOpt), - updateRootPackageJson({ tree: this.idealTree }), + updateRootPackageJson(this.idealTree), ]).then(() => process.emit('timeEnd', 'reify:save')) } diff --git a/node_modules/@npmcli/arborist/lib/update-root-package-json.js b/node_modules/@npmcli/arborist/lib/update-root-package-json.js index f5d62f7a5..735ebd10a 100644 --- a/node_modules/@npmcli/arborist/lib/update-root-package-json.js +++ b/node_modules/@npmcli/arborist/lib/update-root-package-json.js @@ -15,7 +15,7 @@ const depTypes = new Set([ 'peerDependencies', ]) -async function updateRootPackageJson ({ tree }) { +const updateRootPackageJson = async tree => { const filename = resolve(tree.path, 'package.json') const originalContent = await readFile(filename, 'utf8') .then(data => parseJSON(data)) @@ -25,6 +25,16 @@ async function updateRootPackageJson ({ tree }) { ...tree.package, }) + // optionalDependencies don't need to be repeated in two places + if (depsData.dependencies) { + if (depsData.optionalDependencies) { + for (const name of Object.keys(depsData.optionalDependencies)) + delete depsData.dependencies[name] + } + if (Object.keys(depsData.dependencies).length === 0) + delete depsData.dependencies + } + // if there's no package.json, just use internal pkg info as source of truth const packageJsonContent = originalContent || depsData diff --git a/node_modules/@npmcli/arborist/package.json b/node_modules/@npmcli/arborist/package.json index 2107652c6..fa2f18493 100644 --- a/node_modules/@npmcli/arborist/package.json +++ b/node_modules/@npmcli/arborist/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/arborist", - "version": "2.1.1", + "version": "2.2.0", "description": "Manage node_modules trees", "dependencies": { "@npmcli/installed-package-contents": "^1.0.5", @@ -20,7 +20,7 @@ "npm-package-arg": "^8.1.0", "npm-pick-manifest": "^6.1.0", "npm-registry-fetch": "^9.0.0", - "pacote": "^11.2.4", + "pacote": "^11.2.5", "parse-conflict-json": "^1.1.1", "promise-all-reject-late": "^1.0.0", "promise-call-limit": "^1.0.1", @@ -55,7 +55,7 @@ "postversion": "npm publish", "prepublishOnly": "git push origin --follow-tags", "eslint": "eslint", - "lint": "npm run eslint -- \"lib/**/*.js\" \"test/arborist/*.js\" \"test/*.js\"", + "lint": "npm run eslint -- \"lib/**/*.js\" \"test/arborist/*.js\" \"test/*.js\" \"bin/**/*.js\"", "lintfix": "npm run lint -- --fix", "benchmark": "node scripts/benchmark.js", "benchclean": "rm -rf scripts/benchmark/*/" @@ -67,9 +67,13 @@ "author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)", "license": "ISC", "files": [ - "lib/**/*.js" + "lib/**/*.js", + "bin/**/*.js" ], "main": "lib/index.js", + "bin": { + "arborist": "bin/index.js" + }, "tap": { "100": true, "node-arg": [ |