resolve-tree

Recursively resolve node.js modules and its dependencies looking in node_modules trees

Usage no npm install needed!

<script type="module">
  import resolveTree from 'https://cdn.skypack.dev/resolve-tree';
</script>

README

resolve-tree Build Status Code Climate NPM js-standard-style

Recursively resolve node.js modules and its dependencies looking in node_modules trees.

The module resolution algorithm behavies like require.resolve in node.js. It also mimics the recursive module resolution behavior used by npm.

Features

  • Recursively resolves a node_modules dependency tree
  • Proper error reporting if some package cannot be resolved or is missing
  • Detects repeated and circular dependencies across nested dependency trees.
  • Module lookup algorithm behavies like require.resolve
  • Produces a detailed abstract dependency tree representation
  • Provides convenient helpers that you will love
  • Almost dependency free (only uses some stable tiny modules)
  • Fast: all the I/O operations are executed asynchronously in parallel

Not supported yet

  • Semantic version operator based resolution

Installation

npm install resolve-tree

Usage

const resolve = require('resolve-tree')

// Names of the packages to resolve
const names = ['foo', 'bar']

// Custom optional params for the resolution
const opts = {
  basedir: process.cwd(),
  lookups: ['dependencies', 'devDependencies']
}

resolve.packages(names, opts, function (err, tree) {
  if (err) return console.error(err)

  const json = JSON.stringify(tree, null, 2)
  console.log(json)
})

The resolved dependency tree serialized to JSON looks like this:

[{
  "name": "foo",
  "manifest": "/Users/h2non/Projects/resolve-tree/fixtures/simple/node_modules/foo/package.json",
  "basedir": "/Users/h2non/Projects/resolve-tree/fixtures/simple",
  "main": "/Users/h2non/Projects/resolve-tree/fixtures/simple/node_modules/foo/index.js",
  "root": "/Users/h2non/Projects/resolve-tree/fixtures/simple/node_modules/foo",
  "version": "0.1.0",
  "meta": {
    "name": "foo",
    "dependencies": {
      "baz": "~0.1.0",
      "bar": "~0.1.0",
      "quz": "~0.1.0"
    }
  },
  "dependencies": [{
    "name": "baz",
    "manifest": "/Users/h2non/Projects/resolve-tree/fixtures/simple/node_modules/baz/package.json",
    "basedir": "/Users/h2non/Projects/resolve-tree/fixtures/simple/node_modules/foo",
    "main": "/Users/h2non/Projects/resolve-tree/fixtures/simple/node_modules/baz/index.js",
    "root": "/Users/h2non/Projects/resolve-tree/fixtures/simple/node_modules/baz",
    "version": "0.1.0",
    "meta": {
      "name": "baz"
    }
  }, {
    "name": "bar",
    "manifest": "/Users/h2non/Projects/resolve-tree/fixtures/simple/node_modules/bar/package.json",
    "basedir": "/Users/h2non/Projects/resolve-tree/fixtures/simple/node_modules/foo",
    "main": "/Users/h2non/Projects/resolve-tree/fixtures/simple/node_modules/bar/index.js",
    "root": "/Users/h2non/Projects/resolve-tree/fixtures/simple/node_modules/bar",
    "version": "0.1.0",
    "meta": {
      "name": "bar",
      "dependencies": {
        "baz": "~0.1.0"
      }
    },
    "dependencies": [{
      "name": "baz",
      "manifest": "/Users/h2non/Projects/resolve-tree/fixtures/simple/node_modules/baz/package.json",
      "basedir": "/Users/h2non/Projects/resolve-tree/fixtures/simple/node_modules/bar",
      "main": "/Users/h2non/Projects/resolve-tree/fixtures/simple/node_modules/baz/index.js",
      "root": "/Users/h2non/Projects/resolve-tree/fixtures/simple/node_modules/baz",
      "version": "0.1.0",
      "meta": {
        "name": "baz"
      }
    }]
  }, {
    "name": "quz",
    "manifest": "/Users/h2non/Projects/resolve-tree/fixtures/simple/node_modules/foo/node_modules/quz/package.json",
    "basedir": "/Users/h2non/Projects/resolve-tree/fixtures/simple/node_modules/foo",
    "main": "/Users/h2non/Projects/resolve-tree/fixtures/simple/node_modules/foo/node_modules/quz/index.js",
    "root": "/Users/h2non/Projects/resolve-tree/fixtures/simple/node_modules/foo/node_modules/quz",
    "version": "0.1.0",
    "meta": {
      "name": "quz",
      "dependencies": {
        "baz": "~0.0.1"
      }
    },
    "dependencies": [{
      "name": "baz",
      "manifest": "/Users/h2non/Projects/resolve-tree/fixtures/simple/node_modules/foo/node_modules/quz/node_modules/baz/package.json",
      "basedir": "/Users/h2non/Projects/resolve-tree/fixtures/simple/node_modules/foo/node_modules/quz",
      "main": "/Users/h2non/Projects/resolve-tree/fixtures/simple/node_modules/foo/node_modules/quz/node_modules/baz/index.js",
      "root": "/Users/h2non/Projects/resolve-tree/fixtures/simple/node_modules/foo/node_modules/quz/node_modules/baz",
      "version": "0.1.0",
      "meta": {
        "name": "baz",
        "version": "0.0.1"
      }
    }]
  }]
}]

API

Supported options

  • basedir string - Base directory path to start lookups. Default to process.cwd().
  • lookups array<string> - Dependency types to lookup. Allowed values are: dependencies, devDependencies, peerDependencies. Defaults to: dependencies

resolve.packages(names, [ opts, ] cb)

Alias: byName()

Find and resolve modules and its dependencies recursively looking by package name.

resolve.manifest(pkgManifest, [ opts, ] cb)

Resolve dependencies recursively reading the package.json metadata.

resolve.flatten(tree) => array<pkg>

Flatten dependency tree to one level structure tree.

resolve.flattenMap(tree, [ field ]) => array<mixed>

Flatten the given dependency tree mapping by dependency value field or custom mapper function.

resolve.resolutions = object

Map of packages resolution mappings.

{
  'mz': 'mz/fs'
}

resolve.packagesSync(names, [ opts ])

Alias: byNameSync

Synchronous version of packages. Find and resolve modules and its dependencies recursively looking by package name.

resolve.manifestSync(pkgManifest, [ opts ])

Synchronous version of manifest. Resolve dependencies recursively reading the package.json metadata.

License

MIT - Tomas Aparicio