const { explainNode } = require('../utils/explain-dep.js') const completion = require('../utils/completion/installed-deep.js') const Arborist = require('@npmcli/arborist') const npa = require('npm-package-arg') const semver = require('semver') const { relative, resolve } = require('path') const validName = require('validate-npm-package-name') const ArboristWorkspaceCmd = require('../arborist-cmd.js') class Explain extends ArboristWorkspaceCmd { static description = 'Explain installed packages' static name = 'explain' static usage = ['<package-spec>'] static params = [ 'json', 'workspace', ] static ignoreImplicitWorkspace = false // TODO /* istanbul ignore next */ async completion (opts) { return completion(this.npm, opts) } async exec (args) { if (!args.length) { throw this.usageError() } const arb = new Arborist({ path: this.npm.prefix, ...this.npm.flatOptions }) const tree = await arb.loadActual() if (this.npm.flatOptions.workspacesEnabled && this.workspaceNames && this.workspaceNames.length ) { this.filterSet = arb.workspaceDependencySet(tree, this.workspaceNames) } else if (!this.npm.flatOptions.workspacesEnabled) { this.filterSet = arb.excludeWorkspacesDependencySet(tree) } const nodes = new Set() for (const arg of args) { for (const node of this.getNodes(tree, arg)) { const filteredOut = this.filterSet && this.filterSet.size > 0 && !this.filterSet.has(node) if (!filteredOut) { nodes.add(node) } } } if (nodes.size === 0) { throw new Error(`No dependencies found matching ${args.join(', ')}`) } const expls = [] for (const node of nodes) { const { extraneous, dev, optional, devOptional, peer, inBundle, overridden } = node const expl = node.explain() if (extraneous) { expl.extraneous = true } else { expl.dev = dev expl.optional = optional expl.devOptional = devOptional expl.peer = peer expl.bundled = inBundle expl.overridden = overridden } expls.push(expl) } if (this.npm.flatOptions.json) { this.npm.output(JSON.stringify(expls, null, 2)) } else { this.npm.output(expls.map(expl => { return explainNode(expl, Infinity, this.npm.color) }).join('\n\n')) } } getNodes (tree, arg) { // if it's just a name, return packages by that name const { validForOldPackages: valid } = validName(arg) if (valid) { return tree.inventory.query('packageName', arg) } // if it's a location, get that node const maybeLoc = arg.replace(/\\/g, '/').replace(/\/+$/, '') const nodeByLoc = tree.inventory.get(maybeLoc) if (nodeByLoc) { return [nodeByLoc] } // maybe a path to a node_modules folder const maybePath = relative(this.npm.prefix, resolve(maybeLoc)) .replace(/\\/g, '/').replace(/\/+$/, '') const nodeByPath = tree.inventory.get(maybePath) if (nodeByPath) { return [nodeByPath] } // otherwise, try to select all matching nodes try { return this.getNodesByVersion(tree, arg) } catch (er) { return [] } } getNodesByVersion (tree, arg) { const spec = npa(arg, this.npm.prefix) if (spec.type !== 'version' && spec.type !== 'range') { return [] } return tree.inventory.filter(node => { return node.package.name === spec.name && semver.satisfies(node.package.version, spec.rawSpec) }) } } module.exports = Explain
Name | Type | Size | Permission | Actions |
---|---|---|---|---|
access.js | File | 5.45 KB | 0644 |
|
adduser.js | File | 2.2 KB | 0644 |
|
audit.js | File | 11.95 KB | 0644 |
|
bin.js | File | 729 B | 0644 |
|
birthday.js | File | 508 B | 0644 |
|
bugs.js | File | 815 B | 0644 |
|
cache.js | File | 7.08 KB | 0644 |
|
ci.js | File | 3.63 KB | 0644 |
|
completion.js | File | 8.91 KB | 0644 |
|
config.js | File | 8.11 KB | 0644 |
|
dedupe.js | File | 1.37 KB | 0644 |
|
deprecate.js | File | 2.06 KB | 0644 |
|
diff.js | File | 8.1 KB | 0644 |
|
dist-tag.js | File | 5.47 KB | 0644 |
|
docs.js | File | 447 B | 0644 |
|
doctor.js | File | 9.22 KB | 0644 |
|
edit.js | File | 2 KB | 0644 |
|
exec.js | File | 2.44 KB | 0644 |
|
explain.js | File | 3.55 KB | 0644 |
|
explore.js | File | 2.33 KB | 0644 |
|
find-dupes.js | File | 602 B | 0644 |
|
fund.js | File | 6.37 KB | 0644 |
|
get.js | File | 524 B | 0644 |
|
help-search.js | File | 5.62 KB | 0644 |
|
help.js | File | 4.53 KB | 0644 |
|
hook.js | File | 3.93 KB | 0644 |
|
init.js | File | 6.81 KB | 0644 |
|
install-ci-test.js | File | 377 B | 0644 |
|
install-test.js | File | 374 B | 0644 |
|
install.js | File | 5.11 KB | 0644 |
|
link.js | File | 5.02 KB | 0644 |
|
ll.js | File | 234 B | 0644 |
|
logout.js | File | 1.34 KB | 0644 |
|
ls.js | File | 16.94 KB | 0644 |
|
org.js | File | 4.2 KB | 0644 |
|
outdated.js | File | 8.84 KB | 0644 |
|
owner.js | File | 5.88 KB | 0644 |
|
pack.js | File | 2.36 KB | 0644 |
|
ping.js | File | 874 B | 0644 |
|
pkg.js | File | 3.47 KB | 0644 |
|
prefix.js | File | 343 B | 0644 |
|
profile.js | File | 11.25 KB | 0644 |
|
prune.js | File | 779 B | 0644 |
|
publish.js | File | 6.33 KB | 0644 |
|
query.js | File | 2.81 KB | 0644 |
|
rebuild.js | File | 2.16 KB | 0644 |
|
repo.js | File | 1.24 KB | 0644 |
|
restart.js | File | 351 B | 0644 |
|
root.js | File | 298 B | 0644 |
|
run-script.js | File | 6.9 KB | 0644 |
|
search.js | File | 2.72 KB | 0644 |
|
set-script.js | File | 2.63 KB | 0644 |
|
set.js | File | 572 B | 0644 |
|
shrinkwrap.js | File | 2.64 KB | 0644 |
|
star.js | File | 1.87 KB | 0644 |
|
stars.js | File | 1.03 KB | 0644 |
|
start.js | File | 341 B | 0644 |
|
stop.js | File | 336 B | 0644 |
|
team.js | File | 4.44 KB | 0644 |
|
test.js | File | 336 B | 0644 |
|
token.js | File | 6.79 KB | 0644 |
|
uninstall.js | File | 1.52 KB | 0644 |
|
unpublish.js | File | 4.51 KB | 0644 |
|
unstar.js | File | 182 B | 0644 |
|
update.js | File | 1.7 KB | 0644 |
|
version.js | File | 3.6 KB | 0644 |
|
view.js | File | 14.38 KB | 0644 |
|
whoami.js | File | 514 B | 0644 |
|