npm-logical-tree
is a Node.js
library that takes the contents of a package.json
and package-lock.json
(or
npm-shrinkwrap.json
) and returns a nested tree data structure representing the
logical relationships between the different dependencies.
$ npm install npm-logical-tree
const fs = require('fs')
const logicalTree = require('npm-logical-tree')
const pkg = require('./package.json')
const pkgLock = require('./package-lock.json')
logicalTree(pkg, pkgLock)
// returns:
LogicalTree {
name: 'npm-logical-tree',
version: '1.0.0',
address: null,
optional: false,
dev: false,
bundled: false,
resolved: undefined,
integrity: undefined,
requiredBy: Set { },
dependencies:
Map {
'foo' => LogicalTree {
name: 'foo',
version: '1.2.3',
address: 'foo',
optional: false,
dev: true,
bundled: false,
resolved: 'https://registry.npmjs.org/foo/-/foo-1.2.3.tgz',
integrity: 'sha1-rYUK/p261/SXByi0suR/7Rw4chw=',
dependencies: Map { ... },
requiredBy: Set { ... },
},
...
}
}
The npm team enthusiastically welcomes contributions and project participation! There's a bunch of things you can do if you want to contribute! The Contributor Guide has all the information you need for everything from reporting bugs to contributing entire new features. Please don't hesitate to jump in if you'd like to, or even ask us questions if something isn't clear.
All participants and maintainers in this project are expected to follow Code of Conduct, and just generally be excellent to each other.
Please refer to the Changelog for project history details, too.
Happy hacking!
Calculates a logical tree based on a matching package.json
and
package-lock.json
pair. A "logical tree" is a fully-nested dependency graph
for an npm package, as opposed to a physical tree which might be flattened.
logical-tree
will represent deduplicated/flattened nodes using the same object
throughout the tree, so duplication can be checked by object identity.
const pkg = require('./package.json')
const pkgLock = require('./package-lock.json')
logicalTree(pkg, pkgLock)
// returns:
LogicalTree {
name: 'npm-logical-tree',
version: '1.0.0',
address: null,
optional: false,
dev: false,
bundled: false,
resolved: undefined,
integrity: undefined,
requiredBy: Set { },
dependencies:
Map {
'foo' => LogicalTree {
name: 'foo',
version: '1.2.3',
address: 'foo',
optional: false,
dev: true,
bundled: false,
resolved: 'https://registry.npmjs.org/foo/-/foo-1.2.3.tgz',
integrity: 'sha1-rYUK/p261/SXByi0suR/7Rw4chw=',
requiredBy: Set { ... },
dependencies: Map { ... }
},
...
}
}
Manually creates a new LogicalTree node.
opts.version
- version of the node.opts.optional
- is this node an optionalDep?opts.dev
- is this node a devDep?opts.bundled
- is this bundled?opts.resolved
- resolved address.opts.integrity
- SRI string.
logicalTree.node('hello', 'subpath:to:@foo/bar', {dev: true})
Boolean value indicating whether the tree (node) is the root node or not.
tree.isRoot // true
Adds a logical dependency (such as one created by tree.node
) to the tree's dependencies
map. Returns the logicalTree instance.
const node = logicalTree.node('hello', 'hello')
tree.addDep(node)
Deletes a logical dependency from the tree's dependencies
map. Returns the tree instance.
const node = logicalTree.getDep('hello')
tree.delDep(node)
Returns a logical dependency from the tree's dependencies
map.
const node = logicalTree.getDep('hello')
Returns the physical path of the node. An optional prefix (eg. in order to receive an absolute path) can be provided.
const node = logicalTree.getDep('hello')
node.path()
// node_modules/foo/node_modules/bar/node_modules/hello
node.path('/home/myHomeFolder/moduleName/')
// /home/myHomeFolder/moduleName/node_modules/foo/node_modules/bar/node_modules/hello
Returns true if there is a dependency cycle including the current node. Will not check if there is an internal 'unrelated' cycle within the node's children.
const a = logicalTree.getDep('a')
const a.hasCycle() // true
// a ===depends-on===> b ===depends-on===> c ===depends-on===> a
Executes fn
once for each node in the tree.
fn
receives the node object and a cb
to call when it is done.
let flattened = {}
logicalTree.forEach((node, cb) => {
const path = node.path()
flattened[path] = node
cb()
})
Returns a Promise
resolved once fn
is executed asynchronously for every node in the tree.
fn
receives the node object and a cb
to call when it is done.
fn
is expected to return a Promise
, and indeed cb
here returns a Promise
as well.
opts.Promise
- customPromise
implementation
let manifests = {}
await logicalTree.forEach(async (node, cb) => {
const path = node.path()
manifests[path] = await pacote.manifest(`${node.name}@${node.version}`)
await cb()
})
console.log('Yay, we are done!')